From db334931f564694de4481552600636e600562c26 Mon Sep 17 00:00:00 2001 From: Damian Edwards Date: Sat, 11 May 2019 21:21:32 -0700 Subject: [PATCH 01/56] Initial migration to 3.0 --- src/BackEnd/BackEnd.csproj | 14 ++++----- src/BackEnd/Program.cs | 16 +++++----- src/BackEnd/Startup.cs | 26 ++++++++-------- src/ConferenceDTO/SessionResponse.cs | 4 +-- .../Areas/Identity/IdentityHostingStartup.cs | 1 - src/FrontEnd/FrontEnd.csproj | 15 ++++++---- src/FrontEnd/Program.cs | 23 ++++++-------- src/FrontEnd/Properties/launchSettings.json | 4 +-- src/FrontEnd/Startup.cs | 30 +++++++++---------- src/FrontEnd/appsettings.Development.json | 2 +- src/FrontEnd/appsettings.json | 5 ++-- 11 files changed, 69 insertions(+), 71 deletions(-) diff --git a/src/BackEnd/BackEnd.csproj b/src/BackEnd/BackEnd.csproj index 48d2bf6d..1872672c 100644 --- a/src/BackEnd/BackEnd.csproj +++ b/src/BackEnd/BackEnd.csproj @@ -1,17 +1,17 @@  - netcoreapp2.2 + netcoreapp3.0 aspnet-BackEnd-931E56BD-86CB-4A96-BD99-2C6A6ABB0829 - InProcess - - - - - + + + + + + diff --git a/src/BackEnd/Program.cs b/src/BackEnd/Program.cs index 275a06cb..c1a4242e 100644 --- a/src/BackEnd/Program.cs +++ b/src/BackEnd/Program.cs @@ -1,5 +1,5 @@ -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; namespace BackEnd { @@ -7,12 +7,14 @@ public class Program { public static void Main(string[] args) { - CreateWebHostBuilder(args).Build().Run(); + CreateHostBuilder(args).Build().Run(); } - public static IWebHostBuilder CreateWebHostBuilder(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup(); - + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webHostBuilder => + { + webHostBuilder.UseStartup(); + }); } } diff --git a/src/BackEnd/Startup.cs b/src/BackEnd/Startup.cs index f552fac7..826a0071 100644 --- a/src/BackEnd/Startup.cs +++ b/src/BackEnd/Startup.cs @@ -9,8 +9,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Swashbuckle.AspNetCore.Swagger; +using Microsoft.Extensions.Hosting; using BackEnd.Data; +using Microsoft.OpenApi.Models; [assembly: ApiConventionType(typeof(DefaultApiConventions))] @@ -39,34 +40,29 @@ public void ConfigureServices(IServiceCollection services) } }); - services.AddMvc() - .SetCompatibilityVersion(CompatibilityVersion.Version_2_2); + services.AddControllers() + .AddNewtonsoftJson() + .SetCompatibilityVersion(CompatibilityVersion.Version_3_0); services.AddHealthChecks() .AddDbContextCheck(); services.AddSwaggerGen(options => { - options.SwaggerDoc("v1", new Info { Title = "Conference Planner API", Version = "v1" }); + options.SwaggerDoc("v1", new OpenApiInfo { Title = "Conference Planner API", Version = "v1" }); }); } - public void Configure(IApplicationBuilder app, IHostingEnvironment env) + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseDatabaseErrorPage(); } - else - { - app.UseHsts(); - } app.UseHttpsRedirection(); - app.UseHealthChecks("/health"); - app.UseSwagger(); app.UseSwaggerUI(options => @@ -74,8 +70,14 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env) options.SwaggerEndpoint("/swagger/v1/swagger.json", "Conference Planner API v1"); }); - app.UseMvc(); + app.UseRouting(); + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + endpoints.MapHealthChecks("/health"); + }); + app.Run(context => { context.Response.Redirect("/swagger"); diff --git a/src/ConferenceDTO/SessionResponse.cs b/src/ConferenceDTO/SessionResponse.cs index ee4086c4..432a4ae8 100644 --- a/src/ConferenceDTO/SessionResponse.cs +++ b/src/ConferenceDTO/SessionResponse.cs @@ -8,8 +8,8 @@ public class SessionResponse : Session { public Track Track { get; set; } - public ICollection Speakers { get; set; } = new List(); + public List Speakers { get; set; } = new List(); - public ICollection Tags { get; set; } = new List(); + public List Tags { get; set; } = new List(); } } diff --git a/src/FrontEnd/Areas/Identity/IdentityHostingStartup.cs b/src/FrontEnd/Areas/Identity/IdentityHostingStartup.cs index f4631b10..1de6d719 100644 --- a/src/FrontEnd/Areas/Identity/IdentityHostingStartup.cs +++ b/src/FrontEnd/Areas/Identity/IdentityHostingStartup.cs @@ -38,7 +38,6 @@ public void Configure(IWebHostBuilder builder) options.Password.RequireUppercase = false; options.Password.RequireNonAlphanumeric = false; }) - .AddDefaultUI(UIFramework.Bootstrap4) .AddEntityFrameworkStores() .AddClaimsPrincipalFactory(); }); diff --git a/src/FrontEnd/FrontEnd.csproj b/src/FrontEnd/FrontEnd.csproj index 4493e86e..30eae296 100644 --- a/src/FrontEnd/FrontEnd.csproj +++ b/src/FrontEnd/FrontEnd.csproj @@ -1,16 +1,19 @@  - netcoreapp2.2 + netcoreapp3.0 aspnet-FrontEnd-18BDC1FA-5BA8-408A-BC82-D8DB0496B86B - InProcess - - - - + + + + + + + + diff --git a/src/FrontEnd/Program.cs b/src/FrontEnd/Program.cs index d62567da..34f58c29 100644 --- a/src/FrontEnd/Program.cs +++ b/src/FrontEnd/Program.cs @@ -1,13 +1,5 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using FrontEnd.Infrastructure; -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; namespace FrontEnd { @@ -15,11 +7,14 @@ public class Program { public static void Main(string[] args) { - CreateWebHostBuilder(args).Build().Run(); + CreateHostBuilder(args).Build().Run(); } - public static IWebHostBuilder CreateWebHostBuilder(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup(); + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webHostBuilder => + { + webHostBuilder.UseStartup(); + }); } } \ No newline at end of file diff --git a/src/FrontEnd/Properties/launchSettings.json b/src/FrontEnd/Properties/launchSettings.json index 1aff78df..d7e1ee66 100644 --- a/src/FrontEnd/Properties/launchSettings.json +++ b/src/FrontEnd/Properties/launchSettings.json @@ -12,14 +12,12 @@ "commandName": "IISExpress", "launchBrowser": true, "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development", - "AASPNETCORE_HTTPS_PORT": "44374" + "ASPNETCORE_ENVIRONMENT": "Development" } }, "FrontEnd": { "commandName": "Project", "launchBrowser": true, - "launchUrl": "", "applicationUrl": "https://localhost:44374;http://localhost:55994", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" diff --git a/src/FrontEnd/Startup.cs b/src/FrontEnd/Startup.cs index 6270aa0a..c69019cf 100644 --- a/src/FrontEnd/Startup.cs +++ b/src/FrontEnd/Startup.cs @@ -1,14 +1,13 @@ using System; -using System.Security.Claims; using FrontEnd.Data; using FrontEnd.HealthChecks; using FrontEnd.Services; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; namespace FrontEnd { @@ -39,15 +38,15 @@ public void ConfigureServices(IServiceCollection services) client.BaseAddress = new Uri(Configuration["serviceUrl"]); }); - services.AddMvc(options => + services.AddRazorPages(options => { - options.Filters.AddService(); + options.Conventions.AuthorizeFolder("/Admin", "Admin"); }) - .AddRazorPagesOptions(options => + .AddMvcOptions(options => { - options.Conventions.AuthorizeFolder("/Admin", "Admin"); + options.Filters.AddService(); }) - .SetCompatibilityVersion(CompatibilityVersion.Version_2_2); + .SetCompatibilityVersion(CompatibilityVersion.Version_3_0); services.AddHealthChecks() .AddCheck("backend") @@ -56,7 +55,7 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(); } - public void Configure(IApplicationBuilder app, IHostingEnvironment env) + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { @@ -69,21 +68,20 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env) app.UseHsts(); } - app.UseStatusCodePagesWithReExecute("/Status/{0}"); + //app.UseStatusCodePagesWithReExecute("/Status/{0}"); app.UseHttpsRedirection(); - app.UseStaticFiles(); - app.UseAuthentication(); + app.UseRouting(); - app.UseHealthChecks("/health"); + app.UseAuthentication(); + app.UseAuthorization(); - app.UseMvc(routes => + app.UseEndpoints(endpoints => { - routes.MapRoute( - name: "default", - template: "{controller=Home}/{action=Index}/{id?}"); + endpoints.MapRazorPages(); + endpoints.MapHealthChecks("/health"); }); } } diff --git a/src/FrontEnd/appsettings.Development.json b/src/FrontEnd/appsettings.Development.json index fa8ce71a..50fc53cc 100644 --- a/src/FrontEnd/appsettings.Development.json +++ b/src/FrontEnd/appsettings.Development.json @@ -4,7 +4,7 @@ "LogLevel": { "Default": "Debug", "System": "Information", - "Microsoft": "Information" + "Microsoft": "Debug" } } } diff --git a/src/FrontEnd/appsettings.json b/src/FrontEnd/appsettings.json index 1d88c79e..185f3f5c 100644 --- a/src/FrontEnd/appsettings.json +++ b/src/FrontEnd/appsettings.json @@ -1,10 +1,11 @@ { "ServiceUrl": "http://localhost:56009/", - "Admin": "", "Logging": { "IncludeScopes": false, "LogLevel": { - "Default": "Warning" + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" } }, "ConnectionStrings": { From 306885b9154eaa1d0c4c04966aef6103c8a225dd Mon Sep 17 00:00:00 2001 From: Damian Edwards Date: Tue, 14 May 2019 21:25:07 -0700 Subject: [PATCH 02/56] Update sln file to Dev16 --- ConferencePlanner.sln | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ConferencePlanner.sln b/ConferencePlanner.sln index c6c76ae3..9f889d19 100644 --- a/ConferencePlanner.sln +++ b/ConferencePlanner.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26606.0 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28902.138 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrontEnd", "src\FrontEnd\FrontEnd.csproj", "{520772E8-2FA9-4A3E-8F62-ACA084EA2AFF}" EndProject From 1df80348c524f2e128bae9c8615d3492b04524cb Mon Sep 17 00:00:00 2001 From: David Fowler Date: Thu, 16 May 2019 00:41:58 -0700 Subject: [PATCH 03/56] Application clean up - Removed unused controller actions and controllers - Removed tags, conferences (the schema only supports a single conference) - Fixed ID casing --- src/BackEnd/BackEnd.csproj | 10 + .../Controllers/AttendeesController.cs | 12 +- .../Controllers/ConferencesController.cs | 146 --------- src/BackEnd/Controllers/SearchController.cs | 11 +- src/BackEnd/Controllers/SessionsController.cs | 56 +++- src/BackEnd/Controllers/SpeakersController.cs | 60 +--- src/BackEnd/Data/ApplicationDbContext.cs | 18 +- src/BackEnd/Data/Attendee.cs | 2 - src/BackEnd/Data/Conference.cs | 17 - src/BackEnd/Data/ConferenceAttendee.cs | 18 -- src/BackEnd/Data/DataLoader.cs | 2 +- src/BackEnd/Data/DevIntersectionLoader.cs | 7 +- src/BackEnd/Data/Session.cs | 4 - src/BackEnd/Data/SessionAttendee.cs | 4 +- src/BackEnd/Data/SessionTag.cs | 18 -- src/BackEnd/Data/SessionizeLoader.cs | 21 +- src/BackEnd/Data/Tag.cs | 9 - src/BackEnd/Data/Track.cs | 3 - .../Infrastructure/EntityExtensions.cs | 30 +- .../Migrations/20190126203326_Initial.cs | 301 ------------------ ....cs => 20190516073157_Initial.Designer.cs} | 158 ++------- .../Migrations/20190516073157_Initial.cs | 169 ++++++++++ .../ApplicationDbContextModelSnapshot.cs | 156 ++------- src/BackEnd/Startup.cs | 1 + src/ConferenceDTO/Attendee.cs | 2 +- src/ConferenceDTO/AttendeeResponse.cs | 2 - src/ConferenceDTO/Conference.cs | 16 - src/ConferenceDTO/ConferenceResponse.cs | 15 - src/ConferenceDTO/Session.cs | 5 +- src/ConferenceDTO/SessionResponse.cs | 2 - src/ConferenceDTO/Speaker.cs | 2 +- src/ConferenceDTO/Tag.cs | 14 - src/ConferenceDTO/TagResponse.cs | 11 - src/ConferenceDTO/Track.cs | 5 +- src/ConferenceDTO/TrackResponse.cs | 2 - src/FrontEnd/Pages/Admin/EditSession.cshtml | 3 +- .../Pages/Admin/EditSession.cshtml.cs | 3 +- src/FrontEnd/Pages/Error.cshtml | 2 +- src/FrontEnd/Pages/Index.cshtml | 10 +- src/FrontEnd/Pages/Index.cshtml.cs | 2 +- src/FrontEnd/Pages/MyAgenda.cshtml | 10 +- src/FrontEnd/Pages/Search.cshtml | 8 +- src/FrontEnd/Pages/Session.cshtml | 6 +- src/FrontEnd/Pages/Session.cshtml.cs | 2 +- src/FrontEnd/Pages/Speaker.cshtml | 2 +- src/FrontEnd/Pages/Speakers.cshtml | 4 +- src/FrontEnd/Services/ApiClient.cs | 6 +- 47 files changed, 330 insertions(+), 1037 deletions(-) delete mode 100644 src/BackEnd/Controllers/ConferencesController.cs delete mode 100644 src/BackEnd/Data/Conference.cs delete mode 100644 src/BackEnd/Data/ConferenceAttendee.cs delete mode 100644 src/BackEnd/Data/SessionTag.cs delete mode 100644 src/BackEnd/Data/Tag.cs delete mode 100644 src/BackEnd/Migrations/20190126203326_Initial.cs rename src/BackEnd/Migrations/{20190126203326_Initial.Designer.cs => 20190516073157_Initial.Designer.cs} (50%) create mode 100644 src/BackEnd/Migrations/20190516073157_Initial.cs delete mode 100644 src/ConferenceDTO/Conference.cs delete mode 100644 src/ConferenceDTO/ConferenceResponse.cs delete mode 100644 src/ConferenceDTO/Tag.cs delete mode 100644 src/ConferenceDTO/TagResponse.cs diff --git a/src/BackEnd/BackEnd.csproj b/src/BackEnd/BackEnd.csproj index 1872672c..fec8b721 100644 --- a/src/BackEnd/BackEnd.csproj +++ b/src/BackEnd/BackEnd.csproj @@ -5,10 +5,20 @@ aspnet-BackEnd-931E56BD-86CB-4A96-BD99-2C6A6ABB0829 + + + + + + + + + + diff --git a/src/BackEnd/Controllers/AttendeesController.cs b/src/BackEnd/Controllers/AttendeesController.cs index 006f576f..43241435 100644 --- a/src/BackEnd/Controllers/AttendeesController.cs +++ b/src/BackEnd/Controllers/AttendeesController.cs @@ -68,7 +68,7 @@ public async Task> Post(ConferenceDTO.Attendee in return CreatedAtAction(nameof(Get), new { id = result.UserName }, result); } - [HttpPost("{username}/session/{sessionId:int}")] + [HttpPost("{username}/session/{sessionId}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -77,8 +77,6 @@ public async Task> AddSession(string username, in { var attendee = await _db.Attendees.Include(a => a.SessionsAttendees) .ThenInclude(sa => sa.Session) - .Include(a => a.ConferenceAttendees) - .ThenInclude(ca => ca.Conference) .SingleOrDefaultAsync(a => a.UserName == username); if (attendee == null) @@ -95,8 +93,8 @@ public async Task> AddSession(string username, in attendee.SessionsAttendees.Add(new SessionAttendee { - AttendeeID = attendee.ID, - SessionID = sessionId + AttendeeId = attendee.Id, + SessionId = sessionId }); await _db.SaveChangesAsync(); @@ -106,7 +104,7 @@ public async Task> AddSession(string username, in return result; } - [HttpDelete("{username}/session/{sessionId:int}")] + [HttpDelete("{username}/session/{sessionId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -128,7 +126,7 @@ public async Task RemoveSession(string username, int sessionId) return BadRequest(); } - var sessionAttendee = attendee.SessionsAttendees.FirstOrDefault(sa => sa.SessionID == sessionId); + var sessionAttendee = attendee.SessionsAttendees.FirstOrDefault(sa => sa.SessionId == sessionId); attendee.SessionsAttendees.Remove(sessionAttendee); await _db.SaveChangesAsync(); diff --git a/src/BackEnd/Controllers/ConferencesController.cs b/src/BackEnd/Controllers/ConferencesController.cs deleted file mode 100644 index ca26f68a..00000000 --- a/src/BackEnd/Controllers/ConferencesController.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; -using BackEnd.Data; -using ConferenceDTO; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; - -namespace BackEnd.Controllers -{ - [Route("api/[controller]")] - [ApiController] - public class ConferencesController : ControllerBase - { - private readonly ApplicationDbContext _db; - - public ConferencesController(ApplicationDbContext db) - { - _db = db; - } - - [HttpGet] - public async Task>> GetConferences() - { - var conferences = await _db.Conferences.AsNoTracking().Select(s => new ConferenceResponse - { - ID = s.ID, - Name = s.Name - }) - .ToListAsync(); - - return conferences; - } - - [HttpGet("{id:int}")] - public async Task> GetConference(int id) - { - var conference = await _db.FindAsync(id); - - if (conference == null) - { - return NotFound(); - } - - var result = new ConferenceResponse - { - ID = conference.ID, - Name = conference.Name - }; - - return result; - } - - [HttpPost("upload")] - [Consumes("multipart/form-data")] - public async Task UploadConference([Required, FromForm]string conferenceName, [FromForm]ConferenceFormat format, IFormFile file) - { - var loader = GetLoader(format); - - using (var stream = file.OpenReadStream()) - { - await loader.LoadDataAsync(conferenceName, stream, _db); - } - - await _db.SaveChangesAsync(); - - return Ok(); - } - - [HttpPost] - public async Task> CreateConference(ConferenceDTO.Conference input) - { - var conference = new Data.Conference - { - Name = input.Name - }; - - _db.Conferences.Add(conference); - await _db.SaveChangesAsync(); - - var result = new ConferenceDTO.ConferenceResponse - { - ID = conference.ID, - Name = conference.Name - }; - - return CreatedAtAction(nameof(GetConference), new { id = conference.ID }, result); - } - - [HttpPut("{id:int}")] - public async Task PutConference(int id, ConferenceDTO.Conference input) - { - var conference = await _db.FindAsync(id); - - if (conference == null) - { - return NotFound(); - } - - conference.Name = input.Name; - - await _db.SaveChangesAsync(); - - return NoContent(); - } - - [HttpDelete("{id:int}")] - public async Task> DeleteConference(int id) - { - var conference = await _db.FindAsync(id); - - if (conference == null) - { - return NotFound(); - } - - _db.Remove(conference); - - await _db.SaveChangesAsync(); - - var result = new ConferenceDTO.ConferenceResponse - { - ID = conference.ID, - Name = conference.Name - }; - return result; - } - - private static DataLoader GetLoader(ConferenceFormat format) - { - if (format == ConferenceFormat.Sessionize) - { - return new SessionizeLoader(); - } - return new DevIntersectionLoader(); - } - - public enum ConferenceFormat - { - Sessionize, - DevIntersections - } - } -} diff --git a/src/BackEnd/Controllers/SearchController.cs b/src/BackEnd/Controllers/SearchController.cs index 86d63cec..ccefdaf9 100644 --- a/src/BackEnd/Controllers/SearchController.cs +++ b/src/BackEnd/Controllers/SearchController.cs @@ -47,22 +47,21 @@ public async Task>> Search(SearchTerm term) Type = SearchResultType.Session, Value = JObject.FromObject(new SessionResponse { - ID = s.ID, + Id = s.Id, Title = s.Title, Abstract = s.Abstract, - ConferenceID = s.ConferenceID, StartTime = s.StartTime, EndTime = s.EndTime, TrackId = s.TrackId, Track = new ConferenceDTO.Track { - TrackID = s?.TrackId ?? 0, + Id = s?.TrackId ?? 0, Name = s.Track?.Name }, Speakers = s?.SessionSpeakers .Select(ss => new ConferenceDTO.Speaker { - ID = ss.SpeakerId, + Id = ss.SpeakerId, Name = ss.Speaker.Name }) .ToList() @@ -73,7 +72,7 @@ public async Task>> Search(SearchTerm term) Type = SearchResultType.Speaker, Value = JObject.FromObject(new SpeakerResponse { - ID = s.ID, + Id = s.Id, Name = s.Name, Bio = s.Bio, WebSite = s.WebSite, @@ -81,7 +80,7 @@ public async Task>> Search(SearchTerm term) .Select(ss => new ConferenceDTO.Session { - ID = ss.SessionId, + Id = ss.SessionId, Title = ss.Session.Title }) .ToList() diff --git a/src/BackEnd/Controllers/SessionsController.cs b/src/BackEnd/Controllers/SessionsController.cs index 3b38db08..0531b27b 100644 --- a/src/BackEnd/Controllers/SessionsController.cs +++ b/src/BackEnd/Controllers/SessionsController.cs @@ -1,10 +1,12 @@ using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; using BackEnd.Data; using ConferenceDTO; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; namespace BackEnd.Controllers { @@ -26,23 +28,19 @@ public async Task>> Get() .Include(s => s.Track) .Include(s => s.SessionSpeakers) .ThenInclude(ss => ss.Speaker) - .Include(s => s.SessionTags) - .ThenInclude(st => st.Tag) .Select(m => m.MapSessionResponse()) .ToListAsync(); return sessions; } - [HttpGet("{id:int}")] + [HttpGet("{id}")] public async Task> Get(int id) { var session = await _db.Sessions.AsNoTracking() .Include(s => s.Track) .Include(s => s.SessionSpeakers) .ThenInclude(ss => ss.Speaker) - .Include(s => s.SessionTags) - .ThenInclude(st => st.Tag) - .SingleOrDefaultAsync(s => s.ID == id); + .SingleOrDefaultAsync(s => s.Id == id); if (session == null) { @@ -58,7 +56,6 @@ public async Task> Post(ConferenceDTO.Session inpu var session = new Data.Session { Title = input.Title, - ConferenceID = input.ConferenceID, StartTime = input.StartTime, EndTime = input.EndTime, Abstract = input.Abstract, @@ -70,10 +67,10 @@ public async Task> Post(ConferenceDTO.Session inpu var result = session.MapSessionResponse(); - return CreatedAtAction(nameof(Get), new { id = result.ID }, result); + return CreatedAtAction(nameof(Get), new { id = result.Id }, result); } - [HttpPut("{id:int}")] + [HttpPut("{id}")] public async Task Put(int id, ConferenceDTO.Session input) { var session = await _db.Sessions.FindAsync(id); @@ -83,20 +80,19 @@ public async Task Put(int id, ConferenceDTO.Session input) return NotFound(); } - session.ID = input.ID; + session.Id = input.Id; session.Title = input.Title; session.Abstract = input.Abstract; session.StartTime = input.StartTime; session.EndTime = input.EndTime; session.TrackId = input.TrackId; - session.ConferenceID = input.ConferenceID; await _db.SaveChangesAsync(); return NoContent(); } - [HttpDelete("{id:int}")] + [HttpDelete("{id}")] public async Task> Delete(int id) { var session = await _db.Sessions.FindAsync(id); @@ -111,5 +107,37 @@ public async Task> Delete(int id) return session.MapSessionResponse(); } + + + [HttpPost("upload")] + [Consumes("multipart/form-data")] + public async Task Upload([FromForm]ConferenceFormat format, IFormFile file) + { + var loader = GetLoader(format); + + using (var stream = file.OpenReadStream()) + { + await loader.LoadDataAsync(stream, _db); + } + + await _db.SaveChangesAsync(); + + return Ok(); + } + + private static DataLoader GetLoader(ConferenceFormat format) + { + if (format == ConferenceFormat.Sessionize) + { + return new SessionizeLoader(); + } + return new DevIntersectionLoader(); + } + + public enum ConferenceFormat + { + Sessionize, + DevIntersections + } } } diff --git a/src/BackEnd/Controllers/SpeakersController.cs b/src/BackEnd/Controllers/SpeakersController.cs index 71c2ba82..e3f3d6f1 100644 --- a/src/BackEnd/Controllers/SpeakersController.cs +++ b/src/BackEnd/Controllers/SpeakersController.cs @@ -31,13 +31,13 @@ public async Task>> GetSpeakers() return speakers; } - [HttpGet("{id:int}")] + [HttpGet("{id}")] public async Task> GetSpeaker(int id) { var speaker = await _db.Speakers.AsNoTracking() .Include(s => s.SessionSpeakers) .ThenInclude(ss => ss.Session) - .SingleOrDefaultAsync(s => s.ID == id); + .SingleOrDefaultAsync(s => s.Id == id); if (speaker == null) { @@ -47,61 +47,5 @@ public async Task> GetSpeaker(int id) var result = speaker.MapSpeakerResponse(); return result; } - - [HttpPost] - public async Task CreateSpeaker(ConferenceDTO.Speaker input) - { - var speaker = new Data.Speaker - { - Name = input.Name, - WebSite = input.WebSite, - Bio = input.Bio - }; - - _db.Speakers.Add(speaker); - await _db.SaveChangesAsync(); - - var result = speaker.MapSpeakerResponse(); - - return CreatedAtAction(nameof(GetSpeaker), new { id = speaker.ID }, result); - } - - [HttpPut("{id:int}")] - public async Task PutSpeaker(int id, ConferenceDTO.Speaker input) - { - var speaker = await _db.FindAsync(id); - - if (speaker == null) - { - return NotFound(); - } - - speaker.Name = input.Name; - speaker.WebSite = input.WebSite; - speaker.Bio = input.Bio; - - // TODO: Handle exceptions, e.g. concurrency - await _db.SaveChangesAsync(); - - return NoContent(); - } - - [HttpDelete("{id:int}")] - public async Task> DeleteSpeaker(int id) - { - var speaker = await _db.FindAsync(id); - - if (speaker == null) - { - return NotFound(); - } - - _db.Remove(speaker); - - // TODO: Handle exceptions, e.g. concurrency - await _db.SaveChangesAsync(); - - return speaker.MapSpeakerResponse(); - } } } diff --git a/src/BackEnd/Data/ApplicationDbContext.cs b/src/BackEnd/Data/ApplicationDbContext.cs index 01d6b0df..96690679 100644 --- a/src/BackEnd/Data/ApplicationDbContext.cs +++ b/src/BackEnd/Data/ApplicationDbContext.cs @@ -15,35 +15,19 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasIndex(a => a.UserName) .IsUnique(); - // Ignore the computed property - modelBuilder.Entity() - .Ignore(s => s.Duration); - - // Many-to-many: Conference <-> Attendee - modelBuilder.Entity() - .HasKey(ca => new { ca.ConferenceID, ca.AttendeeID }); - // Many-to-many: Session <-> Attendee modelBuilder.Entity() - .HasKey(ca => new { ca.SessionID, ca.AttendeeID }); + .HasKey(ca => new { ca.SessionId, ca.AttendeeId }); // Many-to-many: Speaker <-> Session modelBuilder.Entity() .HasKey(ss => new { ss.SessionId, ss.SpeakerId }); - - // Many-to-many: Session <-> Tag - modelBuilder.Entity() - .HasKey(st => new { st.SessionID, st.TagID }); } - public DbSet Conferences { get; set; } - public DbSet Sessions { get; set; } public DbSet Tracks { get; set; } - public DbSet Tags { get; set; } - public DbSet Speakers { get; set; } public DbSet Attendees { get; set; } diff --git a/src/BackEnd/Data/Attendee.cs b/src/BackEnd/Data/Attendee.cs index 0f61beaf..9b311bd6 100644 --- a/src/BackEnd/Data/Attendee.cs +++ b/src/BackEnd/Data/Attendee.cs @@ -5,8 +5,6 @@ namespace BackEnd.Data { public class Attendee : ConferenceDTO.Attendee { - public virtual ICollection ConferenceAttendees { get; set; } - public virtual ICollection SessionsAttendees { get; set; } } } \ No newline at end of file diff --git a/src/BackEnd/Data/Conference.cs b/src/BackEnd/Data/Conference.cs deleted file mode 100644 index 34b28570..00000000 --- a/src/BackEnd/Data/Conference.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace BackEnd.Data -{ - public class Conference : ConferenceDTO.Conference - { - public virtual ICollection Tracks { get; set; } - - public virtual ICollection Speakers { get; set; } - - public virtual ICollection Sessions { get; set; } - - public virtual ICollection ConferenceAttendees { get; set; } - } -} diff --git a/src/BackEnd/Data/ConferenceAttendee.cs b/src/BackEnd/Data/ConferenceAttendee.cs deleted file mode 100644 index 1c3fff5f..00000000 --- a/src/BackEnd/Data/ConferenceAttendee.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace BackEnd.Data -{ - public class ConferenceAttendee - { - public int ConferenceID { get; set; } - - public Conference Conference { get; set; } - - public int AttendeeID { get; set; } - - public Attendee Attendee { get; set; } - } -} diff --git a/src/BackEnd/Data/DataLoader.cs b/src/BackEnd/Data/DataLoader.cs index 0b4eb353..589c1384 100644 --- a/src/BackEnd/Data/DataLoader.cs +++ b/src/BackEnd/Data/DataLoader.cs @@ -6,7 +6,7 @@ namespace BackEnd.Data { public abstract class DataLoader { - public abstract Task LoadDataAsync(string conferenceName, Stream fileStream, ApplicationDbContext db); + public abstract Task LoadDataAsync(Stream fileStream, ApplicationDbContext db); } } \ No newline at end of file diff --git a/src/BackEnd/Data/DevIntersectionLoader.cs b/src/BackEnd/Data/DevIntersectionLoader.cs index 9438fe3f..932b6ab3 100644 --- a/src/BackEnd/Data/DevIntersectionLoader.cs +++ b/src/BackEnd/Data/DevIntersectionLoader.cs @@ -10,12 +10,10 @@ namespace BackEnd { public class DevIntersectionLoader : DataLoader { - public override async Task LoadDataAsync(string conferenceName, Stream fileStream, ApplicationDbContext db) + public override async Task LoadDataAsync(Stream fileStream, ApplicationDbContext db) { var reader = new JsonTextReader(new StreamReader(fileStream)); - var conference = new Conference { Name = conferenceName }; - var speakerNames = new Dictionary(); var tracks = new Dictionary(); @@ -41,7 +39,7 @@ public override async Task LoadDataAsync(string conferenceName, Stream fileStrea { if (!tracks.ContainsKey(thisTrackName.Value())) { - var thisTrack = new Track { Name = thisTrackName.Value(), Conference = conference }; + var thisTrack = new Track { Name = thisTrackName.Value() }; db.Tracks.Add(thisTrack); tracks.Add(thisTrackName.Value(), thisTrack); } @@ -50,7 +48,6 @@ public override async Task LoadDataAsync(string conferenceName, Stream fileStrea var session = new Session { - Conference = conference, Title = item["title"].Value(), StartTime = item["startTime"].Value(), EndTime = item["endTime"].Value(), diff --git a/src/BackEnd/Data/Session.cs b/src/BackEnd/Data/Session.cs index c583eee3..376f37c4 100644 --- a/src/BackEnd/Data/Session.cs +++ b/src/BackEnd/Data/Session.cs @@ -6,12 +6,8 @@ namespace BackEnd.Data { public class Session : ConferenceDTO.Session { - public Conference Conference { get; set; } - public virtual ICollection SessionSpeakers { get; set; } public Track Track { get; set; } - - public virtual ICollection SessionTags { get; set; } } } \ No newline at end of file diff --git a/src/BackEnd/Data/SessionAttendee.cs b/src/BackEnd/Data/SessionAttendee.cs index 2a6a0752..a6a8eeeb 100644 --- a/src/BackEnd/Data/SessionAttendee.cs +++ b/src/BackEnd/Data/SessionAttendee.cs @@ -7,11 +7,11 @@ namespace BackEnd.Data { public class SessionAttendee { - public int SessionID { get; set; } + public int SessionId { get; set; } public Session Session { get; set; } - public int AttendeeID { get; set; } + public int AttendeeId { get; set; } public Attendee Attendee { get; set; } } diff --git a/src/BackEnd/Data/SessionTag.cs b/src/BackEnd/Data/SessionTag.cs deleted file mode 100644 index 01434e26..00000000 --- a/src/BackEnd/Data/SessionTag.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace BackEnd.Data -{ - public class SessionTag - { - public int SessionID { get; set; } - - public Session Session { get; set; } - - public int TagID { get; set; } - - public Tag Tag { get; set; } - } -} diff --git a/src/BackEnd/Data/SessionizeLoader.cs b/src/BackEnd/Data/SessionizeLoader.cs index bf5f02af..a65c399f 100644 --- a/src/BackEnd/Data/SessionizeLoader.cs +++ b/src/BackEnd/Data/SessionizeLoader.cs @@ -10,17 +10,15 @@ namespace BackEnd { public class SessionizeLoader : DataLoader { - public override async Task LoadDataAsync(string conferenceName, Stream fileStream, ApplicationDbContext db) + public override async Task LoadDataAsync(Stream fileStream, ApplicationDbContext db) { - //var blah = new RootObject().rooms[0].sessions[0].speakers[0].name; + // var blah = new RootObject().rooms[0].sessions[0].speakers[0].name; var addedSpeakers = new Dictionary(); var addedTracks = new Dictionary(); - var addedTags = new Dictionary(); var array = await JToken.LoadAsync(new JsonTextReader(new StreamReader(fileStream))); - var conference = new Conference { Name = conferenceName }; - + var root = array.ToObject>(); foreach (var date in root) @@ -29,7 +27,7 @@ public override async Task LoadDataAsync(string conferenceName, Stream fileStrea { if (!addedTracks.ContainsKey(room.name)) { - var thisTrack = new Track { Name = room.name, Conference = conference }; + var thisTrack = new Track { Name = room.name }; db.Tracks.Add(thisTrack); addedTracks.Add(thisTrack.Name, thisTrack); } @@ -46,19 +44,8 @@ public override async Task LoadDataAsync(string conferenceName, Stream fileStrea } } - foreach (var category in thisSession.categories) - { - if (!addedTags.ContainsKey(category.name)) - { - var thisTag = new Tag { Name = category.name }; - db.Tags.Add(thisTag); - addedTags.Add(thisTag.Name, thisTag); - } - } - var session = new Session { - Conference = conference, Title = thisSession.title, StartTime = thisSession.startsAt, EndTime = thisSession.endsAt, diff --git a/src/BackEnd/Data/Tag.cs b/src/BackEnd/Data/Tag.cs deleted file mode 100644 index 6e872ac5..00000000 --- a/src/BackEnd/Data/Tag.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Collections.Generic; - -namespace BackEnd.Data -{ - public class Tag : ConferenceDTO.Tag - { - public virtual ICollection SessionTags { get; set; } - } -} \ No newline at end of file diff --git a/src/BackEnd/Data/Track.cs b/src/BackEnd/Data/Track.cs index 325a511d..5e1ff782 100644 --- a/src/BackEnd/Data/Track.cs +++ b/src/BackEnd/Data/Track.cs @@ -6,9 +6,6 @@ namespace BackEnd.Data { public class Track : ConferenceDTO.Track { - [Required] - public Conference Conference { get; set; } - public virtual ICollection Sessions { get; set; } } } \ No newline at end of file diff --git a/src/BackEnd/Infrastructure/EntityExtensions.cs b/src/BackEnd/Infrastructure/EntityExtensions.cs index a33d28b7..d148a4d9 100644 --- a/src/BackEnd/Infrastructure/EntityExtensions.cs +++ b/src/BackEnd/Infrastructure/EntityExtensions.cs @@ -7,38 +7,30 @@ public static class EntityExtensions public static ConferenceDTO.SessionResponse MapSessionResponse(this Session session) => new ConferenceDTO.SessionResponse { - ID = session.ID, + Id = session.Id, Title = session.Title, StartTime = session.StartTime, EndTime = session.EndTime, - Tags = session.SessionTags? - .Select(st => new ConferenceDTO.Tag - { - ID = st.TagID, - Name = st.Tag.Name - }) - .ToList(), Speakers = session.SessionSpeakers? .Select(ss => new ConferenceDTO.Speaker { - ID = ss.SpeakerId, + Id = ss.SpeakerId, Name = ss.Speaker.Name }) .ToList(), TrackId = session.TrackId, Track = new ConferenceDTO.Track { - TrackID = session?.TrackId ?? 0, + Id = session?.TrackId ?? 0, Name = session.Track?.Name }, - ConferenceID = session.ConferenceID, Abstract = session.Abstract }; public static ConferenceDTO.SpeakerResponse MapSpeakerResponse(this Speaker speaker) => new ConferenceDTO.SpeakerResponse { - ID = speaker.ID, + Id = speaker.Id, Name = speaker.Name, Bio = speaker.Bio, WebSite = speaker.WebSite, @@ -46,7 +38,7 @@ public static ConferenceDTO.SpeakerResponse MapSpeakerResponse(this Speaker spea .Select(ss => new ConferenceDTO.Session { - ID = ss.SessionId, + Id = ss.SessionId, Title = ss.Session.Title }) .ToList() @@ -55,7 +47,7 @@ public static ConferenceDTO.SpeakerResponse MapSpeakerResponse(this Speaker spea public static ConferenceDTO.AttendeeResponse MapAttendeeResponse(this Attendee attendee) => new ConferenceDTO.AttendeeResponse { - ID = attendee.ID, + Id = attendee.Id, FirstName = attendee.FirstName, LastName = attendee.LastName, UserName = attendee.UserName, @@ -63,20 +55,12 @@ public static ConferenceDTO.AttendeeResponse MapAttendeeResponse(this Attendee a .Select(sa => new ConferenceDTO.Session { - ID = sa.SessionID, + Id = sa.SessionId, Title = sa.Session.Title, StartTime = sa.Session.StartTime, EndTime = sa.Session.EndTime }) .ToList(), - Conferences = attendee.ConferenceAttendees? - .Select(ca => - new ConferenceDTO.Conference - { - ID = ca.ConferenceID, - Name = ca.Conference.Name - }) - .ToList(), }; } } diff --git a/src/BackEnd/Migrations/20190126203326_Initial.cs b/src/BackEnd/Migrations/20190126203326_Initial.cs deleted file mode 100644 index 5219be7c..00000000 --- a/src/BackEnd/Migrations/20190126203326_Initial.cs +++ /dev/null @@ -1,301 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace BackEnd.Migrations -{ - public partial class Initial : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "Attendees", - columns: table => new - { - ID = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - FirstName = table.Column(maxLength: 200, nullable: false), - LastName = table.Column(maxLength: 200, nullable: false), - UserName = table.Column(maxLength: 200, nullable: false), - EmailAddress = table.Column(maxLength: 256, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Attendees", x => x.ID); - }); - - migrationBuilder.CreateTable( - name: "Conferences", - columns: table => new - { - ID = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - Name = table.Column(maxLength: 200, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Conferences", x => x.ID); - }); - - migrationBuilder.CreateTable( - name: "Tags", - columns: table => new - { - ID = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - Name = table.Column(maxLength: 32, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Tags", x => x.ID); - }); - - migrationBuilder.CreateTable( - name: "ConferenceAttendee", - columns: table => new - { - ConferenceID = table.Column(nullable: false), - AttendeeID = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ConferenceAttendee", x => new { x.ConferenceID, x.AttendeeID }); - table.ForeignKey( - name: "FK_ConferenceAttendee_Attendees_AttendeeID", - column: x => x.AttendeeID, - principalTable: "Attendees", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_ConferenceAttendee_Conferences_ConferenceID", - column: x => x.ConferenceID, - principalTable: "Conferences", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Speakers", - columns: table => new - { - ID = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - Name = table.Column(maxLength: 200, nullable: false), - Bio = table.Column(maxLength: 4000, nullable: true), - WebSite = table.Column(maxLength: 1000, nullable: true), - ConferenceID = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Speakers", x => x.ID); - table.ForeignKey( - name: "FK_Speakers_Conferences_ConferenceID", - column: x => x.ConferenceID, - principalTable: "Conferences", - principalColumn: "ID", - onDelete: ReferentialAction.Restrict); - }); - - migrationBuilder.CreateTable( - name: "Tracks", - columns: table => new - { - TrackID = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - ConferenceID = table.Column(nullable: false), - Name = table.Column(maxLength: 200, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Tracks", x => x.TrackID); - table.ForeignKey( - name: "FK_Tracks_Conferences_ConferenceID", - column: x => x.ConferenceID, - principalTable: "Conferences", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Sessions", - columns: table => new - { - ID = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - ConferenceID = table.Column(nullable: false), - Title = table.Column(maxLength: 200, nullable: false), - Abstract = table.Column(maxLength: 4000, nullable: true), - StartTime = table.Column(nullable: true), - EndTime = table.Column(nullable: true), - TrackId = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Sessions", x => x.ID); - table.ForeignKey( - name: "FK_Sessions_Conferences_ConferenceID", - column: x => x.ConferenceID, - principalTable: "Conferences", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_Sessions_Tracks_TrackId", - column: x => x.TrackId, - principalTable: "Tracks", - principalColumn: "TrackID", - onDelete: ReferentialAction.Restrict); - }); - - migrationBuilder.CreateTable( - name: "SessionAttendee", - columns: table => new - { - SessionID = table.Column(nullable: false), - AttendeeID = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_SessionAttendee", x => new { x.SessionID, x.AttendeeID }); - table.ForeignKey( - name: "FK_SessionAttendee_Attendees_AttendeeID", - column: x => x.AttendeeID, - principalTable: "Attendees", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_SessionAttendee_Sessions_SessionID", - column: x => x.SessionID, - principalTable: "Sessions", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "SessionSpeaker", - columns: table => new - { - SessionId = table.Column(nullable: false), - SpeakerId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_SessionSpeaker", x => new { x.SessionId, x.SpeakerId }); - table.ForeignKey( - name: "FK_SessionSpeaker_Sessions_SessionId", - column: x => x.SessionId, - principalTable: "Sessions", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_SessionSpeaker_Speakers_SpeakerId", - column: x => x.SpeakerId, - principalTable: "Speakers", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "SessionTag", - columns: table => new - { - SessionID = table.Column(nullable: false), - TagID = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_SessionTag", x => new { x.SessionID, x.TagID }); - table.ForeignKey( - name: "FK_SessionTag_Sessions_SessionID", - column: x => x.SessionID, - principalTable: "Sessions", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_SessionTag_Tags_TagID", - column: x => x.TagID, - principalTable: "Tags", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_Attendees_UserName", - table: "Attendees", - column: "UserName", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ConferenceAttendee_AttendeeID", - table: "ConferenceAttendee", - column: "AttendeeID"); - - migrationBuilder.CreateIndex( - name: "IX_SessionAttendee_AttendeeID", - table: "SessionAttendee", - column: "AttendeeID"); - - migrationBuilder.CreateIndex( - name: "IX_Sessions_ConferenceID", - table: "Sessions", - column: "ConferenceID"); - - migrationBuilder.CreateIndex( - name: "IX_Sessions_TrackId", - table: "Sessions", - column: "TrackId"); - - migrationBuilder.CreateIndex( - name: "IX_SessionSpeaker_SpeakerId", - table: "SessionSpeaker", - column: "SpeakerId"); - - migrationBuilder.CreateIndex( - name: "IX_SessionTag_TagID", - table: "SessionTag", - column: "TagID"); - - migrationBuilder.CreateIndex( - name: "IX_Speakers_ConferenceID", - table: "Speakers", - column: "ConferenceID"); - - migrationBuilder.CreateIndex( - name: "IX_Tracks_ConferenceID", - table: "Tracks", - column: "ConferenceID"); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "ConferenceAttendee"); - - migrationBuilder.DropTable( - name: "SessionAttendee"); - - migrationBuilder.DropTable( - name: "SessionSpeaker"); - - migrationBuilder.DropTable( - name: "SessionTag"); - - migrationBuilder.DropTable( - name: "Attendees"); - - migrationBuilder.DropTable( - name: "Speakers"); - - migrationBuilder.DropTable( - name: "Sessions"); - - migrationBuilder.DropTable( - name: "Tags"); - - migrationBuilder.DropTable( - name: "Tracks"); - - migrationBuilder.DropTable( - name: "Conferences"); - } - } -} diff --git a/src/BackEnd/Migrations/20190126203326_Initial.Designer.cs b/src/BackEnd/Migrations/20190516073157_Initial.Designer.cs similarity index 50% rename from src/BackEnd/Migrations/20190126203326_Initial.Designer.cs rename to src/BackEnd/Migrations/20190516073157_Initial.Designer.cs index ad4dd9bc..b1a6e283 100644 --- a/src/BackEnd/Migrations/20190126203326_Initial.Designer.cs +++ b/src/BackEnd/Migrations/20190516073157_Initial.Designer.cs @@ -10,20 +10,20 @@ namespace BackEnd.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20190126203326_Initial")] + [Migration("20190516073157_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.1-servicing-10028") + .HasAnnotation("ProductVersion", "3.0.0-preview5.19227.1") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("BackEnd.Data.Attendee", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); @@ -42,7 +42,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .IsRequired() .HasMaxLength(200); - b.HasKey("ID"); + b.HasKey("Id"); b.HasIndex("UserName") .IsUnique(); @@ -50,45 +50,15 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("Attendees"); }); - modelBuilder.Entity("BackEnd.Data.Conference", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("ID"); - - b.ToTable("Conferences"); - }); - - modelBuilder.Entity("BackEnd.Data.ConferenceAttendee", b => - { - b.Property("ConferenceID"); - - b.Property("AttendeeID"); - - b.HasKey("ConferenceID", "AttendeeID"); - - b.HasIndex("AttendeeID"); - - b.ToTable("ConferenceAttendee"); - }); - modelBuilder.Entity("BackEnd.Data.Session", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("Abstract") .HasMaxLength(4000); - b.Property("ConferenceID"); - b.Property("EndTime"); b.Property("StartTime"); @@ -99,9 +69,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("TrackId"); - b.HasKey("ID"); - - b.HasIndex("ConferenceID"); + b.HasKey("Id"); b.HasIndex("TrackId"); @@ -110,13 +78,13 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("BackEnd.Data.SessionAttendee", b => { - b.Property("SessionID"); + b.Property("SessionId"); - b.Property("AttendeeID"); + b.Property("AttendeeId"); - b.HasKey("SessionID", "AttendeeID"); + b.HasKey("SessionId", "AttendeeId"); - b.HasIndex("AttendeeID"); + b.HasIndex("AttendeeId"); b.ToTable("SessionAttendee"); }); @@ -134,30 +102,15 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("SessionSpeaker"); }); - modelBuilder.Entity("BackEnd.Data.SessionTag", b => - { - b.Property("SessionID"); - - b.Property("TagID"); - - b.HasKey("SessionID", "TagID"); - - b.HasIndex("TagID"); - - b.ToTable("SessionTag"); - }); - modelBuilder.Entity("BackEnd.Data.Speaker", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("Bio") .HasMaxLength(4000); - b.Property("ConferenceID"); - b.Property("Name") .IsRequired() .HasMaxLength(200); @@ -165,67 +118,28 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("WebSite") .HasMaxLength(1000); - b.HasKey("ID"); - - b.HasIndex("ConferenceID"); + b.HasKey("Id"); b.ToTable("Speakers"); }); - modelBuilder.Entity("BackEnd.Data.Tag", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("Name") - .IsRequired() - .HasMaxLength(32); - - b.HasKey("ID"); - - b.ToTable("Tags"); - }); - modelBuilder.Entity("BackEnd.Data.Track", b => { - b.Property("TrackID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - b.Property("ConferenceID"); - b.Property("Name") .IsRequired() .HasMaxLength(200); - b.HasKey("TrackID"); - - b.HasIndex("ConferenceID"); + b.HasKey("Id"); b.ToTable("Tracks"); }); - modelBuilder.Entity("BackEnd.Data.ConferenceAttendee", b => - { - b.HasOne("BackEnd.Data.Attendee", "Attendee") - .WithMany("ConferenceAttendees") - .HasForeignKey("AttendeeID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("BackEnd.Data.Conference", "Conference") - .WithMany("ConferenceAttendees") - .HasForeignKey("ConferenceID") - .OnDelete(DeleteBehavior.Cascade); - }); - modelBuilder.Entity("BackEnd.Data.Session", b => { - b.HasOne("BackEnd.Data.Conference", "Conference") - .WithMany("Sessions") - .HasForeignKey("ConferenceID") - .OnDelete(DeleteBehavior.Cascade); - b.HasOne("BackEnd.Data.Track", "Track") .WithMany("Sessions") .HasForeignKey("TrackId"); @@ -235,13 +149,15 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) { b.HasOne("BackEnd.Data.Attendee", "Attendee") .WithMany("SessionsAttendees") - .HasForeignKey("AttendeeID") - .OnDelete(DeleteBehavior.Cascade); + .HasForeignKey("AttendeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); b.HasOne("BackEnd.Data.Session", "Session") .WithMany() - .HasForeignKey("SessionID") - .OnDelete(DeleteBehavior.Cascade); + .HasForeignKey("SessionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("BackEnd.Data.SessionSpeaker", b => @@ -249,40 +165,14 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.HasOne("BackEnd.Data.Session", "Session") .WithMany("SessionSpeakers") .HasForeignKey("SessionId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); b.HasOne("BackEnd.Data.Speaker", "Speaker") .WithMany("SessionSpeakers") .HasForeignKey("SpeakerId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("BackEnd.Data.SessionTag", b => - { - b.HasOne("BackEnd.Data.Session", "Session") - .WithMany("SessionTags") - .HasForeignKey("SessionID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("BackEnd.Data.Tag", "Tag") - .WithMany("SessionTags") - .HasForeignKey("TagID") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("BackEnd.Data.Speaker", b => - { - b.HasOne("BackEnd.Data.Conference") - .WithMany("Speakers") - .HasForeignKey("ConferenceID"); - }); - - modelBuilder.Entity("BackEnd.Data.Track", b => - { - b.HasOne("BackEnd.Data.Conference", "Conference") - .WithMany("Tracks") - .HasForeignKey("ConferenceID") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); #pragma warning restore 612, 618 } diff --git a/src/BackEnd/Migrations/20190516073157_Initial.cs b/src/BackEnd/Migrations/20190516073157_Initial.cs new file mode 100644 index 00000000..6ffa8e83 --- /dev/null +++ b/src/BackEnd/Migrations/20190516073157_Initial.cs @@ -0,0 +1,169 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace BackEnd.Migrations +{ + public partial class Initial : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Attendees", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), + FirstName = table.Column(maxLength: 200, nullable: false), + LastName = table.Column(maxLength: 200, nullable: false), + UserName = table.Column(maxLength: 200, nullable: false), + EmailAddress = table.Column(maxLength: 256, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Attendees", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Speakers", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), + Name = table.Column(maxLength: 200, nullable: false), + Bio = table.Column(maxLength: 4000, nullable: true), + WebSite = table.Column(maxLength: 1000, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Speakers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Tracks", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), + Name = table.Column(maxLength: 200, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Tracks", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Sessions", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), + Title = table.Column(maxLength: 200, nullable: false), + Abstract = table.Column(maxLength: 4000, nullable: true), + StartTime = table.Column(nullable: true), + EndTime = table.Column(nullable: true), + TrackId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Sessions", x => x.Id); + table.ForeignKey( + name: "FK_Sessions_Tracks_TrackId", + column: x => x.TrackId, + principalTable: "Tracks", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "SessionAttendee", + columns: table => new + { + SessionId = table.Column(nullable: false), + AttendeeId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SessionAttendee", x => new { x.SessionId, x.AttendeeId }); + table.ForeignKey( + name: "FK_SessionAttendee_Attendees_AttendeeId", + column: x => x.AttendeeId, + principalTable: "Attendees", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_SessionAttendee_Sessions_SessionId", + column: x => x.SessionId, + principalTable: "Sessions", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "SessionSpeaker", + columns: table => new + { + SessionId = table.Column(nullable: false), + SpeakerId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SessionSpeaker", x => new { x.SessionId, x.SpeakerId }); + table.ForeignKey( + name: "FK_SessionSpeaker_Sessions_SessionId", + column: x => x.SessionId, + principalTable: "Sessions", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_SessionSpeaker_Speakers_SpeakerId", + column: x => x.SpeakerId, + principalTable: "Speakers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Attendees_UserName", + table: "Attendees", + column: "UserName", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_SessionAttendee_AttendeeId", + table: "SessionAttendee", + column: "AttendeeId"); + + migrationBuilder.CreateIndex( + name: "IX_Sessions_TrackId", + table: "Sessions", + column: "TrackId"); + + migrationBuilder.CreateIndex( + name: "IX_SessionSpeaker_SpeakerId", + table: "SessionSpeaker", + column: "SpeakerId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "SessionAttendee"); + + migrationBuilder.DropTable( + name: "SessionSpeaker"); + + migrationBuilder.DropTable( + name: "Attendees"); + + migrationBuilder.DropTable( + name: "Sessions"); + + migrationBuilder.DropTable( + name: "Speakers"); + + migrationBuilder.DropTable( + name: "Tracks"); + } + } +} diff --git a/src/BackEnd/Migrations/ApplicationDbContextModelSnapshot.cs b/src/BackEnd/Migrations/ApplicationDbContextModelSnapshot.cs index 5a6fdb03..87450bda 100644 --- a/src/BackEnd/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/BackEnd/Migrations/ApplicationDbContextModelSnapshot.cs @@ -15,13 +15,13 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.1-servicing-10028") + .HasAnnotation("ProductVersion", "3.0.0-preview5.19227.1") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("BackEnd.Data.Attendee", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); @@ -40,7 +40,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasMaxLength(200); - b.HasKey("ID"); + b.HasKey("Id"); b.HasIndex("UserName") .IsUnique(); @@ -48,45 +48,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("Attendees"); }); - modelBuilder.Entity("BackEnd.Data.Conference", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("ID"); - - b.ToTable("Conferences"); - }); - - modelBuilder.Entity("BackEnd.Data.ConferenceAttendee", b => - { - b.Property("ConferenceID"); - - b.Property("AttendeeID"); - - b.HasKey("ConferenceID", "AttendeeID"); - - b.HasIndex("AttendeeID"); - - b.ToTable("ConferenceAttendee"); - }); - modelBuilder.Entity("BackEnd.Data.Session", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("Abstract") .HasMaxLength(4000); - b.Property("ConferenceID"); - b.Property("EndTime"); b.Property("StartTime"); @@ -97,9 +67,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("TrackId"); - b.HasKey("ID"); - - b.HasIndex("ConferenceID"); + b.HasKey("Id"); b.HasIndex("TrackId"); @@ -108,13 +76,13 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("BackEnd.Data.SessionAttendee", b => { - b.Property("SessionID"); + b.Property("SessionId"); - b.Property("AttendeeID"); + b.Property("AttendeeId"); - b.HasKey("SessionID", "AttendeeID"); + b.HasKey("SessionId", "AttendeeId"); - b.HasIndex("AttendeeID"); + b.HasIndex("AttendeeId"); b.ToTable("SessionAttendee"); }); @@ -132,30 +100,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("SessionSpeaker"); }); - modelBuilder.Entity("BackEnd.Data.SessionTag", b => - { - b.Property("SessionID"); - - b.Property("TagID"); - - b.HasKey("SessionID", "TagID"); - - b.HasIndex("TagID"); - - b.ToTable("SessionTag"); - }); - modelBuilder.Entity("BackEnd.Data.Speaker", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("Bio") .HasMaxLength(4000); - b.Property("ConferenceID"); - b.Property("Name") .IsRequired() .HasMaxLength(200); @@ -163,67 +116,28 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("WebSite") .HasMaxLength(1000); - b.HasKey("ID"); - - b.HasIndex("ConferenceID"); + b.HasKey("Id"); b.ToTable("Speakers"); }); - modelBuilder.Entity("BackEnd.Data.Tag", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("Name") - .IsRequired() - .HasMaxLength(32); - - b.HasKey("ID"); - - b.ToTable("Tags"); - }); - modelBuilder.Entity("BackEnd.Data.Track", b => { - b.Property("TrackID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - b.Property("ConferenceID"); - b.Property("Name") .IsRequired() .HasMaxLength(200); - b.HasKey("TrackID"); - - b.HasIndex("ConferenceID"); + b.HasKey("Id"); b.ToTable("Tracks"); }); - modelBuilder.Entity("BackEnd.Data.ConferenceAttendee", b => - { - b.HasOne("BackEnd.Data.Attendee", "Attendee") - .WithMany("ConferenceAttendees") - .HasForeignKey("AttendeeID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("BackEnd.Data.Conference", "Conference") - .WithMany("ConferenceAttendees") - .HasForeignKey("ConferenceID") - .OnDelete(DeleteBehavior.Cascade); - }); - modelBuilder.Entity("BackEnd.Data.Session", b => { - b.HasOne("BackEnd.Data.Conference", "Conference") - .WithMany("Sessions") - .HasForeignKey("ConferenceID") - .OnDelete(DeleteBehavior.Cascade); - b.HasOne("BackEnd.Data.Track", "Track") .WithMany("Sessions") .HasForeignKey("TrackId"); @@ -233,13 +147,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) { b.HasOne("BackEnd.Data.Attendee", "Attendee") .WithMany("SessionsAttendees") - .HasForeignKey("AttendeeID") - .OnDelete(DeleteBehavior.Cascade); + .HasForeignKey("AttendeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); b.HasOne("BackEnd.Data.Session", "Session") .WithMany() - .HasForeignKey("SessionID") - .OnDelete(DeleteBehavior.Cascade); + .HasForeignKey("SessionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); modelBuilder.Entity("BackEnd.Data.SessionSpeaker", b => @@ -247,40 +163,14 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasOne("BackEnd.Data.Session", "Session") .WithMany("SessionSpeakers") .HasForeignKey("SessionId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); b.HasOne("BackEnd.Data.Speaker", "Speaker") .WithMany("SessionSpeakers") .HasForeignKey("SpeakerId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("BackEnd.Data.SessionTag", b => - { - b.HasOne("BackEnd.Data.Session", "Session") - .WithMany("SessionTags") - .HasForeignKey("SessionID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("BackEnd.Data.Tag", "Tag") - .WithMany("SessionTags") - .HasForeignKey("TagID") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("BackEnd.Data.Speaker", b => - { - b.HasOne("BackEnd.Data.Conference") - .WithMany("Speakers") - .HasForeignKey("ConferenceID"); - }); - - modelBuilder.Entity("BackEnd.Data.Track", b => - { - b.HasOne("BackEnd.Data.Conference", "Conference") - .WithMany("Tracks") - .HasForeignKey("ConferenceID") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); #pragma warning restore 612, 618 } diff --git a/src/BackEnd/Startup.cs b/src/BackEnd/Startup.cs index 826a0071..7b0ff14c 100644 --- a/src/BackEnd/Startup.cs +++ b/src/BackEnd/Startup.cs @@ -50,6 +50,7 @@ public void ConfigureServices(IServiceCollection services) services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new OpenApiInfo { Title = "Conference Planner API", Version = "v1" }); + options.DescribeAllEnumsAsStrings(); }); } diff --git a/src/ConferenceDTO/Attendee.cs b/src/ConferenceDTO/Attendee.cs index 39dd372e..bd0e0366 100644 --- a/src/ConferenceDTO/Attendee.cs +++ b/src/ConferenceDTO/Attendee.cs @@ -6,7 +6,7 @@ namespace ConferenceDTO { public class Attendee { - public int ID { get; set; } + public int Id { get; set; } [Required] [StringLength(200)] diff --git a/src/ConferenceDTO/AttendeeResponse.cs b/src/ConferenceDTO/AttendeeResponse.cs index 54a61502..8f75153b 100644 --- a/src/ConferenceDTO/AttendeeResponse.cs +++ b/src/ConferenceDTO/AttendeeResponse.cs @@ -6,8 +6,6 @@ namespace ConferenceDTO { public class AttendeeResponse : Attendee { - public ICollection Conferences { get; set; } = new List(); - public ICollection Sessions { get; set; } = new List(); } } diff --git a/src/ConferenceDTO/Conference.cs b/src/ConferenceDTO/Conference.cs deleted file mode 100644 index af0ef80a..00000000 --- a/src/ConferenceDTO/Conference.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Text; - -namespace ConferenceDTO -{ - public class Conference - { - public int ID { get; set; } - - [Required] - [StringLength(200)] - public string Name { get; set; } - } -} diff --git a/src/ConferenceDTO/ConferenceResponse.cs b/src/ConferenceDTO/ConferenceResponse.cs deleted file mode 100644 index 7043b377..00000000 --- a/src/ConferenceDTO/ConferenceResponse.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace ConferenceDTO -{ - public class ConferenceResponse : Conference - { - public ICollection Sessions { get; set; } = new List(); - - public ICollection Tracks { get; set; } = new List(); - - public ICollection Speakers { get; set; } = new List(); - } -} diff --git a/src/ConferenceDTO/Session.cs b/src/ConferenceDTO/Session.cs index d0ce37ae..c7e23214 100644 --- a/src/ConferenceDTO/Session.cs +++ b/src/ConferenceDTO/Session.cs @@ -7,10 +7,7 @@ namespace ConferenceDTO { public class Session { - public int ID { get; set; } - - [Required] - public int ConferenceID { get; set; } + public int Id { get; set; } [Required] [StringLength(200)] diff --git a/src/ConferenceDTO/SessionResponse.cs b/src/ConferenceDTO/SessionResponse.cs index 432a4ae8..0834be99 100644 --- a/src/ConferenceDTO/SessionResponse.cs +++ b/src/ConferenceDTO/SessionResponse.cs @@ -9,7 +9,5 @@ public class SessionResponse : Session public Track Track { get; set; } public List Speakers { get; set; } = new List(); - - public List Tags { get; set; } = new List(); } } diff --git a/src/ConferenceDTO/Speaker.cs b/src/ConferenceDTO/Speaker.cs index 9674314f..493dd817 100644 --- a/src/ConferenceDTO/Speaker.cs +++ b/src/ConferenceDTO/Speaker.cs @@ -6,7 +6,7 @@ namespace ConferenceDTO { public class Speaker { - public int ID { get; set; } + public int Id { get; set; } [Required] [StringLength(200)] diff --git a/src/ConferenceDTO/Tag.cs b/src/ConferenceDTO/Tag.cs deleted file mode 100644 index d9966b74..00000000 --- a/src/ConferenceDTO/Tag.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; - -namespace ConferenceDTO -{ - public class Tag - { - public int ID { get; set; } - - [Required] - [StringLength(32)] - public string Name { get; set; } - } -} \ No newline at end of file diff --git a/src/ConferenceDTO/TagResponse.cs b/src/ConferenceDTO/TagResponse.cs deleted file mode 100644 index 85f651a8..00000000 --- a/src/ConferenceDTO/TagResponse.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace ConferenceDTO -{ - public class TagResponse : Tag - { - public ICollection Sessions { get; set; } = new List(); - } -} diff --git a/src/ConferenceDTO/Track.cs b/src/ConferenceDTO/Track.cs index 012b9aeb..52a1a045 100644 --- a/src/ConferenceDTO/Track.cs +++ b/src/ConferenceDTO/Track.cs @@ -6,10 +6,7 @@ namespace ConferenceDTO { public class Track { - public int TrackID { get; set; } - - [Required] - public int ConferenceID { get; set; } + public int Id { get; set; } [Required] [StringLength(200)] diff --git a/src/ConferenceDTO/TrackResponse.cs b/src/ConferenceDTO/TrackResponse.cs index 5d26c837..c0ead352 100644 --- a/src/ConferenceDTO/TrackResponse.cs +++ b/src/ConferenceDTO/TrackResponse.cs @@ -6,8 +6,6 @@ namespace ConferenceDTO { public class TrackResponse : Track { - public Conference Conference { get; set; } - public ICollection Sessions { get; set; } = new List(); } } diff --git a/src/FrontEnd/Pages/Admin/EditSession.cshtml b/src/FrontEnd/Pages/Admin/EditSession.cshtml index e3c49064..cb55684a 100644 --- a/src/FrontEnd/Pages/Admin/EditSession.cshtml +++ b/src/FrontEnd/Pages/Admin/EditSession.cshtml @@ -13,8 +13,7 @@
- - +
diff --git a/src/FrontEnd/Pages/Admin/EditSession.cshtml.cs b/src/FrontEnd/Pages/Admin/EditSession.cshtml.cs index c9cc0dfc..55f1db6b 100644 --- a/src/FrontEnd/Pages/Admin/EditSession.cshtml.cs +++ b/src/FrontEnd/Pages/Admin/EditSession.cshtml.cs @@ -30,8 +30,7 @@ public async Task OnGet(int id) var session = await _apiClient.GetSessionAsync(id); Session = new Session { - ID = session.ID, - ConferenceID = session.ConferenceID, + Id = session.Id, TrackId = session.TrackId, Title = session.Title, Abstract = session.Abstract, diff --git a/src/FrontEnd/Pages/Error.cshtml b/src/FrontEnd/Pages/Error.cshtml index b1f3143a..af70a7fa 100644 --- a/src/FrontEnd/Pages/Error.cshtml +++ b/src/FrontEnd/Pages/Error.cshtml @@ -10,7 +10,7 @@ @if (Model.ShowRequestId) {

- Request ID: @Model.RequestId + Request Id: @Model.RequestId

} diff --git a/src/FrontEnd/Pages/Index.cshtml b/src/FrontEnd/Pages/Index.cshtml index d29bcad6..bb1c24ec 100644 --- a/src/FrontEnd/Pages/Index.cshtml +++ b/src/FrontEnd/Pages/Index.cshtml @@ -34,22 +34,22 @@
@session.Track?.Name
diff --git a/src/FrontEnd/Pages/Speakers.cshtml b/src/FrontEnd/Pages/Speakers.cshtml index 3b0f2b29..bab0eb7b 100644 --- a/src/FrontEnd/Pages/Speakers.cshtml +++ b/src/FrontEnd/Pages/Speakers.cshtml @@ -12,11 +12,11 @@ {
- +
diff --git a/src/FrontEnd/Services/ApiClient.cs b/src/FrontEnd/Services/ApiClient.cs index e1740209..7ca0b415 100644 --- a/src/FrontEnd/Services/ApiClient.cs +++ b/src/FrontEnd/Services/ApiClient.cs @@ -110,7 +110,7 @@ public async Task> GetSpeakersAsync() public async Task PutSessionAsync(Session session) { - var response = await _httpClient.PutAsJsonAsync($"/api/sessions/{session.ID}", session); + var response = await _httpClient.PutAsJsonAsync($"/api/sessions/{session.Id}", session); response.EnsureSuccessStatusCode(); } @@ -160,9 +160,9 @@ public async Task> GetSessionsByAttendeeAsync(string name) return new List(); } - var sessionIds = attendee.Sessions.Select(s => s.ID); + var sessionIds = attendee.Sessions.Select(s => s.Id); - sessions.RemoveAll(s => !sessionIds.Contains(s.ID)); + sessions.RemoveAll(s => !sessionIds.Contains(s.Id)); return sessions; } From 4c1899f44545205042a6d440a2ed5e218b6f4b2c Mon Sep 17 00:00:00 2001 From: David Fowler Date: Thu, 16 May 2019 01:10:39 -0700 Subject: [PATCH 04/56] Use username for attendees --- src/BackEnd/BackEnd.csproj | 9 --------- src/BackEnd/Controllers/AttendeesController.cs | 8 ++++---- src/BackEnd/Infrastructure/EntityExtensions.cs | 1 + src/FrontEnd/FrontEnd.csproj | 1 + 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/src/BackEnd/BackEnd.csproj b/src/BackEnd/BackEnd.csproj index fec8b721..50762a6d 100644 --- a/src/BackEnd/BackEnd.csproj +++ b/src/BackEnd/BackEnd.csproj @@ -5,15 +5,6 @@ aspnet-BackEnd-931E56BD-86CB-4A96-BD99-2C6A6ABB0829 - - - - - - - - - diff --git a/src/BackEnd/Controllers/AttendeesController.cs b/src/BackEnd/Controllers/AttendeesController.cs index 43241435..840e29c5 100644 --- a/src/BackEnd/Controllers/AttendeesController.cs +++ b/src/BackEnd/Controllers/AttendeesController.cs @@ -20,12 +20,12 @@ public AttendeesController(ApplicationDbContext db) _db = db; } - [HttpGet("{id}")] - public async Task> Get(string id) + [HttpGet("{username}")] + public async Task> Get(string username) { var attendee = await _db.Attendees.Include(a => a.SessionsAttendees) .ThenInclude(sa => sa.Session) - .SingleOrDefaultAsync(a => a.UserName == id); + .SingleOrDefaultAsync(a => a.UserName == username); if (attendee == null) { @@ -65,7 +65,7 @@ public async Task> Post(ConferenceDTO.Attendee in var result = attendee.MapAttendeeResponse(); - return CreatedAtAction(nameof(Get), new { id = result.UserName }, result); + return CreatedAtAction(nameof(Get), new { username = result.UserName }, result); } [HttpPost("{username}/session/{sessionId}")] diff --git a/src/BackEnd/Infrastructure/EntityExtensions.cs b/src/BackEnd/Infrastructure/EntityExtensions.cs index d148a4d9..36635121 100644 --- a/src/BackEnd/Infrastructure/EntityExtensions.cs +++ b/src/BackEnd/Infrastructure/EntityExtensions.cs @@ -51,6 +51,7 @@ public static ConferenceDTO.AttendeeResponse MapAttendeeResponse(this Attendee a FirstName = attendee.FirstName, LastName = attendee.LastName, UserName = attendee.UserName, + EmailAddress = attendee.EmailAddress, Sessions = attendee.SessionsAttendees? .Select(sa => new ConferenceDTO.Session diff --git a/src/FrontEnd/FrontEnd.csproj b/src/FrontEnd/FrontEnd.csproj index 30eae296..13a08c39 100644 --- a/src/FrontEnd/FrontEnd.csproj +++ b/src/FrontEnd/FrontEnd.csproj @@ -9,6 +9,7 @@ + From 7715b4f92a99c25a638d1371976c5e7b413f8851 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Thu, 16 May 2019 01:22:29 -0700 Subject: [PATCH 05/56] Change filter to middleware --- .../Identity/Pages/Account/Logout.cshtml.cs | 1 - src/FrontEnd/Filters/RequireLoginFilter.cs | 43 ----------------- src/FrontEnd/Filters/SkipWelcomeAttribute.cs | 11 ----- .../Middleware/RequireLoginMiddleware.cs | 46 +++++++++++++++++++ .../Middleware/SkipWelcomeAttribute.cs | 10 ++++ src/FrontEnd/Pages/Welcome.cshtml.cs | 1 - src/FrontEnd/Startup.cs | 8 +--- 7 files changed, 58 insertions(+), 62 deletions(-) delete mode 100644 src/FrontEnd/Filters/RequireLoginFilter.cs delete mode 100644 src/FrontEnd/Filters/SkipWelcomeAttribute.cs create mode 100644 src/FrontEnd/Middleware/RequireLoginMiddleware.cs create mode 100644 src/FrontEnd/Middleware/SkipWelcomeAttribute.cs diff --git a/src/FrontEnd/Areas/Identity/Pages/Account/Logout.cshtml.cs b/src/FrontEnd/Areas/Identity/Pages/Account/Logout.cshtml.cs index 4937bca9..784e0e91 100644 --- a/src/FrontEnd/Areas/Identity/Pages/Account/Logout.cshtml.cs +++ b/src/FrontEnd/Areas/Identity/Pages/Account/Logout.cshtml.cs @@ -8,7 +8,6 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; -using FrontEnd.Filters; namespace FrontEnd.Areas.Identity.Pages.Account { diff --git a/src/FrontEnd/Filters/RequireLoginFilter.cs b/src/FrontEnd/Filters/RequireLoginFilter.cs deleted file mode 100644 index 587fee04..00000000 --- a/src/FrontEnd/Filters/RequireLoginFilter.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.Linq; -using System.Security.Claims; -using System.Threading.Tasks; -using FrontEnd.Filters; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Filters; -using Microsoft.AspNetCore.Mvc.Routing; - -namespace FrontEnd -{ - public class RequireLoginFilter : IAsyncResourceFilter - { - private readonly IUrlHelperFactory _urlHelperFactory; - - public RequireLoginFilter(IUrlHelperFactory urlHelperFactory) - { - _urlHelperFactory = urlHelperFactory; - } - - public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) - { - var urlHelper = _urlHelperFactory.GetUrlHelper(context); - - // If the user is authenticated but not a known attendee *and* we've not marked this page - // to skip attendee welcome, then redirect to the Welcome page - if (context.HttpContext.User.Identity.IsAuthenticated && - !context.Filters.OfType().Any()) - { - var isAttendee = context.HttpContext.User.IsAttendee(); - - if (!isAttendee) - { - // No attendee registerd for this user - context.HttpContext.Response.Redirect(urlHelper.Page("/Welcome")); - - return; - } - } - - await next(); - } - } -} \ No newline at end of file diff --git a/src/FrontEnd/Filters/SkipWelcomeAttribute.cs b/src/FrontEnd/Filters/SkipWelcomeAttribute.cs deleted file mode 100644 index 876bbb60..00000000 --- a/src/FrontEnd/Filters/SkipWelcomeAttribute.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using Microsoft.AspNetCore.Mvc.Filters; - -namespace FrontEnd.Filters -{ - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] - public class SkipWelcomeAttribute : Attribute, IFilterMetadata - { - - } -} diff --git a/src/FrontEnd/Middleware/RequireLoginMiddleware.cs b/src/FrontEnd/Middleware/RequireLoginMiddleware.cs new file mode 100644 index 00000000..f87daece --- /dev/null +++ b/src/FrontEnd/Middleware/RequireLoginMiddleware.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Routing; + +namespace FrontEnd +{ + public class RequireLoginMiddleware + { + private readonly RequestDelegate _next; + private readonly LinkGenerator _linkGenerator; + + public RequireLoginMiddleware(RequestDelegate next, LinkGenerator linkGenerator) + { + _next = next; + _linkGenerator = linkGenerator; + } + + public Task Invoke(HttpContext context) + { + var endpoint = context.GetEndpoint(); + + // If the user is authenticated but not a known attendee *and* we've not marked this page + // to skip attendee welcome, then redirect to the Welcome page + if (context.User.Identity.IsAuthenticated && + endpoint?.Metadata.GetMetadata() == null) + { + var isAttendee = context.User.IsAttendee(); + + if (!isAttendee) + { + var url = _linkGenerator.GetUriByPage(context, page: "/Welcome"); + // No attendee registerd for this user + context.Response.Redirect(url); + + return Task.CompletedTask; + } + } + + return _next(context); + } + } +} diff --git a/src/FrontEnd/Middleware/SkipWelcomeAttribute.cs b/src/FrontEnd/Middleware/SkipWelcomeAttribute.cs new file mode 100644 index 00000000..371f7286 --- /dev/null +++ b/src/FrontEnd/Middleware/SkipWelcomeAttribute.cs @@ -0,0 +1,10 @@ +using System; + +namespace FrontEnd +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] + public class SkipWelcomeAttribute : Attribute + { + + } +} diff --git a/src/FrontEnd/Pages/Welcome.cshtml.cs b/src/FrontEnd/Pages/Welcome.cshtml.cs index fea4cc4c..f0c3662f 100644 --- a/src/FrontEnd/Pages/Welcome.cshtml.cs +++ b/src/FrontEnd/Pages/Welcome.cshtml.cs @@ -3,7 +3,6 @@ using FrontEnd.Pages.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; -using FrontEnd.Filters; using System.Net.Http; using System.Security.Claims; using Microsoft.AspNetCore.Authentication; diff --git a/src/FrontEnd/Startup.cs b/src/FrontEnd/Startup.cs index c69019cf..a04bab05 100644 --- a/src/FrontEnd/Startup.cs +++ b/src/FrontEnd/Startup.cs @@ -22,8 +22,6 @@ public Startup(IConfiguration configuration) public void ConfigureServices(IServiceCollection services) { - services.AddTransient(); - services.AddAuthorization(options => { options.AddPolicy("Admin", policy => @@ -42,10 +40,6 @@ public void ConfigureServices(IServiceCollection services) { options.Conventions.AuthorizeFolder("/Admin", "Admin"); }) - .AddMvcOptions(options => - { - options.Filters.AddService(); - }) .SetCompatibilityVersion(CompatibilityVersion.Version_3_0); services.AddHealthChecks() @@ -78,6 +72,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseAuthentication(); app.UseAuthorization(); + app.UseMiddleware(); + app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); From c6b568b6cb72d82fb4cbb3cd46d15987774d674b Mon Sep 17 00:00:00 2001 From: Damian Edwards Date: Fri, 17 May 2019 16:25:40 -0700 Subject: [PATCH 06/56] Simplify admin user creation (first is admin) --- .../Identity/Pages/Account/Register.cshtml | 8 ------ .../Identity/Pages/Account/Register.cshtml.cs | 26 +++++-------------- src/FrontEnd/Services/AdminService.cs | 3 --- src/FrontEnd/Services/IAdminService.cs | 2 -- src/FrontEnd/Startup.cs | 2 +- 5 files changed, 7 insertions(+), 34 deletions(-) diff --git a/src/FrontEnd/Areas/Identity/Pages/Account/Register.cshtml b/src/FrontEnd/Areas/Identity/Pages/Account/Register.cshtml index 242ca807..284ef7b6 100644 --- a/src/FrontEnd/Areas/Identity/Pages/Account/Register.cshtml +++ b/src/FrontEnd/Areas/Identity/Pages/Account/Register.cshtml @@ -27,14 +27,6 @@
- @if (Model.AllowAdminCreation) - { -
- - - -
- }
diff --git a/src/FrontEnd/Areas/Identity/Pages/Account/Register.cshtml.cs b/src/FrontEnd/Areas/Identity/Pages/Account/Register.cshtml.cs index 8b4c3f26..28b6c80f 100644 --- a/src/FrontEnd/Areas/Identity/Pages/Account/Register.cshtml.cs +++ b/src/FrontEnd/Areas/Identity/Pages/Account/Register.cshtml.cs @@ -9,6 +9,7 @@ using Microsoft.Extensions.Logging; using FrontEnd.Data; using FrontEnd.Services; +using Microsoft.AspNetCore.Mvc.Filters; namespace FrontEnd.Areas.Identity.Pages.Account { @@ -20,22 +21,19 @@ public class RegisterModel : PageModel private readonly ILogger _logger; private readonly IEmailSender _emailSender; private readonly IAdminService _adminService; - private readonly IdentityDbContext _dbContext; public RegisterModel( UserManager userManager, SignInManager signInManager, ILogger logger, IEmailSender emailSender, - IAdminService adminService, - IdentityDbContext dbContext) + IAdminService adminService) { _userManager = userManager; _signInManager = signInManager; _logger = logger; _emailSender = emailSender; _adminService = adminService; - _dbContext = dbContext; } [BindProperty] @@ -43,8 +41,6 @@ public RegisterModel( public string ReturnUrl { get; set; } - public bool AllowAdminCreation { get; set; } - public class InputModel { [Required] @@ -62,31 +58,21 @@ public class InputModel [Display(Name = "Confirm password")] [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] public string ConfirmPassword { get; set; } - - [DataType(DataType.Password)] - [Display(Name = "Admin creation key")] - public long? AdminCreationKey { get; set; } } - public async Task OnGetAsync(string returnUrl = null) + public void OnGet(string returnUrl = null) { ReturnUrl = returnUrl; - - if (await _adminService.AllowAdminUserCreationAsync()) - { - AllowAdminCreation = true; - _logger.LogInformation("Admin creation is enabled. Use the following key to create an admin user: {adminKey}", _adminService.CreationKey); - } } public async Task OnPostAsync(string returnUrl = null) { - returnUrl = returnUrl ?? Url.Content("~/"); + returnUrl ??= Url.Content("~/"); if (ModelState.IsValid) { var user = new User { UserName = Input.Email, Email = Input.Email }; - if (await _adminService.AllowAdminUserCreationAsync() && Input.AdminCreationKey == _adminService.CreationKey) + if (await _adminService.AllowAdminUserCreationAsync()) { // Set as admin user user.IsAdmin = true; @@ -109,7 +95,7 @@ public async Task OnPostAsync(string returnUrl = null) var callbackUrl = Url.Page( "/Account/ConfirmEmail", pageHandler: null, - values: new { userId = user.Id, code = code }, + values: new { userId = user.Id, code }, protocol: Request.Scheme); await _emailSender.SendEmailAsync(Input.Email, "Confirm your email", diff --git a/src/FrontEnd/Services/AdminService.cs b/src/FrontEnd/Services/AdminService.cs index 7b85a2a1..9df2b883 100644 --- a/src/FrontEnd/Services/AdminService.cs +++ b/src/FrontEnd/Services/AdminService.cs @@ -8,7 +8,6 @@ namespace FrontEnd.Services { public class AdminService : IAdminService { - private readonly Lazy _creationKey = new Lazy(() => BitConverter.ToInt64(Guid.NewGuid().ToByteArray(), 7)); private readonly IServiceProvider _serviceProvider; private bool _adminExists; @@ -18,8 +17,6 @@ public AdminService(IServiceProvider serviceProvider) _serviceProvider = serviceProvider; } - public long CreationKey => _creationKey.Value; - public async Task AllowAdminUserCreationAsync() { if (_adminExists) diff --git a/src/FrontEnd/Services/IAdminService.cs b/src/FrontEnd/Services/IAdminService.cs index d65c5b91..002c49cd 100644 --- a/src/FrontEnd/Services/IAdminService.cs +++ b/src/FrontEnd/Services/IAdminService.cs @@ -4,8 +4,6 @@ namespace FrontEnd.Services { public interface IAdminService { - long CreationKey { get; } - Task AllowAdminUserCreationAsync(); } } \ No newline at end of file diff --git a/src/FrontEnd/Startup.cs b/src/FrontEnd/Startup.cs index a04bab05..e08a2c27 100644 --- a/src/FrontEnd/Startup.cs +++ b/src/FrontEnd/Startup.cs @@ -62,7 +62,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseHsts(); } - //app.UseStatusCodePagesWithReExecute("/Status/{0}"); + app.UseStatusCodePagesWithReExecute("/Status/{0}"); app.UseHttpsRedirection(); app.UseStaticFiles(); From 0729467d360694ec7eac0f58299dacb1f4ad40ef Mon Sep 17 00:00:00 2001 From: Damian Edwards Date: Fri, 17 May 2019 17:46:14 -0700 Subject: [PATCH 07/56] Cache conference data on home page. MyAgenda page needs to be fixed to use updated logic. --- src/FrontEnd/Infrastructure/CacheKeys.cs | 12 +++ .../Pages/Admin/EditSession.cshtml.cs | 10 ++- src/FrontEnd/Pages/Index.cshtml | 12 +-- src/FrontEnd/Pages/Index.cshtml.cs | 90 ++++++++++++------- src/FrontEnd/Pages/MyAgenda.cshtml | 8 +- src/FrontEnd/Pages/MyAgenda.cshtml.cs | 10 ++- 6 files changed, 97 insertions(+), 45 deletions(-) create mode 100644 src/FrontEnd/Infrastructure/CacheKeys.cs diff --git a/src/FrontEnd/Infrastructure/CacheKeys.cs b/src/FrontEnd/Infrastructure/CacheKeys.cs new file mode 100644 index 00000000..396092db --- /dev/null +++ b/src/FrontEnd/Infrastructure/CacheKeys.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace FrontEnd.Infrastructure +{ + public class CacheKeys + { + public static readonly object ConferenceData = new object(); + } +} diff --git a/src/FrontEnd/Pages/Admin/EditSession.cshtml.cs b/src/FrontEnd/Pages/Admin/EditSession.cshtml.cs index 55f1db6b..599d8ab4 100644 --- a/src/FrontEnd/Pages/Admin/EditSession.cshtml.cs +++ b/src/FrontEnd/Pages/Admin/EditSession.cshtml.cs @@ -5,16 +5,20 @@ using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Caching.Memory; +using FrontEnd.Infrastructure; namespace FrontEnd.Pages { public class EditSessionModel : PageModel { private readonly IApiClient _apiClient; + private readonly IMemoryCache _cache; - public EditSessionModel(IApiClient apiClient) + public EditSessionModel(IApiClient apiClient, IMemoryCache cache) { _apiClient = apiClient; + _cache = cache; } [BindProperty] @@ -48,6 +52,8 @@ public async Task OnPostAsync() await _apiClient.PutSessionAsync(Session); + _cache.Remove(CacheKeys.ConferenceData); + Message = "Session updated successfully!"; return RedirectToPage(); @@ -62,6 +68,8 @@ public async Task OnPostDeleteAsync(int id) await _apiClient.DeleteSessionAsync(id); } + _cache.Remove(CacheKeys.ConferenceData); + Message = "Session deleted successfully!"; return RedirectToPage("/Index"); diff --git a/src/FrontEnd/Pages/Index.cshtml b/src/FrontEnd/Pages/Index.cshtml index bb1c24ec..e5bae0ea 100644 --- a/src/FrontEnd/Pages/Index.cshtml +++ b/src/FrontEnd/Pages/Index.cshtml @@ -16,7 +16,7 @@

My Conference @System.DateTime.Now.Year

- @foreach (var timeSlot in Model.Sessions) + @foreach (var timeSlot in Model.ConferenceModel[Model.CurrentDayOffset]) {

@timeSlot.Key?.ToString("HH:mm")

@@ -45,19 +45,19 @@ } -
+

Edit - @if (Model.UserSessions.Contains(session.Id)) + @if (Model.UserSessions?.Contains(session.Id) ?? false) { - } else { - } diff --git a/src/FrontEnd/Pages/Index.cshtml.cs b/src/FrontEnd/Pages/Index.cshtml.cs index a67f6947..1d6b7114 100644 --- a/src/FrontEnd/Pages/Index.cshtml.cs +++ b/src/FrontEnd/Pages/Index.cshtml.cs @@ -3,24 +3,26 @@ using System.Linq; using System.Threading.Tasks; using ConferenceDTO; +using FrontEnd.Infrastructure; using FrontEnd.Services; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.Extensions.Caching.Memory; namespace FrontEnd.Pages { public class IndexModel : PageModel { protected readonly IApiClient _apiClient; + private readonly IMemoryCache _cache; - public IndexModel(IApiClient apiClient) + public IndexModel(IApiClient apiClient, IMemoryCache cache) { _apiClient = apiClient; + _cache = cache; } - public IEnumerable> Sessions { get; set; } - - public IEnumerable<(int Offset, DayOfWeek? DayofWeek)> DayOffsets { get; set; } + public ConferenceData ConferenceModel { get; private set; } public List UserSessions { get; set; } @@ -31,49 +33,77 @@ public IndexModel(IApiClient apiClient) public bool ShowMessage => !string.IsNullOrEmpty(Message); - protected virtual Task> GetSessionsAsync() + public async Task OnGetAsync(int day = 0) { - return _apiClient.GetSessionsAsync(); + CurrentDayOffset = day; + + if (User.Identity.IsAuthenticated) + { + var userSessions = await _apiClient.GetSessionsByAttendeeAsync(User.Identity.Name); + + UserSessions = userSessions.Select(u => u.Id).ToList(); + } + + ConferenceModel = await GetConferenceDataAsync(); } + + public async Task OnPostAsync(int sessionId, int day = 0) + { + await _apiClient.AddSessionToAttendeeAsync(User.Identity.Name, sessionId); - public async Task OnGetAsync(int day = 0) + return RedirectToPage(new { day }); + } + + public async Task OnPostRemoveAsync(int sessionId, int day = 0) { - CurrentDayOffset = day; + await _apiClient.RemoveSessionFromAttendeeAsync(User.Identity.Name, sessionId); - var userSessions = await _apiClient.GetSessionsByAttendeeAsync(User.Identity.Name); + return RedirectToPage(new { day }); + } - UserSessions = userSessions.Select(u => u.Id).ToList(); + protected virtual Task GetConferenceDataAsync() + { + return _cache.GetOrCreateAsync(CacheKeys.ConferenceData, async entry => + { + var sessions = await _apiClient.GetSessionsAsync(); - var sessions = await GetSessionsAsync(); + var startDate = sessions.Min(s => s.StartTime?.Date); + var endDate = sessions.Max(s => s.EndTime?.Date); - var startDate = sessions.Min(s => s.StartTime?.Date); - var endDate = sessions.Max(s => s.EndTime?.Date); + var numberOfDays = ((endDate - startDate)?.Days + 1) ?? 0; - var numberOfDays = ((endDate - startDate)?.Days) + 1; + var dict = new ConferenceData(numberOfDays); - DayOffsets = Enumerable.Range(0, numberOfDays ?? 0) - .Select(offset => (offset, (startDate?.AddDays(offset))?.DayOfWeek)); + for (int i = 0; i < numberOfDays; i++) + { + var filterDate = startDate?.AddDays(i); - var filterDate = startDate?.AddDays(day); + dict[i] = sessions.Where(s => s.StartTime?.Date == filterDate) + .OrderBy(s => s.TrackId) + .GroupBy(s => s.StartTime) + .OrderBy(g => g.Key); + } - Sessions = sessions.Where(s => s.StartTime?.Date == filterDate) - .OrderBy(s => s.TrackId) - .GroupBy(s => s.StartTime) - .OrderBy(g => g.Key); - } - - public async Task OnPostAsync(int sessionId) - { - await _apiClient.AddSessionToAttendeeAsync(User.Identity.Name, sessionId); + entry.SetSlidingExpiration(TimeSpan.FromHours(1)); - return RedirectToPage(); + dict.StartDate = startDate; + dict.EndDate = endDate; + dict.DayOffsets = Enumerable.Range(0, numberOfDays) + .Select(offset => (offset, (startDate?.AddDays(offset))?.DayOfWeek)); + + return dict; + }); } - public async Task OnPostRemoveAsync(int sessionId) + public class ConferenceData : Dictionary>> { - await _apiClient.RemoveSessionFromAttendeeAsync(User.Identity.Name, sessionId); + public ConferenceData(int capacity) : base(capacity) + { + } - return RedirectToPage(); + public DateTimeOffset? StartDate { get; set; } + public DateTimeOffset? EndDate { get; set; } + public IEnumerable<(int Offset, DayOfWeek? DayofWeek)> DayOffsets { get; set; } } } } diff --git a/src/FrontEnd/Pages/MyAgenda.cshtml b/src/FrontEnd/Pages/MyAgenda.cshtml index 3a90f450..eadeacff 100644 --- a/src/FrontEnd/Pages/MyAgenda.cshtml +++ b/src/FrontEnd/Pages/MyAgenda.cshtml @@ -25,15 +25,15 @@ }

- @foreach (var timeSlot in Model.Sessions) + @*@foreach (var timeSlot in Model.Sessions) {

@timeSlot.Key?.ToString("HH:mm")

@@ -77,5 +77,5 @@
}
- } + }*@
\ No newline at end of file diff --git a/src/FrontEnd/Pages/MyAgenda.cshtml.cs b/src/FrontEnd/Pages/MyAgenda.cshtml.cs index 39ed1f3d..59ccf9c0 100644 --- a/src/FrontEnd/Pages/MyAgenda.cshtml.cs +++ b/src/FrontEnd/Pages/MyAgenda.cshtml.cs @@ -5,21 +5,23 @@ using ConferenceDTO; using FrontEnd.Services; using Microsoft.AspNetCore.Authorization; +using Microsoft.Extensions.Caching.Memory; namespace FrontEnd.Pages { [Authorize] public class MyAgendaModel : IndexModel { - public MyAgendaModel(IApiClient client) - : base(client) + public MyAgendaModel(IApiClient client, IMemoryCache cache) + : base(client, cache) { } - protected override Task> GetSessionsAsync() + protected override Task GetConferenceDataAsync() { - return _apiClient.GetSessionsByAttendeeAsync(User.Identity.Name); + throw new Exception("later asshole"); + //return _apiClient.GetSessionsByAttendeeAsync(User.Identity.Name); } } } \ No newline at end of file From 7994588975652e76ab0ec4f9d9c13e894c3f68d4 Mon Sep 17 00:00:00 2001 From: Damian Edwards Date: Fri, 24 May 2019 12:54:33 -0700 Subject: [PATCH 08/56] ExcludeAssets="runtime" for scaffolding package to prevent Roslyn, etc. from appearing in app's build output --- src/BackEnd/BackEnd.csproj | 12 ++++++++++++ src/FrontEnd/FrontEnd.csproj | 13 ++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/BackEnd/BackEnd.csproj b/src/BackEnd/BackEnd.csproj index 50762a6d..f8c0367f 100644 --- a/src/BackEnd/BackEnd.csproj +++ b/src/BackEnd/BackEnd.csproj @@ -5,6 +5,17 @@ aspnet-BackEnd-931E56BD-86CB-4A96-BD99-2C6A6ABB0829 + + + $(RestoreSources); + https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json; + https://dotnetfeed.blob.core.windows.net/dotnet-windowsdesktop/index.json; + https://dotnetfeed.blob.core.windows.net/aspnet-aspnetcore/index.json; + https://dotnetfeed.blob.core.windows.net/aspnet-extensions/index.json; + https://api.nuget.org/v3/index.json; + + + @@ -13,6 +24,7 @@ + diff --git a/src/FrontEnd/FrontEnd.csproj b/src/FrontEnd/FrontEnd.csproj index 13a08c39..d740cbf9 100644 --- a/src/FrontEnd/FrontEnd.csproj +++ b/src/FrontEnd/FrontEnd.csproj @@ -5,6 +5,17 @@ aspnet-FrontEnd-18BDC1FA-5BA8-408A-BC82-D8DB0496B86B + + + $(RestoreSources); + https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json; + https://dotnetfeed.blob.core.windows.net/dotnet-windowsdesktop/index.json; + https://dotnetfeed.blob.core.windows.net/aspnet-aspnetcore/index.json; + https://dotnetfeed.blob.core.windows.net/aspnet-extensions/index.json; + https://api.nuget.org/v3/index.json; + + + @@ -14,7 +25,7 @@ - + From 0d3d67fb5af30219baf33d67a530fb77cc151c1d Mon Sep 17 00:00:00 2001 From: Damian Edwards Date: Fri, 24 May 2019 14:40:15 -0700 Subject: [PATCH 09/56] Move session abstract line formatting to the razor file --- src/FrontEnd/Pages/Session.cshtml | 7 ++++++- src/FrontEnd/Pages/Session.cshtml.cs | 6 ------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/FrontEnd/Pages/Session.cshtml b/src/FrontEnd/Pages/Session.cshtml index ddfa3e75..ebddd0eb 100644 --- a/src/FrontEnd/Pages/Session.cshtml +++ b/src/FrontEnd/Pages/Session.cshtml @@ -18,7 +18,12 @@ @speaker.Name } -

@Html.Raw(Model.Session.Abstract)

+@foreach (var line in Model.Session.Abstract.Split("\r\n", StringSplitOptions.RemoveEmptyEntries)) +{ +

+ @line +

+} diff --git a/src/FrontEnd/Pages/Session.cshtml.cs b/src/FrontEnd/Pages/Session.cshtml.cs index 9b4f31fa..e86ba00e 100644 --- a/src/FrontEnd/Pages/Session.cshtml.cs +++ b/src/FrontEnd/Pages/Session.cshtml.cs @@ -5,7 +5,6 @@ using ConferenceDTO; using FrontEnd.Services; using Microsoft.AspNetCore.Mvc.RazorPages; -using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace FrontEnd.Pages @@ -44,11 +43,6 @@ public async Task OnGetAsync(int id) DayOffset = Session.StartTime?.Subtract(startDate ?? DateTimeOffset.MinValue).Days; - if (!string.IsNullOrEmpty(Session.Abstract)) - { - Session.Abstract = "

" + String.Join("

", Session.Abstract.Split("\r\n", StringSplitOptions.RemoveEmptyEntries)) + "

"; - } - return Page(); } From e2ac852daa87d7bb187d933d8843bc9d710293c2 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Fri, 31 May 2019 20:31:49 -0700 Subject: [PATCH 10/56] Use System.Text.Json on the backend --- src/BackEnd/BackEnd.csproj | 1 - src/BackEnd/Controllers/SearchController.cs | 9 ++++----- src/BackEnd/Startup.cs | 5 ++++- src/ConferenceDTO/ConferenceDTO.csproj | 1 - src/ConferenceDTO/SearchResult.cs | 8 +++----- src/FrontEnd/Pages/Search.cshtml | 18 +++++++++--------- src/FrontEnd/Pages/Search.cshtml.cs | 17 ++--------------- 7 files changed, 22 insertions(+), 37 deletions(-) diff --git a/src/BackEnd/BackEnd.csproj b/src/BackEnd/BackEnd.csproj index f8c0367f..6a468baa 100644 --- a/src/BackEnd/BackEnd.csproj +++ b/src/BackEnd/BackEnd.csproj @@ -17,7 +17,6 @@ - diff --git a/src/BackEnd/Controllers/SearchController.cs b/src/BackEnd/Controllers/SearchController.cs index ccefdaf9..b4770029 100644 --- a/src/BackEnd/Controllers/SearchController.cs +++ b/src/BackEnd/Controllers/SearchController.cs @@ -5,7 +5,6 @@ using ConferenceDTO; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -using Newtonsoft.Json.Linq; namespace BackEnd { @@ -45,7 +44,7 @@ public async Task>> Search(SearchTerm term) var results = sessionResults.Select(s => new SearchResult { Type = SearchResultType.Session, - Value = JObject.FromObject(new SessionResponse + Session = new SessionResponse { Id = s.Id, Title = s.Title, @@ -65,12 +64,12 @@ public async Task>> Search(SearchTerm term) Name = ss.Speaker.Name }) .ToList() - }) + } }) .Concat(speakerResults.Select(s => new SearchResult { Type = SearchResultType.Speaker, - Value = JObject.FromObject(new SpeakerResponse + Speaker = new SpeakerResponse { Id = s.Id, Name = s.Name, @@ -84,7 +83,7 @@ public async Task>> Search(SearchTerm term) Title = ss.Session.Title }) .ToList() - }) + } })); return results.ToList(); diff --git a/src/BackEnd/Startup.cs b/src/BackEnd/Startup.cs index 7b0ff14c..1c0bbcec 100644 --- a/src/BackEnd/Startup.cs +++ b/src/BackEnd/Startup.cs @@ -41,7 +41,10 @@ public void ConfigureServices(IServiceCollection services) }); services.AddControllers() - .AddNewtonsoftJson() + .AddMvcOptions(o => + { + o.SerializerOptions.PropertyNameCaseInsensitive = true; + }) .SetCompatibilityVersion(CompatibilityVersion.Version_3_0); services.AddHealthChecks() diff --git a/src/ConferenceDTO/ConferenceDTO.csproj b/src/ConferenceDTO/ConferenceDTO.csproj index 99a388fa..4fc81985 100644 --- a/src/ConferenceDTO/ConferenceDTO.csproj +++ b/src/ConferenceDTO/ConferenceDTO.csproj @@ -5,7 +5,6 @@ -
diff --git a/src/ConferenceDTO/SearchResult.cs b/src/ConferenceDTO/SearchResult.cs index d4d57bdd..63bfc59b 100644 --- a/src/ConferenceDTO/SearchResult.cs +++ b/src/ConferenceDTO/SearchResult.cs @@ -1,18 +1,16 @@ -using Newtonsoft.Json.Linq; - namespace ConferenceDTO { public class SearchResult { public SearchResultType Type { get; set; } - public JObject Value { get; set; } + public SessionResponse Session { get; set; } + + public SpeakerResponse Speaker { get; set; } } public enum SearchResultType { - Attendee, - Conference, Session, Track, Speaker diff --git a/src/FrontEnd/Pages/Search.cshtml b/src/FrontEnd/Pages/Search.cshtml index be8f3210..be5caa68 100644 --- a/src/FrontEnd/Pages/Search.cshtml +++ b/src/FrontEnd/Pages/Search.cshtml @@ -24,39 +24,39 @@ @foreach (var result in Model.SearchResults) {
- @switch (result) + @switch (result.Type) { - case SpeakerResponse speaker: + case SearchResultType.Speaker:
-

Speaker: @speaker.Name

+

Speaker: @result.Speaker.Name

- @foreach (var session in speaker.Sessions) + @foreach (var session in result.Speaker.Sessions) { @session.Title }

- @speaker.Bio + @result.Speaker.Bio

break; - case SessionResponse session: + case SearchResultType.Session:
-

Session: @session.Title

- @foreach (var speaker in session.Speakers) +

Session: @result.Session.Title

+ @foreach (var speaker in result.Session.Speakers) { @speaker.Name }

- @session.Abstract + @result.Session.Abstract

diff --git a/src/FrontEnd/Pages/Search.cshtml.cs b/src/FrontEnd/Pages/Search.cshtml.cs index 460f49b6..5c748ff8 100644 --- a/src/FrontEnd/Pages/Search.cshtml.cs +++ b/src/FrontEnd/Pages/Search.cshtml.cs @@ -18,25 +18,12 @@ public SearchModel(IApiClient apiClient) public string Term { get; set; } - public List SearchResults { get; set; } + public List SearchResults { get; set; } public async Task OnGetAsync(string term) { Term = term; - var results = await _apiClient.SearchAsync(term); - SearchResults = results.Select(sr => - { - switch (sr.Type) - { - case SearchResultType.Session: - return (object)sr.Value.ToObject(); - case SearchResultType.Speaker: - return (object)sr.Value.ToObject(); - default: - return (object)sr; - } - }) - .ToList(); + SearchResults = await _apiClient.SearchAsync(term); } } } \ No newline at end of file From ec719196d316df44576238e75e5d557b4080be90 Mon Sep 17 00:00:00 2001 From: DamianEdwards Date: Tue, 11 Jun 2019 15:07:59 -0700 Subject: [PATCH 11/56] Moved to preview6 - Moved to 3.0.0-preview6 - Roll EF Core back to 2.2 in BackEnd as the new query engine doesn't work there yet - Fix PackageReferences for dev dependencies so build/publish output is clean --- src/BackEnd/BackEnd.csproj | 28 +++++++++++++-------- src/BackEnd/Properties/launchSettings.json | 3 +-- src/BackEnd/Startup.cs | 4 --- src/FrontEnd/FrontEnd.csproj | 29 ++++++++++++---------- src/FrontEnd/appsettings.json | 2 +- 5 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/BackEnd/BackEnd.csproj b/src/BackEnd/BackEnd.csproj index 6a468baa..6b7e8bd8 100644 --- a/src/BackEnd/BackEnd.csproj +++ b/src/BackEnd/BackEnd.csproj @@ -8,26 +8,34 @@ $(RestoreSources); - https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json; - https://dotnetfeed.blob.core.windows.net/dotnet-windowsdesktop/index.json; - https://dotnetfeed.blob.core.windows.net/aspnet-aspnetcore/index.json; - https://dotnetfeed.blob.core.windows.net/aspnet-extensions/index.json; + https://dotnetfeed.blob.core.windows.net/dotnet-core-preview6-012264/index.json; https://api.nuget.org/v3/index.json; - - - - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + diff --git a/src/BackEnd/Properties/launchSettings.json b/src/BackEnd/Properties/launchSettings.json index 53f3f06e..e5a76b2a 100644 --- a/src/BackEnd/Properties/launchSettings.json +++ b/src/BackEnd/Properties/launchSettings.json @@ -12,8 +12,7 @@ "commandName": "IISExpress", "launchBrowser": true, "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development", - "AASPNETCORE_HTTPS_PORT": "44360" + "ASPNETCORE_ENVIRONMENT": "Development" } }, "BackEnd": { diff --git a/src/BackEnd/Startup.cs b/src/BackEnd/Startup.cs index 1c0bbcec..30fa5655 100644 --- a/src/BackEnd/Startup.cs +++ b/src/BackEnd/Startup.cs @@ -41,10 +41,6 @@ public void ConfigureServices(IServiceCollection services) }); services.AddControllers() - .AddMvcOptions(o => - { - o.SerializerOptions.PropertyNameCaseInsensitive = true; - }) .SetCompatibilityVersion(CompatibilityVersion.Version_3_0); services.AddHealthChecks() diff --git a/src/FrontEnd/FrontEnd.csproj b/src/FrontEnd/FrontEnd.csproj index d740cbf9..e0822ac8 100644 --- a/src/FrontEnd/FrontEnd.csproj +++ b/src/FrontEnd/FrontEnd.csproj @@ -8,24 +8,27 @@ $(RestoreSources); - https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json; - https://dotnetfeed.blob.core.windows.net/dotnet-windowsdesktop/index.json; - https://dotnetfeed.blob.core.windows.net/aspnet-aspnetcore/index.json; - https://dotnetfeed.blob.core.windows.net/aspnet-extensions/index.json; + https://dotnetfeed.blob.core.windows.net/dotnet-core-preview6-012264/index.json; https://api.nuget.org/v3/index.json; - - - - - - - - - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/FrontEnd/appsettings.json b/src/FrontEnd/appsettings.json index 185f3f5c..c72afbf3 100644 --- a/src/FrontEnd/appsettings.json +++ b/src/FrontEnd/appsettings.json @@ -1,5 +1,5 @@ { - "ServiceUrl": "http://localhost:56009/", + "ServiceUrl": "https://localhost:44360/", "Logging": { "IncludeScopes": false, "LogLevel": { From e40f69aa362a68d6c5f0ede10a7ee53cec14600d Mon Sep 17 00:00:00 2001 From: David Fowler Date: Fri, 14 Jun 2019 12:05:27 -0700 Subject: [PATCH 12/56] Removed feeds --- src/BackEnd/BackEnd.csproj | 8 -------- src/FrontEnd/FrontEnd.csproj | 8 -------- 2 files changed, 16 deletions(-) diff --git a/src/BackEnd/BackEnd.csproj b/src/BackEnd/BackEnd.csproj index 6b7e8bd8..9c2da783 100644 --- a/src/BackEnd/BackEnd.csproj +++ b/src/BackEnd/BackEnd.csproj @@ -4,14 +4,6 @@ netcoreapp3.0 aspnet-BackEnd-931E56BD-86CB-4A96-BD99-2C6A6ABB0829 - - - - $(RestoreSources); - https://dotnetfeed.blob.core.windows.net/dotnet-core-preview6-012264/index.json; - https://api.nuget.org/v3/index.json; - - diff --git a/src/FrontEnd/FrontEnd.csproj b/src/FrontEnd/FrontEnd.csproj index e0822ac8..c9af7a9f 100644 --- a/src/FrontEnd/FrontEnd.csproj +++ b/src/FrontEnd/FrontEnd.csproj @@ -5,14 +5,6 @@ aspnet-FrontEnd-18BDC1FA-5BA8-408A-BC82-D8DB0496B86B - - - $(RestoreSources); - https://dotnetfeed.blob.core.windows.net/dotnet-core-preview6-012264/index.json; - https://api.nuget.org/v3/index.json; - - - From fd50c148478809d22f627a03886f9e51eba7fa6e Mon Sep 17 00:00:00 2001 From: David Fowler Date: Fri, 14 Jun 2019 21:28:11 -0700 Subject: [PATCH 13/56] 3.0 updates to session 1 and session 2 --- docs/1. Create BackEnd API project.md | 34 ++- docs/2. Build out BackEnd and Refactor.md | 310 +++------------------- src/ConferenceDTO/TrackResponse.cs | 11 - 3 files changed, 64 insertions(+), 291 deletions(-) delete mode 100644 src/ConferenceDTO/TrackResponse.cs diff --git a/docs/1. Create BackEnd API project.md b/docs/1. Create BackEnd API project.md index 0a89eaa7..0a7f6972 100644 --- a/docs/1. Create BackEnd API project.md +++ b/docs/1. Create BackEnd API project.md @@ -1,7 +1,7 @@ ## Creating a basic EF model -1. Create a new solution called `ConferencePlanner`, and add a new project named `BackEnd` using File / New / ASP.NET Core Web Application. Select the Web API template, No Auth, no Docker support. +1. Create and add a new project named `BackEnd` and name the solution `ConferencePlanner` using File / New / ASP.NET Core Web Application. Select the Web API template, No Auth, no Docker support. ![](images/new-solution.png "Creating a new solution in Visual Studio") ![](images/add-project.png "Adding a project to the solution") ![](images/name-backend-project.png "Naming the new Web API project") @@ -19,14 +19,12 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; - using Microsoft.Extensions.DependencyInjection; - using Microsoft.EntityFrameworkCore.Design; namespace BackEnd.Models { public class Speaker { - public int ID { get; set; } + public int Id { get; set; } [Required] [StringLength(200)] @@ -40,6 +38,12 @@ } } ``` +1. Add a reference to the NuGet package `Microsoft.EntityFrameworkCore.SqlServer`. Note that you'll need to resolve several references by adding missing `using` statements (`Ctrl + .` is your friend). + > **If you're not using Visual Studio** install the package from the command line with `dotnet add package Microsoft.EntityFrameworkCore.SqlServer --version 2.2.4` +1. Add a reference to the NuGet package `Microsoft.EntityFrameworkCore.Sqlite`. Note that you'll need to resolve several references by adding missing `using` statements (`Ctrl + .` is your friend). + ![](images/add-sqlite-nuget-reference.png "Adding the SQLite NuGet reference") + + > **If you're not using Visual Studio** install the package from the command line with `dotnet add package Microsoft.EntityFrameworkCore.Sqlite --version 2.2.4` 1. Next we'll create a new Entity Framework DbContext. Create a new `ApplicationDbContext` class in the `Models` folder using the following code: ```csharp using Microsoft.EntityFrameworkCore; @@ -68,7 +72,9 @@ }, "Logging": { "LogLevel": { - "Default": "Warning" + "Default": "Warning", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*" @@ -91,14 +97,14 @@ }); ``` > This code registers the `ApplicationDbContext` service so it can be injected into controllers. Additionally, it configures operating system specific database technologies and connection strings -1. Add a reference to the NuGet package `Microsoft.EntityFrameworkCore.Sqlite`. Note that you'll need to resolve several references by adding missing `using` statements (`Ctrl + .` is your friend). - ![](images/add-sqlite-nuget-reference.png "Adding the SQLite NuGet reference") - - > **If you're not using Visual Studio** install the package from the command line with `dotnet add package Microsoft.EntityFrameworkCore.Sqlite --version 2.2.1` ## Configuring EF Migrations ### Visual Studio: Package Manager Console + +1. Add a reference to the NuGet package `Microsoft.EntityFrameworkCore.Tools`. Note that you'll need to resolve several references by adding missing `using` statements (`Ctrl + .` is your friend). + > **If you're not using Visual Studio** install the package from the command line with `dotnet add package Microsoft.EntityFrameworkCore.Tools --version 2.2.4` + 1. In Visual Studio, select the Tools -> NuGet Package Manager -> Package Manager Console 1. Run the following commands in the Package Manager Console @@ -109,6 +115,8 @@ ### Command line +1. TODO: Install the global tool + 1. Open a command prompt and navigate to the project directory. (The directory containing the `Startup.cs` file). 1. Run the following commands in the command prompt: @@ -140,7 +148,7 @@ First, open the `Controllers` folder and take a quick look at the `ValuesControl ### Using the cmd line 1. Install the "Microsoft.VisualStudio.Web.CodeGeneration.Design" package ``` -dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design --version 2.2.0 +dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design --version 3.0.0-preview5-19264-04 ``` 1. Install the `aspnet-codegenerator` global tool by running the following command: @@ -169,10 +177,10 @@ Additional information on using Swashbuckle in ASP.NET Core is available in this > This can be done from the command line using `dotnet add package Swashbuckle.AspNetCore` 1. Add the Swashbuckle services in your `ConfigureServices` method: ```csharp - services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); + services.AddControllers(); services.AddSwaggerGen(options => - options.SwaggerDoc("v1", new Info { Title = "Conference Planner API", Version = "v1" }) + options.SwaggerDoc("v1", new OpenApiInfo { Title = "Conference Planner API", Version = "v1" }) ); ``` 1. Configure Swashbuckle by adding the following lines to top of the `Configure` method in `Startup.cs`: @@ -183,7 +191,7 @@ Additional information on using Swashbuckle in ASP.NET Core is available in this options.SwaggerEndpoint("/swagger/v1/swagger.json", "Conference Planner API v1") ); ``` - > ***Note:* Due to how the middleware and pipeline are structured, you'll want to place this before the `app.UseMvc()` statement.** + > ***Note:* Due to how the middleware and pipeline are structured, you'll want to place this before the `app.UseEndpoints()` statement.** 1. Add a redirect to the end of the pipeline that redirects to the swagger end point. ```csharp app.Run(context => diff --git a/docs/2. Build out BackEnd and Refactor.md b/docs/2. Build out BackEnd and Refactor.md index 67d60dd7..4560212b 100644 --- a/docs/2. Build out BackEnd and Refactor.md +++ b/docs/2. Build out BackEnd and Refactor.md @@ -53,7 +53,7 @@ We've got several more models to add, and unfortunately it's a little mechanical { public class Attendee { - public int ID { get; set; } + public int Id { get; set; } [Required] [StringLength(200)] @@ -70,26 +70,7 @@ We've got several more models to add, and unfortunately it's a little mechanical [StringLength(256)] public virtual string EmailAddress { get; set; } } - } - ``` -1. Create a `Conference.cs` class with the following code: - ```csharp - using System; - using System.Collections.Generic; - using System.ComponentModel.DataAnnotations; - using System.Text; - - namespace ConferenceDTO - { - public class Conference - { - public int ID { get; set; } - - [Required] - [StringLength(200)] - public string Name { get; set; } - } - } + } ``` 1. Create a `Session.cs` class with the following code: ```csharp @@ -102,10 +83,7 @@ We've got several more models to add, and unfortunately it's a little mechanical { public class Session { - public int ID { get; set; } - - [Required] - public int ConferenceID { get; set; } + public int Id { get; set; } [Required] [StringLength(200)] @@ -125,23 +103,6 @@ We've got several more models to add, and unfortunately it's a little mechanical } } ``` -1. Create a new `Tag.cs` class with the following code: - ```csharp - using System.Collections.Generic; - using System.ComponentModel.DataAnnotations; - - namespace ConferenceDTO - { - public class Tag - { - public int ID { get; set; } - - [Required] - [StringLength(32)] - public string Name { get; set; } - } - } - ``` 1. Create a new `Track.cs` class with the following code: ```csharp using System; @@ -152,10 +113,7 @@ We've got several more models to add, and unfortunately it's a little mechanical { public class Track { - public int TrackID { get; set; } - - [Required] - public int ConferenceID { get; set; } + public int Id { get; set; } [Required] [StringLength(200)] @@ -169,27 +127,6 @@ We're not going to create our EF models directly from the *ConferenceDTO* classe We're also going to take this opportunity to rename the `Models` directory in the *BackEnd* project to `Data` since it no longer just contains models. 1. Right-click the `Models` directory and select `Rename`, changing the name to `Data`. -1. In the *BackEnd* project, add a `ConferenceAttendee.cs` class to the `Data` directory with the following code: - ```csharp - using System; - using System.Collections.Generic; - using System.Linq; - using System.Threading.Tasks; - - namespace BackEnd.Data - { - public class ConferenceAttendee - { - public int ConferenceID { get; set; } - - public Conference Conference { get; set; } - - public int AttendeeID { get; set; } - - public Attendee Attendee { get; set; } - } - } - ``` 1. Add a `SessionSpeaker.cs` class to the `Data` directory with the following code: ```csharp using System; @@ -211,27 +148,6 @@ We're also going to take this opportunity to rename the `Models` directory in th } } ``` -1. Add a `SessionTag.cs` class to the `Data` directory with the following code: - ```csharp - using System; - using System.Collections.Generic; - using System.Linq; - using System.Threading.Tasks; - - namespace BackEnd.Data - { - public class SessionTag - { - public int SessionID { get; set; } - - public Session Session { get; set; } - - public int TagID { get; set; } - - public Tag Tag { get; set; } - } - } - ``` 1. Add an `SessionAttendee.cs` class with the following code: ```csharp using System; @@ -243,11 +159,11 @@ We're also going to take this opportunity to rename the `Models` directory in th { public class SessionAttendee { - public int SessionID { get; set; } + public int SessionId { get; set; } public Session Session { get; set; } - public int AttendeeID { get; set; } + public int AttendeeId { get; set; } public Attendee Attendee { get; set; } } @@ -262,32 +178,10 @@ We're also going to take this opportunity to rename the `Models` directory in th { public class Attendee : ConferenceDTO.Attendee { - public virtual ICollection ConferenceAttendees { get; set; } - public virtual ICollection SessionsAttendees { get; set; } } } ``` -1. Add a `Conference.cs` class with the following code: - ```csharp - using System; - using System.Collections.Generic; - using System.Text; - - namespace BackEnd.Data - { - public class Conference : ConferenceDTO.Conference - { - public virtual ICollection Tracks { get; set; } - - public virtual ICollection Speakers { get; set; } - - public virtual ICollection Sessions { get; set; } - - public virtual ICollection ConferenceAttendees { get; set; } - } - } - ``` 1. Add a `Session.cs` class with the following code: ```csharp using System; @@ -298,13 +192,9 @@ We're also going to take this opportunity to rename the `Models` directory in th { public class Session : ConferenceDTO.Session { - public Conference Conference { get; set; } - public virtual ICollection SessionSpeakers { get; set; } public Track Track { get; set; } - - public virtual ICollection SessionTags { get; set; } } } ``` @@ -322,18 +212,6 @@ We're also going to take this opportunity to rename the `Models` directory in th } ``` -1. Add a `Tag.cs` class with the following code: - ```csharp - using System.Collections.Generic; - - namespace BackEnd.Data - { - public class Tag : ConferenceDTO.Tag - { - public virtual ICollection SessionTags { get; set; } - } - } - ``` 1. Add a `Track.cs` class with the following code: ```csharp using System; @@ -344,9 +222,6 @@ We're also going to take this opportunity to rename the `Models` directory in th { public class Track : ConferenceDTO.Track { - [Required] - public Conference Conference { get; set; } - public virtual ICollection Sessions { get; set; } } } @@ -357,14 +232,7 @@ Okay, now we need to update our `ApplicationDbContext` so Entity Framework knows 1. Update `ApplicationDbContext.cs` to use the following code: ```csharp - using System; - using System.Collections.Generic; - using System.Linq; - using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; - using Microsoft.EntityFrameworkCore.Infrastructure; - using Microsoft.EntityFrameworkCore.Design; - using Microsoft.Extensions.DependencyInjection; namespace BackEnd.Data { @@ -379,38 +247,22 @@ Okay, now we need to update our `ApplicationDbContext` so Entity Framework knows protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity() - .HasIndex(a => a.UserName) - .IsUnique(); - - // Ignore the computed property - modelBuilder.Entity() - .Ignore(s => s.Duration); - - // Many-to-many: Conference <-> Attendee - modelBuilder.Entity() - .HasKey(ca => new { ca.ConferenceID, ca.AttendeeID }); - - // Many-to-many: Session <-> Attendee - modelBuilder.Entity() - .HasKey(ca => new { ca.SessionID, ca.AttendeeID }); - - // Many-to-many: Speaker <-> Session - modelBuilder.Entity() - .HasKey(ss => new { ss.SessionId, ss.SpeakerId }); - - // Many-to-many: Session <-> Tag - modelBuilder.Entity() - .HasKey(st => new { st.SessionID, st.TagID }); - } + .HasIndex(a => a.UserName) + .IsUnique(); - public DbSet Conferences { get; set; } + // Many-to-many: Session <-> Attendee + modelBuilder.Entity() + .HasKey(ca => new { ca.SessionId, ca.AttendeeId }); + + // Many-to-many: Speaker <-> Session + modelBuilder.Entity() + .HasKey(ss => new { ss.SessionId, ss.SpeakerId }); + } public DbSet Sessions { get; set; } public DbSet Tracks { get; set; } - public DbSet Tags { get; set; } - public DbSet Speakers { get; set; } public DbSet Attendees { get; set; } @@ -440,22 +292,14 @@ Okay, now we need to update our `ApplicationDbContext` so Entity Framework knows >Save point for above code changes is [here](/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner) ## Updating the Speakers API controller -1. We'll rename `_context` to `_db`, so your context will appear as shown: - ```csharp - private readonly ApplicationDbContext _db; - - public SpeakersController(ApplicationDbContext db) - { - _db = db; - } - ``` + 1. Modify the query for the `GetSpeakers()` method as shown below: ```csharp - var speakers = await _db.Speakers.AsNoTracking() + var speakers = await _context.Speakers.AsNoTracking() .Include(s => s.SessionSpeakers) .ThenInclude(ss => ss.Session) .ToListAsync(); - return speakers; + return speakers; ``` 1. While the above will work, this is directly returning our model class. A better practice is to return an output model class. Create a `SpeakerResponse.cs` class in the *ConferenceDTO* project with the following code: ```csharp @@ -487,7 +331,7 @@ Okay, now we need to update our `ApplicationDbContext` so Entity Framework knows public static ConferenceDTO.SpeakerResponse MapSpeakerResponse(this Speaker speaker) => new ConferenceDTO.SpeakerResponse { - ID = speaker.ID, + Id = speaker.Id, Name = speaker.Name, Bio = speaker.Bio, WebSite = speaker.WebSite, @@ -495,7 +339,7 @@ Okay, now we need to update our `ApplicationDbContext` so Entity Framework knows .Select(ss => new ConferenceDTO.Session { - ID = ss.SessionId, + Id = ss.SessionId, Title = ss.Session.Title }) .ToList() @@ -508,7 +352,7 @@ Okay, now we need to update our `ApplicationDbContext` so Entity Framework knows [HttpGet] public async Task>> GetSpeakers() { - var speakers = await _db.Speakers.AsNoTracking() + var speakers = await _context.Speakers.AsNoTracking() .Include(s => s.SessionSpeakers) .ThenInclude(ss => ss.Session) .Select(s => s.MapSpeakerResponse()) @@ -518,13 +362,13 @@ Okay, now we need to update our `ApplicationDbContext` so Entity Framework knows ``` 1. Update the `GetSpeaker()` method to use our mapped response models as follows: ```csharp - [HttpGet("{id:int}")] + [HttpGet("{id}")] public async Task> GetSpeaker(int id) { - var speaker = await _db.Speakers.AsNoTracking() + var speaker = await _context.Speakers.AsNoTracking() .Include(s => s.SessionSpeakers) .ThenInclude(ss => ss.Session) - .SingleOrDefaultAsync(s => s.ID == id); + .SingleOrDefaultAsync(s => s.Id == id); if (speaker == null) { return NotFound(); @@ -533,74 +377,15 @@ Okay, now we need to update our `ApplicationDbContext` so Entity Framework knows return result; } ``` -1. Update the remaining actions in the *SpeakerController* as shown below: - ```csharp - [HttpPost] - public async Task> PostSpeaker(ConferenceDTO.Speaker input) - { - var speaker = new Speaker - { - Name = input.Name, - WebSite = input.WebSite, - Bio = input.Bio - }; - - _db.Speakers.Add(speaker); - await _db.SaveChangesAsync(); - - var result = speaker.MapSpeakerResponse(); - - return CreatedAtAction(nameof(GetSpeaker), new { id = speaker.ID }, result); - } - - [HttpPut("{id:int}")] - public async Task PutSpeaker(int id, ConferenceDTO.Speaker input) - { - var speaker = await _db.FindAsync(id); - - if (speaker == null) - { - return NotFound(); - } - - speaker.Name = input.Name; - speaker.WebSite = input.WebSite; - speaker.Bio = input.Bio; - - // TODO: Handle exceptions, e.g. concurrency - await _db.SaveChangesAsync(); - - return NoContent(); - } - - [HttpDelete("{id:int}")] - public async Task> DeleteSpeaker(int id) - { - var speaker = await _db.FindAsync(id); - - if (speaker == null) - { - return NotFound(); - } - - _db.Remove(speaker); - await _db.SaveChangesAsync(); - - return speaker.MapSpeakerResponse(); - } - ``` +1. Remove the other actions. ## Adding the remaining API Controllers 1. Add the following response DTO classes from [the save point folder](/save-points/2b-BackEnd-completed/ConferencePlanner/ConferenceDTO) - `AttendeeResponse` - `SessionResponse` - - `ConferenceResponse` - - `TrackResponse` - - `TagResponse` 1. Update the `EntityExtensions` class with the extra mapping methods from [the save point folder](/save-points/2b-BackEnd-completed/ConferencePlanner/BackEnd/Infrastructure) 1. Copy the following controllers from [the save point folder](/save-points/2b-BackEnd-completed/ConferencePlanner/BackEnd/Controllers) into the current project's `BackEnd/Controllers` directory: - `SessionsController` - - `ConferencesController` - `AttendeesController` ## Update EntityExtensions @@ -619,38 +404,30 @@ Okay, now we need to update our `ApplicationDbContext` so Entity Framework knows public static ConferenceDTO.SessionResponse MapSessionResponse(this Session session) => new ConferenceDTO.SessionResponse { - ID = session.ID, + Id = session.Id, Title = session.Title, StartTime = session.StartTime, EndTime = session.EndTime, - Tags = session.SessionTags? - .Select(st => new ConferenceDTO.Tag - { - ID = st.TagID, - Name = st.Tag.Name - }) - .ToList(), Speakers = session.SessionSpeakers? .Select(ss => new ConferenceDTO.Speaker { - ID = ss.SpeakerId, + Id = ss.SpeakerId, Name = ss.Speaker.Name }) .ToList(), TrackId = session.TrackId, Track = new ConferenceDTO.Track { - TrackID = session?.TrackId ?? 0, + Id = session?.TrackId ?? 0, Name = session.Track?.Name }, - ConferenceID = session.ConferenceID, Abstract = session.Abstract }; public static ConferenceDTO.SpeakerResponse MapSpeakerResponse(this Speaker speaker) => new ConferenceDTO.SpeakerResponse { - ID = speaker.ID, + Id = speaker.Id, Name = speaker.Name, Bio = speaker.Bio, WebSite = speaker.WebSite, @@ -658,7 +435,7 @@ Okay, now we need to update our `ApplicationDbContext` so Entity Framework knows .Select(ss => new ConferenceDTO.Session { - ID = ss.SessionId, + Id = ss.SessionId, Title = ss.Session.Title }) .ToList() @@ -667,28 +444,20 @@ Okay, now we need to update our `ApplicationDbContext` so Entity Framework knows public static ConferenceDTO.AttendeeResponse MapAttendeeResponse(this Attendee attendee) => new ConferenceDTO.AttendeeResponse { - ID = attendee.ID, + Id = attendee.Id, FirstName = attendee.FirstName, LastName = attendee.LastName, UserName = attendee.UserName, Sessions = attendee.SessionsAttendees? - .Select(s => + .Select(sa => new ConferenceDTO.Session { - ID = sa.SessionID, + Id = sa.SessionId, Title = sa.Session.Title, StartTime = sa.Session.StartTime, EndTime = sa.Session.EndTime }) - .ToList(), - Conferences = attendee.ConferenceAttendees? - .Select(ca => - new ConferenceDTO.Conference - { - ID = ca.ConferenceID, - Name = ca.Conference.Name - }) - .ToList(), + .ToList() }; } } @@ -698,8 +467,15 @@ Okay, now we need to update our `ApplicationDbContext` so Entity Framework knows 1. Copy the `DataLoader.cs` class from [here](/src/BackEnd/Data/DataLoader.cs) into the `Data` directory of the `BackEnd` project. 1. Copy the `SessionizeLoader.cs` and `DevIntersectionLoader.cs` classes from [here](/src/BackEnd/Data/) into the current project's `/src/BackEnd/Data/` directory. > Note: We have data loaders from the two conference series where this workshop has been presented most; you can update this to plug in your own conference file format. +1. Turn enums as strings by changing `AddSwaggerGen` in `Startup.cs` to the following: + ``` + services.AddSwaggerGen(options => + { + options.SwaggerDoc("v1", new OpenApiInfo { Title = "Conference Planner API", Version = "v1" }); + options.DescribeAllEnumsAsStrings(); + }); + ``` 1. Run the application to see the updated data via Swagger UI. 1. Use the Swagger UI to upload [NDC_London_2019.json](/src/BackEnd/Data/Import/NDC_London_2019.json) to the `/api/Conferences/upload` API. - **Next**: [Session #3 - Front-end](3.%20Add%20front-end%2C%20render%20agenda%2C%20set%20up%20front-end%20models.md) | **Previous**: [Session #1 - Setup, basic EF model](/docs/1.%20Create%20BackEnd%20API%20project.md) diff --git a/src/ConferenceDTO/TrackResponse.cs b/src/ConferenceDTO/TrackResponse.cs deleted file mode 100644 index c0ead352..00000000 --- a/src/ConferenceDTO/TrackResponse.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace ConferenceDTO -{ - public class TrackResponse : Track - { - public ICollection Sessions { get; set; } = new List(); - } -} From 0435987e3c1ce21fab0859aee0fa9a9602d686c4 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sat, 15 Jun 2019 00:31:01 -0700 Subject: [PATCH 14/56] Finished up to 3 --- docs/2. Build out BackEnd and Refactor.md | 3 +- ... render agenda, set up front-end models.md | 171 ++++++++++-------- .../Controllers/AttendeesController.cs | 2 +- src/BackEnd/Controllers/SearchController.cs | 2 +- src/ConferenceDTO/SearchResult.cs | 1 - 5 files changed, 97 insertions(+), 82 deletions(-) diff --git a/docs/2. Build out BackEnd and Refactor.md b/docs/2. Build out BackEnd and Refactor.md index 4560212b..1b107266 100644 --- a/docs/2. Build out BackEnd and Refactor.md +++ b/docs/2. Build out BackEnd and Refactor.md @@ -373,8 +373,7 @@ Okay, now we need to update our `ApplicationDbContext` so Entity Framework knows { return NotFound(); } - var result = speaker.MapSpeakerResponse(); - return result; + return speaker.MapSpeakerResponse(); } ``` 1. Remove the other actions. diff --git a/docs/3. Add front-end, render agenda, set up front-end models.md b/docs/3. Add front-end, render agenda, set up front-end models.md index d60ad9c9..379c1b50 100644 --- a/docs/3. Add front-end, render agenda, set up front-end models.md +++ b/docs/3. Add front-end, render agenda, set up front-end models.md @@ -56,6 +56,10 @@ In this session, we'll add the front end web site, with a public (anonymous) hom } } ``` +1. Add a reference to the *Microsoft.AspNet.WebApi.Client* NuGet package in the FrontEnd project: + ``` + dotnet add package Microsoft.AspNet.WebApi.Client + ``` 1. Staying in this folder, add a new class called `ApiClient` that implements the `IApiClient` interface by using `HttpClient` to call out to our BackEnd API application and JSON serialize/deserialize the payloads: ``` csharp using System; @@ -170,7 +174,7 @@ In this session, we'll add the front end web site, with a public (anonymous) hom public async Task PutSessionAsync(Session session) { - var response = await _httpClient.PutAsJsonAsync($"/api/sessions/{session.ID}", session); + var response = await _httpClient.PutAsJsonAsync($"/api/sessions/{session.Id}", session); response.EnsureSuccessStatusCode(); } @@ -305,14 +309,14 @@ In this session, we'll add the front end web site, with a public (anonymous) hom
@session.Track?.Name
@@ -456,10 +459,6 @@ In this session, we'll add the front end web site, with a public (anonymous) hom >We'll add a page to allow users to search the conference agenda, finding sessions and speakers that match the supplied search term. ### Add DTOs for search -1. Add a reference to the *Newtonsoft.Json* NuGet package in the DTO project: - ``` - dotnet add package Newtonsoft.Json - ``` 1. Add a new DTO class `SearchTerm` in the DTO project: ```csharp using System; @@ -479,25 +478,23 @@ In this session, we'll add the front end web site, with a public (anonymous) hom using System; using System.Collections.Generic; using System.Text; - using Newtonsoft.Json.Linq; namespace ConferenceDTO { public class SearchResult { - public SearchResultType Type { get; set; } + public SearchResultType Type { get; set; } - public JObject Value { get; set; } - } + public SessionResponse Session { get; set; } - public enum SearchResultType - { - Attendee, - Conference, - Session, - Track, - Speaker - } + public SpeakerResponse Speaker { get; set; } + } + + public enum SearchResultType + { + Session, + Speaker + } } ``` @@ -512,7 +509,6 @@ In this session, we'll add the front end web site, with a public (anonymous) hom using ConferenceDTO; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; - using Newtonsoft.Json.Linq; namespace BackEnd.Controllers { @@ -528,45 +524,73 @@ In this session, we'll add the front end web site, with a public (anonymous) hom } [HttpPost] - public async Task Search(SearchTerm term) + public async Task>> Search(SearchTerm term) { var query = term.Query; - - var sessionResultsTask = _db.Sessions.AsNoTracking() - .Include(s => s.Track) - .Include(s => s.SessionSpeakers) - .ThenInclude(ss => ss.Speaker) - .Where(s => - s.Title.Contains(query) || - s.Track.Name.Contains(query) - ) - .ToListAsync(); - - var speakerResultsTask = _db.Speakers.AsNoTracking() - .Include(s => s.SessionSpeakers) - .ThenInclude(ss => ss.Session) - .Where(s => - s.Name.Contains(query) || - s.Bio.Contains(query) || - s.WebSite.Contains(query) - ) - .ToListAsync(); - - var sessionResults = await sessionResultsTask; - var speakerResults = await speakerResultsTask; + var sessionResults = await _db.Sessions.Include(s => s.Track) + .Include(s => s.SessionSpeakers) + .ThenInclude(ss => ss.Speaker) + .Where(s => + s.Title.Contains(query) || + s.Track.Name.Contains(query) + ) + .ToListAsync(); + + var speakerResults = await _db.Speakers.Include(s => s.SessionSpeakers) + .ThenInclude(ss => ss.Session) + .Where(s => + s.Name.Contains(query) || + s.Bio.Contains(query) || + s.WebSite.Contains(query) + ) + .ToListAsync(); var results = sessionResults.Select(s => new SearchResult { Type = SearchResultType.Session, - Value = JObject.FromObject(s.MapSessionResponse()) + Session = new SessionResponse + { + Id = s.Id, + Title = s.Title, + Abstract = s.Abstract, + StartTime = s.StartTime, + EndTime = s.EndTime, + TrackId = s.TrackId, + Track = new ConferenceDTO.Track + { + Id = s?.TrackId ?? 0, + Name = s.Track?.Name + }, + Speakers = s?.SessionSpeakers + .Select(ss => new ConferenceDTO.Speaker + { + Id = ss.SpeakerId, + Name = ss.Speaker.Name + }) + .ToList() + } }) .Concat(speakerResults.Select(s => new SearchResult { Type = SearchResultType.Speaker, - Value = JObject.FromObject(s.MapSpeakerResponse()) + Speaker = new SpeakerResponse + { + Id = s.Id, + Name = s.Name, + Bio = s.Bio, + WebSite = s.WebSite, + Sessions = s.SessionSpeakers? + .Select(ss => + new ConferenceDTO.Session + { + Id = ss.SessionId, + Title = ss.Session.Title + }) + .ToList() + } })); - return Ok(results); + return results.ToList(); } } } @@ -609,7 +633,7 @@ In this session, we'll add the front end web site, with a public (anonymous) hom public string Term { get; set; } - public List SearchResults { get; set; } + public List SearchResults { get; set; } } ``` 1. Add a page handler method to retrieve the search results and set them on the model, deserializing the individual search items to the relevant model type: @@ -617,20 +641,7 @@ In this session, we'll add the front end web site, with a public (anonymous) hom public async Task OnGetAsync(string term) { Term = term; - var results = await _apiClient.SearchAsync(term); - SearchResults = results.Select(sr => - { - switch (sr.Type) - { - case SearchResultType.Session: - return (object)sr.Value.ToObject(); - case SearchResultType.Speaker: - return (object)sr.Value.ToObject(); - default: - return (object)sr; - } - }) - .ToList(); + SearchResults = await _apiClient.SearchAsync(term); } ``` 1. Open the *Search.cshtml* file and add markup to allow users to enter a search term and display the results, casting each result to the relevant display model type: @@ -661,39 +672,39 @@ In this session, we'll add the front end web site, with a public (anonymous) hom @foreach (var result in Model.SearchResults) {
- @switch (result) + @switch (result.Type) { - case SpeakerResponse speaker: + case SearchResultType.Speaker:
-

Speaker: @speaker.Name

+

Speaker: @result.Speaker.Name

- @foreach (var session in speaker.Sessions) + @foreach (var session in result.Speaker.Sessions) { - @session.Title + @session.Title }

- @speaker.Bio + @result.Speaker.Bio

break; - case SessionResponse session: + case SearchResultType.Session:
-

Session: @session.Title

- @foreach (var speaker in session.Speakers) +

Session: @result.Session.Title

+ @foreach (var speaker in result.Session.Speakers) { - @speaker.Name + @speaker.Name }

- @session.Abstract + @result.Session.Abstract

@@ -703,6 +714,12 @@ In this session, we'll add the front end web site, with a public (anonymous) hom }
``` -1. Browse to `/Search` to test the new search feature. +1. Add the search link to the navigation pane in `_Layout.cshtml`: + ```html + + ``` +1. Click on the `Search` link to test the new search feature. **Next**: [Session #4 - Authentication](4.%20Add%20auth%20features.md) | **Previous**: [Session #2 - Back-end](2.%20Build%20out%20BackEnd%20and%20Refactor.md) diff --git a/src/BackEnd/Controllers/AttendeesController.cs b/src/BackEnd/Controllers/AttendeesController.cs index 840e29c5..70562e99 100644 --- a/src/BackEnd/Controllers/AttendeesController.cs +++ b/src/BackEnd/Controllers/AttendeesController.cs @@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Http; using ConferenceDTO; -namespace BackEnd +namespace BackEnd.Controllers { [Route("/api/[controller]")] [ApiController] diff --git a/src/BackEnd/Controllers/SearchController.cs b/src/BackEnd/Controllers/SearchController.cs index b4770029..f868c05b 100644 --- a/src/BackEnd/Controllers/SearchController.cs +++ b/src/BackEnd/Controllers/SearchController.cs @@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -namespace BackEnd +namespace BackEnd.Controllers { [Route("api/[controller]")] [ApiController] diff --git a/src/ConferenceDTO/SearchResult.cs b/src/ConferenceDTO/SearchResult.cs index 63bfc59b..3b9b39eb 100644 --- a/src/ConferenceDTO/SearchResult.cs +++ b/src/ConferenceDTO/SearchResult.cs @@ -12,7 +12,6 @@ public class SearchResult public enum SearchResultType { Session, - Track, Speaker } } \ No newline at end of file From c32d1099d4fc8b623dc3ea1bf07c6e816b0cbdef Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sat, 15 Jun 2019 01:32:56 -0700 Subject: [PATCH 15/56] Updated images and project creation --- docs/1. Create BackEnd API project.md | 7 +++---- docs/images/vs2019-name-backend-project.png | Bin 0 -> 36812 bytes docs/images/vs2019-new-project.png | Bin 0 -> 97984 bytes docs/images/vs2019-new-web-api.png | Bin 0 -> 82916 bytes 4 files changed, 3 insertions(+), 4 deletions(-) create mode 100644 docs/images/vs2019-name-backend-project.png create mode 100644 docs/images/vs2019-new-project.png create mode 100644 docs/images/vs2019-new-web-api.png diff --git a/docs/1. Create BackEnd API project.md b/docs/1. Create BackEnd API project.md index 0a7f6972..b0eff9e1 100644 --- a/docs/1. Create BackEnd API project.md +++ b/docs/1. Create BackEnd API project.md @@ -2,10 +2,9 @@ ## Creating a basic EF model 1. Create and add a new project named `BackEnd` and name the solution `ConferencePlanner` using File / New / ASP.NET Core Web Application. Select the Web API template, No Auth, no Docker support. - ![](images/new-solution.png "Creating a new solution in Visual Studio") - ![](images/add-project.png "Adding a project to the solution") - ![](images/name-backend-project.png "Naming the new Web API project") - ![](images/new-web-api-settings.png "Web API Project settings") + ![](images/vs2019-new-project.png "Creating a new solution in Visual Studio") + ![](images/vs2019-name-backend-project.png "Adding a project to the solution") + ![](images/vs2019-new-web-api.png "Web API Project settings") > ***Note:* If not using Visual Studio, create the project using `dotnet new webapi` at the cmd line, details as follows:** > 1. Create folder ConferencePlanner and call `dotnet new sln` at the cmd line to create a solution diff --git a/docs/images/vs2019-name-backend-project.png b/docs/images/vs2019-name-backend-project.png new file mode 100644 index 0000000000000000000000000000000000000000..ac4db77cac39c11d984c0b35879a2ea9fb532098 GIT binary patch literal 36812 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

6JBzZ|YDN^D}HJW!dqMu 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 NHg4Zg_?yok{{iqC+8F=< literal 0 HcmV?d00001 diff --git a/docs/images/vs2019-new-project.png b/docs/images/vs2019-new-project.png new file mode 100644 index 0000000000000000000000000000000000000000..ad86b291b0613407c4ab0641a7d5be99effeb560 GIT binary patch literal 97984 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 z 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

    P<}#XK$9xVG4-ZV^^V(s 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 Date: Sat, 15 Jun 2019 01:59:55 -0700 Subject: [PATCH 16/56] More updates --- docs/1. Create BackEnd API project.md | 10 +++++----- ...d, render agenda, set up front-end models.md | 5 ++--- docs/images/vs2019-new-razorpages-project.png | Bin 0 -> 87823 bytes 3 files changed, 7 insertions(+), 8 deletions(-) create mode 100644 docs/images/vs2019-new-razorpages-project.png diff --git a/docs/1. Create BackEnd API project.md b/docs/1. Create BackEnd API project.md index b0eff9e1..ded989a2 100644 --- a/docs/1. Create BackEnd API project.md +++ b/docs/1. Create BackEnd API project.md @@ -37,12 +37,12 @@ } } ``` -1. Add a reference to the NuGet package `Microsoft.EntityFrameworkCore.SqlServer`. Note that you'll need to resolve several references by adding missing `using` statements (`Ctrl + .` is your friend). - > **If you're not using Visual Studio** install the package from the command line with `dotnet add package Microsoft.EntityFrameworkCore.SqlServer --version 2.2.4` -1. Add a reference to the NuGet package `Microsoft.EntityFrameworkCore.Sqlite`. Note that you'll need to resolve several references by adding missing `using` statements (`Ctrl + .` is your friend). +1. Add a reference to the NuGet package `Microsoft.EntityFrameworkCore.SqlServer` version `3.0.0-preview6.19304.10`. Note that you'll need to resolve several references by adding missing `using` statements (`Ctrl + .` is your friend). + > **If you're not using Visual Studio** install the package from the command line with `dotnet add package Microsoft.EntityFrameworkCore.SqlServer --version 3.0.0-preview6.19304.10` +1. Add a reference to the NuGet package `Microsoft.EntityFrameworkCore.Sqlite` version `3.0.0-preview6.19304.10`. Note that you'll need to resolve several references by adding missing `using` statements (`Ctrl + .` is your friend). ![](images/add-sqlite-nuget-reference.png "Adding the SQLite NuGet reference") - > **If you're not using Visual Studio** install the package from the command line with `dotnet add package Microsoft.EntityFrameworkCore.Sqlite --version 2.2.4` + > **If you're not using Visual Studio** install the package from the command line with `dotnet add package Microsoft.EntityFrameworkCore.Sqlite --version 3.0.0-preview6.19304.10` 1. Next we'll create a new Entity Framework DbContext. Create a new `ApplicationDbContext` class in the `Models` folder using the following code: ```csharp using Microsoft.EntityFrameworkCore; @@ -102,7 +102,7 @@ ### Visual Studio: Package Manager Console 1. Add a reference to the NuGet package `Microsoft.EntityFrameworkCore.Tools`. Note that you'll need to resolve several references by adding missing `using` statements (`Ctrl + .` is your friend). - > **If you're not using Visual Studio** install the package from the command line with `dotnet add package Microsoft.EntityFrameworkCore.Tools --version 2.2.4` + > **If you're not using Visual Studio** install the package from the command line with `dotnet add package Microsoft.EntityFrameworkCore.Tools --version 3.0.0-preview6.19304.10` 1. In Visual Studio, select the Tools -> NuGet Package Manager -> Package Manager Console diff --git a/docs/3. Add front-end, render agenda, set up front-end models.md b/docs/3. Add front-end, render agenda, set up front-end models.md index 379c1b50..630c6530 100644 --- a/docs/3. Add front-end, render agenda, set up front-end models.md +++ b/docs/3. Add front-end, render agenda, set up front-end models.md @@ -7,10 +7,9 @@ In this session, we'll add the front end web site, with a public (anonymous) hom ### Adding the FrontEnd Project using Visual Studio 1. If using Visual Studio, right-click on the Solution and select *Add* / *New Project...*. 1. Select *.NET Core* from the project types on the left and select the *ASP.NET Core Web Application* template. Name the project "FrontEnd", name the solution "ConferencePlanner", and press OK. -![](images/new-frontend-project.png) -1. Select *ASP.NET Core 2.2* from the drop-down list in the top-left corner +1. Select *ASP.NET Core 3.0* from the drop-down list in the top-left corner 1. Select the *Web Application* template and click *OK* -![](images/new-razorpages-project.png) +![](images/vs2019-new-razorpages-project.png) 1. Right-click on the *FrontEnd* project and add a reference to the *ConferenceDTO* project. ### Adding the FrontEnd Project via the Command Line diff --git a/docs/images/vs2019-new-razorpages-project.png b/docs/images/vs2019-new-razorpages-project.png new file mode 100644 index 0000000000000000000000000000000000000000..cb1b3d49b181bf737fa883787554ab1ddf80039b GIT binary patch literal 87823 zcmeFZdsvcL_dkp^*34L0Q(5Mz!*noDk*RqAYpk5KveZ;OPpG6wW_Sn@wVKJA5<7T4 zKxJsAXddtk+E|cB3Kcx1B?&1iDFO5D2vT_|HciL7)}DpWoPxK9bT*-bT>v2 ztEaNfd9nd%EVfH9A9Lu)pVy0yd#gcz-W_?de!6HiF!n#MZfNkIe*=GHZT;`6qj^>b4?{8u-Jr?u&gR?7gSHw^}9ehc|DbM$Nz zd;2C3XaYZx*`qiR_5Qa_^Htw8O#b2p%3GxY+LxlM0V3`HrkL^k^VfiQp?~A*$)0mh zUA6Cld{sJ^eX>_J!d{!-xiRZ$Nr(b{M!@j2-jU0GtI;s=W~I8_mByXHUMta!HNM!S zW$;U*Vy9Yq-im%Z4!dO8WfGY1he`BpA_j4Vg&>>ekpzU*3!(cG0pashH9#t--H#+B zuf&16mr<|-{i=y*<#>-PwKy|SD~>TZ%FujHE%Y`8@qP<`UeVP4Tb68APuXI)6LiTX z)k-a|PU+$+pyiu@0I-<#vL+t$8xSb2BW`t^dOqa!$-65Rvn6pGL9I3p&mw~E=F^af_PAb| zNk2L^Lx327<%HE2D(3W2^el10=32(|A7Ay=`lA2&_G)qbW6GU21E4!5H3X0C>A%wH z@-EUqI!%b_yt)GdbT{3#Y!&+Q?;4;&l~eJo>Z~oAEu&L-QfEC*xLSVksRjr_L_+gA z(n^(1@8!nkW^F9ReEbaq$aE0b4NAL0h*#=~+ImCP-s;ep!-$3fXrF2iUk~k5YC$E- z{iCZO^c8WM8g~Ta4Cs}yLK=Z+-F!be`;qGYq-F8;Rm{3BU$2YqokdM0oYPD(#Pp+! zOy4jZCq2D|&n|u+d?I}x!EtSk7;T)QA)hr@=3O56MH`4yr!-7KlE?gQvCYfV)V!=d z3V~?@wXD-o^B*y;WM11iiU?VyzH~3v&nF4Rm3_%Bw!m4lr=!u z)9z0)te)uTsJ#HS+*OVfKOo>HB-J`8P==k)?~Zqh%+{V6Ez?}zx<|YNeS%6TEFy@K zvtu!@8eG{lD>XpJsVp&6lEt1_%}c}fxi25jt5Uk-wY)|czz=KTTB!wtPUMC8EQaEJ z-JtGk!4LgQ-Mm)n-%v`~ArBr=qHQQAOp*DHYmcAGFHU7`ruX-iO%o_+k{4E^@Q4Xt;mR~|ZA+l4!P zS9FpbzdEkg$-?zgGeuSKD8gt|VTB;};jC>*Q&gP$@2u#P)wbj-EWSq)y_p}QNg^U! z;TnIca($B;?9!Oo^OPU4Th&GH&PF`|^B<`lxGQfRxu-H@)5dg8$>NZjWO^oibcsY% z8Bxkisjv5A^{mDqCcm|t z|B!s3*xm;X8BgJ1#;WxwJ5x0g`3rVBHZJjF<5-k75^a3FFq&!NDKjsd7W12WQ{!_Z zeAKaR%-`B=*u)h09dv)FLWqCPW|HnBk^o2_ChkR5JX~TvD@jzt|fg@#d45)d{s>39s1wg_C^L2;wZ0 zx+hal&sC;bxksEQHLm)gSy{CDu2x8(lxD+1$JlYl75W&wc_bsaHVneyU9?O8d1OxF z_NcQMoWd&%!_zmX!?ih6Xhd_r)RPF9zXxE=-}$Mm%vWY?dtwmneoMPPF41q6(Oq`2 z4{>+A&F$Rbv8JiS(AMoy`u6PtO+YGKd*9~LDY$-iJ!`oGv+>Bds25E=KYy;8aHx~! z2XCJ+AXTf|o1Q9*aOjI?A%e#E2McT@^L2Z~jXpjk%miwOUY~I>Np$H6@we>&7-bZy zPTfKO;-^SE$E0}IR&pjnN+S~dXBh`2Xp8HGke(VoLi7vzbVdPN>?B(yxs$8`N8*v3 z>#y+QsPk(S#=@m(C0^^Ln38ViO{Iy~){5+5koyOVF=HJuU?E9)8^xN{m!e*{SM73p*9|R(dCSyn5b_ zBkUH{s>0+`canIYMU{73q>_+z`~mM8I(uFeF&a)x7Wof>duj&#&|RWx>ld1wq6C(v z#JwgW>_JRzQxKht=|Ag-G%Vc@vF->Wwty$l%%;)%@sAIvLeK{{Wi%G5mhx$*Yuf!# zniN6*m_naDnjwmz8j)hyJafJEqSW@oH(BPz3A1<5p2(J9in+KZ>wXC;l^3`Qg3hxt z!Ox}>dLu?MTyQ&clh(o1%g(Z&B)sH3i14}bA|{Q@yxA?S$wW{1GpkVe{nF}V9;kwe z!mMDgzC|~`zB=x1lGyh zi!4&uCVe(8r`UAd6On6Bo@DDfzICk&1CP3i=AVfL)WBx4!r9n0+eyr@ru;F{?4Gv! z<~*gc&cs5zV=X!Uec=fv?rGTD#PCtd)>7GrZMtoZETXMLzA70l%+F^2;NhJ(*4Rxs zDlx}%Yy%DLxkhg_f;2DT`8B4wo~h`E(13Ba%-h0<%H7Dw`fT~aUTTTo^Q!O7Jjt zPl9x<%2450FAuR--YRel;sguN)lT0zEeJ`8y(uyqey;1C*(?}r>E)ZJq}p3oCAA+; zU{x0DGVaGXsvv3W}!j@9Oh?yw0NU8E+9vWGf;|OgCVX(cXAnM>X8Iw2 zzSWY~uT_R3A!dpwnd}3xP2%Wjc@0)`^;WO(H*< z7kO#Gg$fe3?H;kjaRCc;m46X-yo9I+t~h~;Ms5{wpd3#lIKL#RKCgHk1)N)C-u^yI zu@VI8{yrFV`$M;?>|D`HWZ-j?fGa-khZ1l<-$)u28&bD=i{?)F7XjWolA+bX?zUKi zo9|524>?xIS!M;(f_cE|Qx1j@SkX_74D9@qX+{uEd1YSxqfS09>yIQsm2+-b!tEx3 zu9pZt4%w{^!%f}M#Cn~!P<84x!V$)_H|oAk9p0Sl$-nD3$mj%LFC+&ON@J3tJ|ysw z+}q;U=)!XSkP-K%XM!sEP?KaEk{7Sje^HvIL2(`vTWu&mx4NI?OUY$t;qEI2Z z#4yxA2VN5MQRF)6Bl)yJ9w7D)_v5zEb4%^Pj9I6FLVUH{YZO_2RLwVYh{n|u=bQ~e zX>W%S2xt$BJo~qU`2n6!gd#1GS9&5QzAh`A$w1KHb5&;i`op zCQDL@SVa3BNRLxHYZH@4Gr0qXcBuCEjvRR4*u2Q6*=a{DVTiIJv4wq56~aJ!X*_b~ zI1)=(h^RFR@tH^b-ckRtMR4)5h0VM7!GSDjCE96}vjGb=mgA9QRson{XZmz~m{&q| zW$V8zk)oWfwm#ms=%{^QiAj7$-mA2i7dMRD$+Ze4Du$q8zFg9aQzkWCG zrh+;8Nt!Yi%@A3bl~Aj_erK7$WtfDd_F)!UOIMu3j&vA7ziUA-u+YrKv{*FHUZjEd zdLdO(t8p84QC4#rF_XmXPQ%uAH#7TwW)tY={D_0>{-mPawJCP!fg1LjF9N0#1?Ek? z869e*$y2kl#t{?vo`{j&VhUt&-uCS#LH+450hp-&SwfQXwXD*Egg*eYw9&r`fq9hX z4LY@q8`Eu=0B%B?0d}O%a4Xc|&LwL<=!~>ch#AiG`(5uvFQ!-=YcmqKEimhvxvrO4 zX#|s9QsNH)VB!GUdrLi3=U7A?zbxJB)}+K308Y)(SmXgNC*N(Su(K_ zfboV`cxg2BoVt%;?d};S`lbzY(vx#Nt*l55Ig{?XMVKUS>Rxm>QuP<%9?;s4y3~(V zd*`L}Nkxzd?XtSht-{B`lfkxHi&5|zK<$&%U=USb^ghm`;kCDXZB$+rlG!$Q?k0Oh z9gcnlnRy#D z5+WrnNwud|51p2F=7SW6t*O`vw~r(`G5-2K4}(ERtGyo4^fU z;%3dBZRw>z=_?CajVG;&Q;agNfzbzl>mG14JU&A3%7{I)7kvX;m)EK4r2>C7dPg2@ znkZHmEz(#g3x`W1$bfdyTH%?1k*GAl zsP6)x{`Q_n&pRKTJI-@2KYzx|76S1bpEj&u7_NfI^>3(}TRSz$B5!fM@J)YuiOU{7ZXg65!gISVSC%4?1j0+FPtM2>L!r*#_l!kQRztSynY9}@Z?@Y zuN-(UAqT+!IP&uq4M*&5ZA34M*QqvZVY(ZpLHf<>2)DUedOMP+Jh_dJ*b5t611^TA zb2GF&7$xmK`CcT3pah_mYam(v{NUquMB)HaKPOC>C3tTMZ>D&U@}Y3zPx(4dMekWw zerz6nPgfpNe0s4CavG?BI3`V)Um6PsL}2t6_%X%YbU?^mmckmMKQR$ZOmK5a=^cIl z8X(*utyW3P?q9mVp8A?k`Ui=uD_T9ddUw0}u!^LZTuHx!J?DZEx;+POkX+RVP20sr2Ol$ysKRFq_ z2rD$Lb3hO;d>NJEV~CqC6&R{4>%4(6X?GJQg-$zWg!IT~n>Kq0X~ax-EG2$wESl1+ ze;AOHdDz7@fQfLzl$Oe~ic1y+y(@lM%S7ZIi(uY`Ppl&$$u71dA`{-g1wZjCU1>E= zr~yB1Ns3{VgZ+rbh3#PJV>hl)O3 zNK?-0by06Seyp%he|QrqGy}plFgS%}wmbxQcZma!1>_iT19oEgd}#!i(!HgYG9r>o zOQjZsp8_Y`6%*SuZne^L%qzK0P;1)!lcM||NRvWK{=CJ<>J|2iCt~V#A~OTRuMX4B z%gW1NRKgqMdZ*%T$$HtT?zM7HL}>(+Usb6=f$C%G3D>#@Tfy+Pl-W=C>Pz%k@RRQp+%_QJNe;6B5*3_H<}Jbk#t+oOkaw`;d_ zws6|>8i{F#(zZe~;mq(yHD#rjnxhkD3;#vj9D;78p1E6y7B2epCIL)c_yfPV(>0`^h=9G-3;Uf#F=3b# zT9nq5t)x2+xLB9&A7F<&Wh{)LyX;+vg#Z#m`QC8m=(Hr-6g#TU-B23!0X#B0mSJ$t ziz0HAW44wdE5nO}yjD61TXvS#)KQ|~1LhNFspULxJT-E9PV+9jY4lUO34^L&@B{RxAnerNh|;?}{bowI4q1G{0~AxyD%!EQo9A&tZX z>kZb>-MI$I!t~wnKW)PJ!ON2sH@Z2j?S2ygad>0)vg*|VNqUYWP!q$W%(!d6;&b(9 zd~U{?5VnveGe`~3H9L91hNU(BS*hksV&%~h(ZgxoPG|we!hYDDyTlIV6ug+{tXB1zz{iMG!A6TME1mA%u0 zx&NwPaz4FaffD~*Kh|F5QUD{0ZW-~5`_Q6Hh1n_cb|CCf-K^=ePW7c0kK1Bz^)8qG zz;D_k#b5vM%~u52EqGm!x9JdfKI)gF#I;gt20OQPp;^xMcf zvS_~q;oU|+1{39%ZdUV9H;I)yqjegJ&P) z>+Pkj2o3#T_c1(Mw)8Bn`s>aJ zU*#{)&|kMcG<@&7v;~8A{mT}ZxQz`<+ag;3+`^z2xAZIxSk_v)T)ymN*k|^2|3l%I zZ4AB_{+|r!b8GLu`8vM;-U7AI|7zolkuARbe@Gh-o->MR+Ur8sSG;Q8y1nSk(kRnb znu50YsgiEo0BRjBE7pZ30LxLp)nN5Z>2=)7Gaxrhs#JFZ0eTiu<*?|nAW*A{259x= zwaRgn4lHpfW(5ctFW>O_NkiR#zx02MB7DcLeN1-sHecM%*7(~d?-_0q_7OMLCuTNr zQ1SRgZq>}ttq%Brc4vT#n$*0%h$qJ7ZGj|pk#H@%Co$nG{u zs7<{LomE$g_Z!14?!N@CQNS92UY@8zN5Ze;{gny`TW?KujvD@g`+d)zBNtct_Dv7u z(fgTUi6w_Fj>N#FMVnu_MhUbL(o%Qd-sUdZ+CFCQ-q5E~r?z+?AMw-x6Gt6;x6qXl z*T7QUr9RF#t~hk9MD>wcv?FMz%G&QpI{SV76-sd(kEKu(UQF)0`U$6+$Ryg8;%Nfb zengw|y&>870yR1#0#TeYvsm=q4{`XNGZ<(1|)57CS}s zph~3rjT0NmSl1D4#0W{AuC=M(L0U_sqca}L%0yNHr<87!govd4u#v zyw2V6&yPzUZd+!tGs#+FrZNR{Uv=Fd^^}&T3c6%>xXkg{2|(vjqL<8P-g*W$Bc*Dd zhHtq+;_oN&MEwp}-ec2EaNdT7vJZ>PT8o#=clm?o-7C+iByEPBJ}NAWJ9|K7s`KiB zyI{<3y?V-%=UyK#J{$R?%Bh~2Z?%=C*If&s_@;lPI*32CK#R%Po61xE5von2<>ijq ze@tzLSx*z>Bajjc|9l-n?@UzRH?Q1A0R;Jc;l7xQvYi#UDu)9D^k21q*S99Sif<^U z+~Sz8)6SjF?;Plk0X6Kan{5jjP;QwHxiuhncA$-w8I<~ly$JbcMxOqb`v~fAJy~?o zS}WF?vY(O==T5cj01qpr{qcj;c&V$8K*eeWT<3_v=^xHyC|{dHf_GKzH=SAE_w-DQ z2IH)XTk_brF=+0FL#(XBI_7L1U;_7zDn}KTpWhYI4<$a@f_gAdqX6_wA8;ra+Kjo>Pg?Xt z2_av}515Dn2PE!?QJVkW^gjtX;2CyV@G?`h9M-b&VfCA}ru=Jp+v}1N64+1BPa}cc{^lPm35^MTwtgqMa z6Di$yZ)je&4;)wS*I?(Sfce@g=^#0y_}L`e5rX4`SG~V0TBepYSWT~J4Vne&^OD&L z?6EqdZ(EFqwe#e^*1Nh@uM!A5D~>SJcDTewIC!)u4pUm(TxSy!thr`2W-G>vuj2VxM(OSIIU&v_jQI9(QZYmtz5S zwZMDN7DLe;gP^rbpR0Ult?01UIzm}I=pa}`z|hHGZ+yP0HkSD+et2pCJaE$q1|7I@ zYxhz^FUV=ig4EL}fcZ5nhJwSMR@=6JzAn7fcdP$3NCo%`doc(N4Fwv;&NS*==nX#c zrBTDbH=0*H_gppRSzsA>sga?Y)~jOsClx>&zKiI;)sVoOA}-7l%}}PhmImON3VRmw zU6&g0k*s3U>-kjc8mvF-0Vw#hy{z5jfX1-RKz2$vod#hOG4M*vzc)c$n0e!{I(2>| zw%Yd7U^I8o8{B_MV8$x-{&%xFkcz-9Z&;A&EXb~^82&6`tOmvE&+pyVcLYe+KU*WS z2KH=V?#1q6^?6at!uHj3*ukkt;g$=vrHrPucDZO0*Xq*;x--A|>vUM} zS7Em>z0hwzHFM^|w|rvO4G9OW`$HL0R?XwTwh+Ah-JFQ2qdoU-rE22k7du=Y${s=6 zs7en&ROR7u)rHZ_g_IP{FHQYs<>7P(tz)$98UN|YZ_t(h=Y8uM@gOhl@ zcxJS$tl%{643Reg`t&?TS(3~%Q!e#cet_o+f@KGTwl2EM5X?-4ZS?T(qdGKL__2zi&|M0(Dr>n0lcqbY{+kvxXBr zA!?)$>m#JzBNl{Yk8{hn%Ei_J;~bFq0%&Ic|JWc3w5KYzrLA&}Fm`a|^%fuz_|%y< zFZuLhH#GEeZwJA&ZmwM_#16_M8D%HqcAA2s@6-p(nH(aojvEuMc%~Hh*-{a2|A`B# zB}x}NI2W{wWHVijNFPz}dv%9c`loING@?p~6I%8Qyro+vBJ1Vj1J;W6X%0;i-gws4 z3(_Cm(H5y^Ed|u_s39w&Y zV`59ZckxXV>1q&f3F!``QZ+z>G9Ie-(0sU0)di^lTO|KO+}LLJc7MNw95QI&<2?AW zew6FFx;SdM;JVNJu+M<id|8_`5j|NGx7eZZcvZ^e-L-9RliB-I%Uu)>b$BPCxrAv`qqtvD4Y(8E($(kG7rl>KDd!yLEb4D-NMFV@{=J zwfumb&;V(!0KrdF7Orh%Ro7DkKbqh`hj=f`VlFBckoFz-HDI>@u%uMWA)y{HiT zoLJc1K(6e!s1s6!I)wS@JYn;mR|}F#DsHCNHDn77*B2RqnJymC^I{}B)UWwDcKxB) z&2AW8Kj?HyBui_h236UIn_`bMMT=@;Q$I(D?*zT48kv=;A>j zge^i+PcP_ovEq%{!p1pH$rIKBW8rek1V<7*QAVuI)S3Ncdwr9SZ0P-)#F*&`&fLe$ z`R^rtE3UYX2%|W)5wp`~O4IRI>cbinYT;rWb#XjaVXwO`?cyJStia?i`} zf2-vqqDDu~i*+6$R*9;5X$uOWwbgi_gGP~Jj`DddpW$Kq(EBgF z_s#gM%!#XAP<*nVi%N63*sFtB?z`plRIT~9sahE;Zj|t2=lMdl8R>j0bFTH`{476j ze%fJS+K{;ga_OY{T|K%q74zdBfo%Ry5&$v|PF8UVK zvY37Yp{Iqt;*cN~w8w3sVI}mUbaia92s-^xRYUtz+{&@}m2m?Cjrlp%r9+D^$`ERW zK0i^E`{>Kcp-(1aH=e$(`ZHr|`76A9YiK|Ule69cwagFGHiJyaEjJ0*T<5bZDE!-4 z!~Oh;%t6pz^_Ca1Xz!4bETxA1U;T-q^mth-(D#Cp?UqpJ-BA$Yogv zk*1fkaQxGvGi@5HT=?!mtQbJ?qG%usHNGyT3Kfwl3o=9CEXEf)V!AYi>I9 z5R{2XrI<686W3nCdN!ZH&(z>P)pYHa@1m-nl2=66fH?>46w@Q{e2O(CWIpOu^QfnrzO07Ag}P-Wiy37xvs~!qY~>jU%|T)??dWxEyvjP4bJxXs*sahrY=V}|JME`1 z>Oz#`m;Y4JBD)0|)nB_MVq{;duS5@a)=!r-?o$b)(6}HG){xkDR$D zt0{S()j2=vN{y--eOe&=ejXr9OWe2;^~EBOTyaxruDE^J&&O0{9|te@z39T$VP1VX z@9}ZIiX^_=x*BBPVrsU3?%0VY8;L>R=Dq(IldldX^kNsIctGJ0hp;jWeRd`pRylpFOkt#fEpscSmE$CfcYiHXuT#k$_J%a-cP0aK&{02^$@Gc zn+}=;NqOG*{JY{9em!u~6F6n{H}P{e97+6`He43cra~krry&`*eFydWzE?|?4TuED z?c|CeMjpPA6(xhUU<+wIR`xmUO>ZpLfLa>9z<>=3^fM5y;&Gp`)@Mf;fI8Nm@>yi0 zFqxpd05IOa+3v%wh01pi zk?eIYN)P*~FK+@gitDJ`sBee@&4j7Q z@b&W-I{wM&%2vmTnAWkIE^;a-I1d0iUGhaORVV+M_O+UV*!q9Yz41S&u)WG-K_c7p zQq#^_kUZn8PM7PSrU_s2Okk*AQq}{hYCl^?PV^f-D+=Kh!^CHB{$JUbeiy|7hkQ(c`ik>zcCaCKP9CZA6cMYWD2P zPi2?dBm>q5Hl=Vn!_P5_tA>8ZY9?a#lRZ&Ia0sd5F%bTLK3-6ei(B&uNPoRD778~D zo#N*THA~63@o~N9m5ntoqKUoK?d@;26`jd!9P4)1SBy3Ba>eN8f+=vKqP3%+0Y5X` zhnSCQFHXn{JNcP~3bC@cmK7||UQMmuzuWP5{4=-CVJ|*AD&2Bc$3u0Klcw1C z%5FLc_xs2edxzS*;5r8bF|4V*&k<$t3!4*s!bvDU*jCM#r%8Vwi^^y`Xd7R3>}-8+ z6Q2B%#ncugGN* z?HBw@dK`LxZpL*{7zTFtS#3 z(>kBnU+fb@2DnN;<-&stw*vIxyy|`3y(Tp2v zEO7|;N9{Gx8*J_yjVJ06nWHy`;numW6o(eNP$Y*>UKVO*M&PNTRBL z1MTi!5UyUAURlYD2%I-H5tRZ(Lles{L5OeMiNoDAzrDpeL~q1!SIVf1$7C9(-JumR zBID#SxKU(DnMD#$?h>Te!F$pf<1AXsuO+qJHEUU1I*OSfC+1qaIL$^^cZXy$^+U1} z!5EZ2Ng6YA+0#JUTF#=%S+#rw$|A5{z{Eg1qWWP3iZV*UR5H&f+Zh1HB^odIb#Gx#2SG z$^1g=3z+EY8Se^SVV7zL9($I}SMT7vU~}T_C;e~&^8of#Qg6ky`+uI9Hv*k+70WN$w`gqYOqtl!A&I*OIkE== zJ>VAO6B1qZ>^GV)HhOD`Rf!iign?C?C)Gg|pV0n+E~hYMVLn8oVlEicP9g5r5`{Op zEkNOV`Ozg_`LgJR$D>X)I+-MKxxeBzW*nDaM3@Bp>?tF$OZL9Qc~^=-f^FdbOxF+x zB3ABb%+BZ7i7+Qf49O!lt$vLk**kD}jM{r+{9~062{;dHwynI5Mowwgkt6vGDU&r6 zewUIjJ4bs$UoTe|yg`y)(%fo@_raJhGi%<=0DS|)7XYFQ;V(pLefOHpc$zbHPpy#* zB&HP8Bs&-WlE$WQ5R{s7t&S!ao1{8149H9xv@6GA9H)th9_+BCx@43eKzfAxkC3K% zFjL&y3V}NOfL;eMO|_1w7f=uPEF02nsGH7^dHED<0ZuLLTuC&d3Db=WIC)*pv%yft zbaf?_fZX5Fel3K<+g_15+~%yU&PWSHy+j+9&EDcaPAcM%B_7;-F*%~Oa9Ec@p4|I3 zPwS6=fTq;gW0h3@*-4KB2n_dH+yFvltarJM;Qe;()X)Kuq%9Lcfk=Hzsx!2WB zs?fINP{1u|2x3XHbI;6Hn7||0zPJm|bSiZz*6%V2k1nCI=3Yj#6WtV0qX z=JgX3IyeY!DVSdIs3g%ewZt=DNSX@0;NPk-D8;`)a$9>_Zlj{$@~CWzmMB@~JB-U9 zC5~KUY78>w_P3|w5sE$e77D}(dIYsZ72bD?-Mb%k`wbX_Bc7~{@h7WN1csUQ2W?5y zIJ$P5j4i_C50_Mo_f7>;EK-3o=3i;U9}0Z~w*4)|6G-s1rXGc4HTg?pVb>Y=4~%L3 z#7h2^KU$|GlAHss)Dcp2Pf0K4EVP5)g9zSvwqC~Ta5l_Mr*dBfi+2|w$7bm5#M|R3 z^bH+nT>}Y0j7Jox6ws?Kkrk$&iyim0Z_6ej=c9p`knYl+m#+#vS*)morMtW>4T~`b zlw0ECow*xJY{TSJ!HUz_%}AN)Ii0%6?zFm4{YmQ7M4yzU>4(aXg(milM(VvSuwo4q z40PL4_=1~a2|hoWkRScDuTY$md;wn#6}yKwv1VVFIO=e#w`6)Zr)r6~+QxJ+Bd56_ z#*Y!C5CQa7$8K0U(wJlp9JqNrMV}w<;ABG(DSPm$rzmjJ%H_j1RW))A*yGgV zMzz_UXCnsVe>a-q1IZ}A2^Tp}H~9DHJ+8y`DpJP5%Vb*&e@jH-k1AEZo(!$&B? zt}vueAo_NG^2Axf!IdTboic_ukrI(q&$iWa(#BewQj?4PdVKFDA zur0?y2MZbRh}T8CjM^R_PEa`E_i%&20EXj+PkVXlV)Mx>XY&FHuXL7%6`V7POBV*Gd}Z11MN8@Nw& zIDCp8F(+rIMac&;9Wb5NL`JZ?)2Js*A$P`}dJv=e)F?h!1;k$5y)!iQU0zSwjS1MEzQ)q&ksce{k>?Gv9}>l#zu<0j zUrjwJWO4@umzj-~0D>;YCmo&p7liNu0)`c8?X9<-?-}SscX7m=!^yLR8Dx>?(*i_v zi8r;K{-FHeK=*}w9WX>AvCWHp>Oe{tl5}#!KCD?`Q*4i!b30dkZ`8-s2bu`Ws2r&9 zW2WV}#0KKYUImuCGPGJpsjQIPU9Vs4>hGLKtu)1%x23a6X)nsb7_Qq8R^vX)plxbo z@bZb`WHm-%`3&YJsx5Sl-N+g7(b;p}RN+X$SevW8^eJ?>Od6%dhZAMkB8M)n`~iF( z=b$q#E0e-I#&NAk)XM{dl1}D>@=};L#h6dsZtvPNAP6KvUr4E(qwK_c%^HmTj5`0P zg;Ralg5t9SbQHf!L+;#yl+EQP-$HLgL5J!9P%Shh`phP&G3uG!{^Sq}Jix%AVBF?Q zxkK`7H7K8>Zc)*>BCgl@P7Qm0b7>TwqI5^>pZ{QPTi>#{@udaHKLY71Z{KU?ZjzqC zx>YDwn(siOWLc#L<3wlO9m?_FrndiMm#<74*SIM-cYJxTR~3;AB>wEtr~5`W0Gw#v`t%bSUw(c#TDw@>!}N$4I2k)nYD1h5o>ANux46*8G&|c*ni5=Mu|?}iBW|sF zI4`(}9$^Q+CGJj(k{K%MK31{pP`YiL^kLm(1ClLyaNa%1G;%U)+%lICBW@jritPsx z9rULb)82|_bD@MN*?IJNAtSd>-krjP1JIgKV%xQ;1?Veyo{?1y=G-?Ysgf&BS|i9Y zN0MFnC1I_V_q!}}KT|ULSaD>>Xt_n{EEq*7h3_x$ao30;oTOy75pkv`lFxc4aHhsA zBLL>~S73ey*>Hd@e!8`KzU{QkQ3Le->4FLKtJ7xv7aNO;k=>v@V*l^f^r(S?*MD9- zSg-Ah-TDe|@V6;FYWAl}=7wBcI>uz9H6VriRzRZ)D58-CE#!v2S}L)8@_&)$!;tN;-!QH zJiQb=o(z^D^uEi8I7Q6Z~YOzsw=0rvkN#hqwBpT4=Q%&dOWj`>wrq?O)m`6 zlBIzq3GQCBx9&dCuoiybT8Z~?Sv6DkHpqUD&xtZ{zIG$a9T*7e&w<>C_s0o*P_N47 z$cSa@5%zLO#TnXcVtmSKkd@vg#rC0xOPR4R*6lRs)zzjb;qrEvZ_nu(OCR7fD zE^9FTkGnZ4;;+)7pO7=Yp{q1G%bG~C?afY3hfy|42xYTIy2%uul3;X zs?@%5sljv350^wFIATXri}Qeiz6hfhiS4J^U45zUnIsG606Py7?N)c9%S`W-l(89}J=NiTU10F>#*F`0mhm;hav0E7zzO*p*w+djes>-3%XYVeqGE`B%8s0kg z-73U$-m2j<-Zta%ip~%UU-Yd;qET@y&_1m${{TG5i%gr5Jf@78{qmUi%V0$kPtZD* z)SSXn@_qXsweqhr>91A4Zt@CybMd+IrpJu-r>)0{@r1k^}Z-#rg?bmH6?Hc@mJ{j01uzU8(!srR160Cq4qkiRqPZ8(QCs~X6xOE=Zo%N=Ay zdjo7G4H|KZUO}4FoQf$wW}-u8CPcPzMmB^S%pkYYY+rEyS-pvXMEL%sDvEkixfNe2 zRl*d3lVl~k@>Z;_*jHf=3A_06>e-$WCnxUMcOL@h!?jD{_D=<#C{7WEgy5d8aVU$1 zempNN?Cmb}B&(Jv3d#2<@_>^9rxP4tt<$TQfVpoPLu59mG$-RdAkdR+o?oy>jkYSr z+C3*Dks!aGb?FqZG{ReY1}EhlicY-2_-ENSE6CtZ_^Xv4+^yLklFWOWyLr>EpKnyI zD2?mVeHtqHX6nEKRjJ;b5`pBzvBIq^d0mKO+=Ronmj4%f?;X|j*@uk>Dbk9H)-5Bp zKGp$95dm3=*0!iosiJHM5&>C8ij0tiI9jn)NLyKo60HVgh82d4peRvRl#u`d0#b+} zK!A`zLX!6mj%pwEdEVbSzjNL{9{=#@A>@01@A0`mbnBP25Qh(7p6j>Qr{1`PR}U$`tJ#5}@F9g4Q4q@9_S9L$ruRiNuB~wJnkHQ)VH+!-6>?bCVoWN(~ zUiVJvK75Zvawpu*6W{izfQ2s3rI9NpFthq6(h-A4?!k5CEl*NQC(>Ei;X+DVAt}df zBxVABp7QlOb@*funNm zPkC^Bu{EYJUyF-g>^_c7 z$W^D{S{Y}R%`G=b9tu9UHeqHvX`CC`a6Ot{;wSt|*fE@$3~$-1ALlKP!Peik3G&N@ z7c#nLelM&!%()$AY+pawVCkbASw2Lb@4~lLLo*VOUPv#-XF` z`UocD1X@vZvRW)KArheS^?4*^)$#1mp-UK(USi-#Rmv1Fv5fj-6l}NY4HWrN(T1Y| z$&N$C%FVru8{|i@_RILTVDgMzMyucGC071kj;ULYi@P7He5hcFm5Hn*W_yz*5O|}+`UPNC%p9_x>(9Qi0Zo_srw7Ltgc^x&@`Ps?0$DP+^w{SL#eW4E4ie|K}U_mpXWXF#bYil+lE zleJF<4*n{thdqR)jO4hDI546uGTq<^1yMnrB3n;j2IWoaRF|K4`ipDv>w`D)orrD< zB|b2=IhDh1%QWMDokI!eLntot@(RTzP*Ldr4Y3tZcBGd|#4Zlal;C|bVJ-4hd zgqhyOCYdoCl0mk25L@kh1LS|*{S_|^(3T8TD`KVyMYb+9OM@|BsKyWjE1@DT2rtiNr#oAGl}V225UYZkuWdyRZ(%-Vr0j*%_pu47UpN>6dg zGH`kBr)HY)=!b%AGXhZYnA5P?*%uMaSfVrYvT&S}(t0%i^jLeslh&%l+zwXw4SyaP zme?R@(^l2ApWJUM+8x+nHB_}eJ>s7w&W$~e_U*iZ10z&2yAJt;x%(I{x}6py5Ki0u zbgf#k29?*`TJ9T@>=?*2trpX_6~|5|SixSTy-eYSi~^Jg*-n1h#N8I@??`$scfJ=D zq;Nhs0!$oV7?f+1ZeTu$*o(6W#*QhZr;>fFF-b$g?3>|gdN*Tj}|AFarH&ssH8nJpE7v< z7Q8QrQU)x3hud10{iZ`#!VV(T+l4X@(qLtwPH8d2Yo6mq%}Y<@c%n)BxVe#AhiXKK zoH{5A+e~EyFk6US*u|MGl}88``F*F?(7~KcCC<%>C91~V4enSJVG@mUqr_KaG71fw zuk__CCQ-;qmw3(uW~LeNgdM`0JpWEAS*2-$R0@zI$!SjzWGb8M&HWDsC4}Zg#o}Ok zv{sRKL{}Kx#oN|f50zyac5+|%3XoQ{R5Hzq+YkEZ!PIGH!5Be+OI4?jOsRS%qB?eX z-_psA|DHr6#X#EY(hQ$Zd+Ub9ytp(|MUDF=$CMddUz7*7ta*L+d32zsS#=`AIKJ0I zZDIz`D?3kPNg~ry0o|QnOd~D>RPsbwow|<~EMd!AAGffFqOwwVGtH1=S zw+y3?%^!{4D_TF_Fs43OV=V!<|6Vl_(;+Z!F3TH?t#bYZ0(aw?+tXb zC7%`~%J9n3a<90;&>VKAUxIa(pduIzGTY8Ai{5!be57+ zhIfYYqVt;jtOL7(j9Q!ovoB;nxbJ6SlZYf!>M{=Fs@SA*kgx8@7(#f69k` zj?n!%!_XhKruaxH(;GNbhL&R*G5a~bF*vB4$zBED+HsYfRztI-iDN_VRZGr(-j;GD zEVuCTNW*aGNM}%TgJ^m)A7#=DL_A2yrhHnB#j5^qOm$;TPG)ecfypS#) zbj>xac825n_79m3wH4-`L^G)Ck{lzB)2kX#!oS$!pr)G3%})D?*`ykZa|?IUoursO z&V6WnBQ3QLbsbxrWNN#L8lD)R*?|OkHxJ=)Zi`1w8_cMhl`VP(DpMiUq-H0^Y$ql` z9?Q4q;3@vQEzk4BB6d3FK3LYVEz2ziyo(H0h}bV?*HP8?@kN=TW)WKQ4eDCIH2 zvY>_gn{G?otiJ_NQ^3Q`eHD*A}p!vA4_!edI$dh z7LVfpi67tZ>VHO|`Acca7btkFHU!Xm{~5+tH=UE)`$z1hYGvMsdQT1wsAm3>^wlwX zrxd+mYHocg&~R2~VPC>+)cBH^t6CCl(+EJ%mlCz)>let1!R{?M@Nd!gn^`UhT`qMw zMFU?1fv|zR;=752zem7+6g%dqtETUVfQAbI!~8a;W}D8qBvoxxLRM)_V`~(qA(}gB zpFfWE`+-N$-Gnr8%-R~d=eX3awc*ihA9{8715(D$MSz2y4>eO3*GWC5~S4T{TuV<&F<{{%E=N^DUsS4e4} zEhOY_PcB4#0@<O?Z%IfjP zY^RhTyik^qPp35@v!8tAmsaUqPdPW5j<4*2$K~1d&lY()JnDb)T zPSX{4h+u|3pR*CzkY%-cRzOd^1qeI-gV*$CcF&-8o`OPd0=eD~ZQlN;omPr5)-nx9 zt^G^G``+Vg{B!IhM;>eT;b{n@-1Z|6BwwVdIDe(7Adt`xuN>IhuPHfi<*DABl>hzM z@qg3u{_E-Gyr=<*{~vY>eJTz(zgpaVKHIWG+`j0H zbSy&aS4Eg=EY|$w=b#bJ&{``)Va zy3_AztPAG!GinCLg%1~ff{Z-KD%a?z-%z+4gl4>^OkH&=cymp>!{^hvLp;iEbk$a!JQ9*j_HV*)j6%b>(Z zKl;xi7w45C+}9YT3_ZDi+ff-E+LVmM?3?iuRE+R!=P;mrjP zX}2XFy^wT6)y1U<-c^(=v6*Vh-Jtj?E z1flYUd@6&j*J*{`_LnObx7%8S7GP(fOS)auN-k&=q-T3ej$hMpt6%k>mSl)F+eqsnhtAvdl<;Ij%ILW< zZ&02#0z*Imy283bz+aeT_ivj|!2fVBW29&s$_nCpZCd1qnv}r=l^Q=dMR+JT$d;cM z`Zsae;;|Ch@o<|A!Q6e&32-UzHHR~GQ02td;xm;jZBFp6nTkAWQhXN6xSRqBZ(1dk z)>c|u`q=qt?v(x5nlj0IcGv(g4j;}mPNh1@mvh&(r5Tua-N{-JYL#kcE2 zo1X(IP-#p&GK~#W>&wJx+rQWqdi_k_7A^xWqf1Q@6`=C zA?nhuX?BO;n&zLG7R3aMntC_Ft%|5$EMx!CRdE>VTa*5u_W3zwhE@mdovr@%Q(s<} z(W{Gn{*EtzEqp^bfIU6g_x1*@N>dAp0M)OTaSrywHdIYiuY^zJ^vCQ4wJzr$VowH# z`k`LN2M;4aq5X{y3ZD0hdat%l_s+>v03Bj$t@mMi5@kgq$>R+n0#KFScRLPm(BUC?RAD}kBdY$KypcMMP>(LC9 zh`B8{*jmp;p|iVz>tOljDIajU)KAHMluLR!mU5tt@V>ovdSR%h&jEkMOXA1}cL*x$ zz!{6HqLHT9VXB`0 zY80ulT5Ge&rZGI|BqkT3)l}c~WaTh=WPWWA$_d(@GTOQMS~KS`Yc%VL`eZ!kz2C3e zc-=t@xjfpvjk4dZm7iaEvP}y=%d0OlPq;XO*sYeYW(B8z{8CBQpc=AwUm`Yfp^hi=AB< z(tV z-sBk^(*X_*i#2f!Vf9Haw*ho34^Uk|l{lQl-QoDUIP83Q#<%jYXhylWBl9%e62T8_ zl&ukV%MSyp3t(IwAwqLRb(vZFjXl;9TaQ~(`qE(zc~GVPCR*$BnZwrv=wy2R2*0>w z$5!f<<}0Sb;m_$ex7FkyR$SeZChGEb3^lbSwT={@PMREJhappjg!Ev=u5Z8fEdId0 zRW!}>GTVXLQvSKHA-xunysqY<3*$TF+Uj8~4TCqf1QW?N)rBXM3WFJ~A+fmh!_{5oI5($IR|BSZaKdpr7qZMe z$u!+m02}l3Q>-Q@u=*UZGN9yA?*D$X|C8KpLCJBAWT3xXP(Lritaf=D>QwXS0n?$z zgd|yF$1TY|N#HXx(4r@Yc`z@bZ>D)F8X-FFkHN|hy@sm?<|k#~G8n~-&VAXjqUOvj z09VJ-fA1P`bY^u<#@~RiVVk_cTYndfZ#e?LQ|)qfhb6U_&FTveif~u!S)L7Wher z)A0a?E0SB18y;blBEpy#kKY#Z>^9>PRwISU(MJq!c-)wBo9% zN~!F4mhKh`?l9*0q!~Bc;(N-Jhe1s*o_&e6`?@x-F*zSvTm}b*H24GV@D4AX?S6FQ z$Is8Zks*$odqcENHytL#v;`0TLJz`E4L%EABmDO7mkExTZW4H6nvButnO09xhWedj zhBv2!0v&jT95n2J=+X9K%YqB7H~HMvtBwlS2V zNKcjfRd+%RBWr52*Vu7UQvLF=HK>dZv>*2b1KJksW;0hW{pirOJbl;I=M2Jb4xZoM zclcgeNAhKjqC%e7TjNWTW4$+`JI~zLs#s%UE8rLz`Jiq=VHd6W7aG`8%uV>&r7X59^wM3`Bufob#J z?TwYCLVfODx*|Gn|MhV40l+*M`b9JrUK3o}60RnEJ&F<8=$&tU9*vrNkq|q}C^y?@ zuFjOCWU9f@-iB4e5j<0@&u#CX7N9)rx!Feu86+rH(Ae?}TtSnrS=G5nWpo~#Tnd~B zme2d$u2a_*+}U*I4+EiW-TsBGspRRqTA@|2GpMs$k^Z1SDY?I^EyWy92)UfmK_=j1 zo|uJ}4I}8dnLcZDGsUgZDecOM&FCEHWL5kDPC!0tO-IMIMl-M?vJPinD#cX%oj*Q= z$4_K3+`aPD6gD$t7St^!gq6UL2=s35g9W&EbzbN*sy;n_v{`0%UX^K zR{P~{G%7=5sn$kGc~sU2afELG2lx4{_eU_x{tVQ}80~bWGc5wx_6eVj-?$c+9_&dm zdvQtaiD-Smn4M@@v)cKT*Dmp>>+r4fttfdEC^?*ItY53*csSQli6#|REV0^L1Q6F&ODalO^0Q%)nDWn+e-JOZENreq4g7+%Xl%^E1b z;>?27)5E;?2PSXpoV_O&``?e>8_xZ2TK@ZKIrI3n%C4=cx?ywXH;aZBLV#ZR2TPlo z_aA}epbNyEB01|Lj!rd)sFlkb;IXFfIPZdmFK->$g$gJ zinU1GPrq6A&SzzuSgsJ9G4-DuX8N(Wk2ah8K*zL4D}4-!wO?_rYw%bLL@kqk!spUg z<{qxE3Ss$su@~O9A|ZMzK4E#Zn4se`Lecm#)!y*+TbG{LR{Zmdmq~@^*Gd99-^vx; zFa1SBRsO{fbzF-Tk6X@l+3V><+9?H^9mnWZK^t3x*qJF45z)o50r;E_xPJ=-A_hHr z=70Pf3vU*m`|E=0=*|sAwPn0UkFP6N^o!}D?uiILS?s0G1O`8T=&~_|C*M$H=Px!& ztZ!KZsf7V}b?wRn{-p)4X3_JCc;VZAc;{B~%}U)P^qXZDIldCkW#X=r(5BK7;~nEP zvfxmku`3!wMstXJWu-xil}gvr!hY@pu1P$HSj~(K1q07`Fn_0}$M&mT4;H)(ziZiAi$2!Yq z@Ny^aLWs{6P;@N#?#fk@+*e^P>yCZh+jnm1C9UhlVB~uojO}#_bf7;;?uV#MqDkXI zdb|d4=$GV?hIu^l;L4H|lOhPsLFDdb2^fZv|J8`or0XIOTAB9A-m=nIlhhkpjL_mQ zbQ0w87yqb<&jO%&=e1YpQ{vTDkc=iU$IJiY9$KdJP_kN6m<-#HnkR`go)75KHP9+Tnujg$Klwm;jd$9G~xMY z$sr$&Q)|wP9{|Ciu1HVLg%q)kFF?fPUY`!#4~kQwj^S^mRb5hZ@eOmxnZp0L!3<%Y zJrAa`E)Sf4QMeeYpW^nlM_^=+><_J86XNu)aHO})G6QItH7DfeHn>4ieYt{b+N5!I zQhK_zCSaep17SGgpMKt{n^q13t10nKL%?8-Lb+4l4Esu%dkS!-alrU}uv zh*0UIUnnbqz7Btc9`EeU6JElrx0YII=i^)JXWeh;kcbPqr|F9{p(V*;+9$ZHhreb^ zZm*nZnKx$En}P=Y($E&iVYK8imOTh|!QJa));e_NtP@$Ml9Z!@QS`qI=~`}2d^qkPu8+wOIGdT!5m zEC;SqF1lKbg~M*wjYlMN6OH2~X6PyrJ*#eFBUCExZP4$w5NW9`&1Cz#CKsHZIce9k zCfAxmj#)e^F4gGQY-Mr8rh$fzEANa(zyP)jsaP5BXW9a|a?b z<6ZLt#x++1p4)mko71U_Aox1AkWe#PUuhuW%(ns(Ynt^anwj^4i;QF6CkuW{uE$iXM5JhY0$|Orfd{nOCYm8UsN8iz34+0mO!_8l+ zSmFg(D|^+fP_Xn4veg=(ZFU7hdn9@qFrq30zwiW`k~-P0j60h|Ok0dnxtyJTc;MIE zn)F!XqZ!F3>&;fj8rLi)QZf@ATr0z;A5F7%I@2CE%w4hR*&m&h)KG|8xUi0*l2LTk z%pXVG)OU4PNV9+40P25NB4KL%FGEQ=eUUDkI{|s2u9EujxR} zGQ!&Jp6*{V^fS3nzV0}EXE|M^dv0~e)+D`U|7tnc0^puC)?{dSVj!80TACIPA704c zowqeODhT;)6O{2?R+Z_TUTt*4N4L3esm8=y8Gu#UXYVPjU~q=Gu&CyVE(Y$TbUG7e zk9$7ixX=YZn>~Pn$~z~BDk-tf0XC&uNq~!=5p`XV5u%AFj^MOzx3aE`2DAuE*(WOz)vA^oyfT7B>;)Tgu}*Tam#d|R67zrS)q6tMt$Ie~6m?cdY1iOin=6PRsz@-x13%)?f4w=nd3Me1Ni+(zcJwiH(q zEq1mLpb6Mh(#W~X-qGz{7Yv-mxpMx?`^(8V6oLaHgKJuPV^6MnsLB+m+O|%p;?X#i zbSi~r=SfhA>Q>cE{Oq;HNstsf7;m+>tS^SYm9`RD`q|BUMF7Ew2!Tj%QqGmaqC@V- zXrUJkNifD|^fbpd6fHWl`jdnRUNtH*Z#?7Vl5?&c1zzvc8Thnht@K z$PU|#GaP!hKkf#Zy>Gv@ivZ?&{z&sbF&eMTbzzBydX<0N0o1-uYLEw6$SB1`6hRVI zr{g_wZs7SPQ^Q!13n3zU`ZmUuWLJw8Np-TWbP<_bs(>@o88%FE+p^cp|hQ(FWv zJP>1!tsfI&XJ?Y!kiKU)Tq}F9{!lc3_1sp;3Stz%_6V9^10(-omrZ`lzj^Q63=uzy zic6u*4ppM3_W*pcLT_RzYvWPa5MyoKo zEtxv2i|aqRzW--a+`z;ItEyw*guv}_3O*7FS6973df3@*y#_ui*`K zqzRw7BajXY=h0zqdK*y6m9PnWaBh>Iv?3zDRa}?bpfJdKb3e^>V)E(hFEt1sR(^cf zuiV3;2oCitH<)6cfRh>WXnP()8Ak4o20MiGpwkLTt*s!?>7 z?a#uK3=2%0ghF0^q6LX!(;)@4FvM#MCYyU1prL92bD z`JC#AXq6oHwVi^;SgriaajQWeW~lN)8v35!s+%-ku$3+v)2Px{{`DPUo1F^7fWlslhwkUGs)eM$Mc>jJ;wYWYU2owCnGJ@6xXyEr=mf3_UA;uhqJH1)O}tbHF2PDo^=4C z=!W8jNEqLZu@)x3%2-r}=Y!m(yla3(P_W`skm9L>F-=Irmt$n zQNX7|-RyelrPOO?%)w5_7 zY)H8*J10sbS}{)0Qqbf#*ijlWY8$v>7ZKYt7)AU1g<6r;<@+>vhbZrYneQOvV$;X9wZ2r`4CfdDWnRq93ceN`ucSFvo}_koy;b?AbmB42rBlS|$`!#*CaH`dpsT!E>L0}h#E$R+f^=`+h zuy}$FpzhDS)~M9I_3p7$Bjy1bTl1a4s&9&c83sYQ^#@bcI6>Jv@w+YofF>$A=Cfm* zs=(+zs2w31m?X0v0NsMd&ZH19K-J!`LZ<=#yk)!Gg~nCEBo&Ma9omFWIJv4d7%7mpmOvtW4^1IY+`+Wd=e)O&#!@J?)9$e3SS$x)0CsP!{v(8^|@ zzg{ylT$vDx0Zat%u6k<3!9Zh3fx6kot4Q{R6=Zp;ii(s|2P`OAc5h8p zz44sR0)61Q$$B0LhH3T#`fp-`S%hZ4n2m-i6*QG3N-Kq<6qj+vq&0dFbssRV2&~8` zKILJzNPQq}%f7cvCYMh&80Bys)UwnM(EAfdpRCUvyIW7X72cJ$sy`8EO1ugqzoTi~ z?3YpOm8=UauwVj=1UqMWy_V3X;gIQ^SlEP8cQH*RXLJMOMHtPX^p?nx8Z?my&B6}E zCeXQ~ub#q_9~-})WN90P_kK=2kC zKk8fraU4rM)Odv&I-`)9AQy^_fLQ(xoi~Y?YkzVePgRf~ZYs10)8_^>q0;_|nP3>a z2jJBfS>eZqZPDKg^tS>iMlbXeCP(}6JW&I7$hObgj@t!x%xs3r3^&N<^e8A0h0QI3 z^f7!PILT83lfWo==|Q^lSo7jv@0hmsf7pKChWWJwIa(FEYEP1C06rTx0DP!E`zeq) zy10wI`}WP5tWVDCS|=NSD#+5B2&P|lPe06FTj>b@>%ynCYXK+W?}?vCrQ7)fytU2+ zIY*$Z+YK<3y=5Zg)E_Ae(F8U-j#Vv=sN{@M)+yuQ)4v1zsvMu_74*cq{N_!8hlw@{ zX1|!_MCm~YGaOZr#9L1TptXdNX*x9NC0cn7au@D3ChR%yU6=7(s9B_DzuL-9pjBhE zUM*+Ba6qiT6bR^EA5JUM@X=tS9?Y-Z&Menh()hwc4{|E`t%2*@K}PjP)Tu8!a8`ld zIX;dH<5twob)vY(QltzpRHLSmpq&5#+HXY|w2BLW%dMmOYLSJ)6)jx2V5ZJ#YfQt$ z3kP_NBnomw%Qjegs*!c#m`4LCU&xZNHzd2s)4F-OX@emVfv zFI!i{0&1D-&1fA0Pzv3g;i1RW<#>-qF;_W;8eiz6+x_lN`Z9Ur{DJt@mnH29Yt#~| zCcO=vsR;ZhJ0jk>VUe=dlnVhc;nhkskIz=k_2ppT#n%SbLucX!77-Nn1G=gS;sv^5 zWH8doL!o;XAorKntsg(48gT*Y9Jh4Yq57L@RRCoi9X)l0WLGtzWvUN0s+BHO)k%-j z#ZS~##-Ek<3S#S=zzx=`drF~u#sn3uT}U<#;Ae5fZGDA$kd^%g!uW_G;x3-?3C5bfg=V2` zyr?=8e8T)qQVM+e>|D0txd_>#SaimeBOMw5p_ghd3|aM z=s(T;A<&fq{Y8OKR*guN?NU9GFX>(`t+%QP1M>j#-PCmj4!d}VmsrhzT-;xJaptF1 zcRdKXG<2an1oCas6!}clw|*X|$!YQCI$8TRTbez$CV69;E~0UYU4O>7S*v#Qn<9Za zsi*=iQfzS}PNcQzAb`{bF|8ts_JDgsfMa=q8=qZ<4_Gxpn7(aTE$`SV)1>XY5~KJz z7LOF>MjIMa;Z9zp~|Ux-xy{}>-FiD zqn63;oTU80@0ppOuLL^m(T;fx`$4q`=52D#YRkU#Do7^i$@?;6owFH4CqaeNDTJAn zN|nYbb%PCQ+bR`roS?DEm9lfzf>h}bVzEhhALe|_qlqL_Ld2?B7g=5z4ljMG4c}fh zl|)$!qBZ1p+@wq|lBW&;=6d8r&-j^g6hU9i0DmyHe5{l`Zmdcg=nke8=!}u?oN0!*NlJ1jB>5EQfzx8&y%0>@#b%gp#u$xs1RLY6F4)#H- zP7$6Uyltu^_5!`Rt~|CB9Creos2B-9c6mRmY!)th;;8Fb@nSPD=rh?~-3O4B81?Iw z$cJg?R3N^-7s$ULRr@^AAgO3!H}IL`>hTB)cI=!C^}5+inC(9!h7wE29ZQXAxJJ!1 z*_2E-&kTXM{#Lg9rnvoFoBjQW-@#@M0aOouE==cJ`4qV{iIPd&C!DFjS(H~8?dw6U z`W?LM%36wnc@V}uwCw4QqlW$MZ(V87Su4?bQ79VAo&YB=TmsincR5-_nCOA8&IkJ~ zE~;ASRVP&TW9kN>s^B^Y)g%h|JSvIHtm0&GzdA0Fwr9esIYbIXEFta)7! z2>nfUvtv1YvLif;G}~PW5`f730vC9k~ z{j2{z#?Mt;vQ2bj& z_OGiIjcd4mOL=*anhg$U{D47X{adAnMCB!5pU65 z&;yuSMtsu*!r-5lN|kVhaD1-Em=S3z=XyhcXfA34XzO>q?02h;A3zU) zDEO_y;s-Dc;6rnqlaE$)!H52?=zXA={QujK828jw%{oz;0ueL%G~4w1Nd2XZjNp5Y zH_kP2d;MTb!s6duiFe=oLEzf1Lh9W(jNuD*{)UN3bt!a&l0~*RV&(pBAPn02<-LQW zQdD0wpXek=U|b0t3JN!g>Hgei+={Z#)yrZme8~(P8HxI5D+&!kWo0{Vb(a~XJK+?? zHl1wU*&X0N5^|GlKhBL<^dI?QPaM4{ZF34uNrCZ#EZJjKz^zT7U88&8}C05Wg zV0TS{Y~A)W8acnqBFilJa+efuxb*z;eT;cWVLo?Qe@2?PSsxlXe}a0nRrW)6<(;K% z7ReT$JW2?h>ou`-vdW}``ME!^hucLpgzT+m&}-oxSDR^!_2n$ZV`>k7U$_sqEiuBU?drt$k@F#nT zE?M%)#-jcUM-*=N0*Bf!Jf6C^d;TNP0hp2PH1345f5h+$+#i?9FsXQmy9*nSkQ|x5 zJd>I{?9&iU3=GuIYcI znF0)pM#aYUdzZmHgw;vZeZl(G+(pEXm3NKwGYw;AcTc6>%p*)VSv%rBEsP7pM*pHa zY-2b{H*qu$(6#^G?qt0(D?j%D*$;39JU}~wp+XzqnNH&7@UgZcz!_LdsESHBU`tQm zk)C@1G?%!W*J^RaZEZjvfTSjkBz3v^R>CNKbV~%O;$jki<}y=eOc!r(!YHKEHb#`v zpSpjgS4GD9!VoMP%-)a{Of~g2cp%AZcg|=&l%=>k{6$L?B5l26vO|OiN73T}T|~&u zn8NtdLSe;KVX*qYsD+7rX;fuL0x#krXmi%ka2)UtTB0I*vBj2o39imFMK%74OEbQ- z(dfo*5sGV(zI%Z0vc@rljf5IDvPR@ER!VMsA-P*TBeF@i%8LA1JtFa%gc)P|gpFW8 zX++n!3A_Oi zh&XzMg^$7>ng!r5qfDq6=DV@?yXb_U2bag*LhB~N9QQUF&DLEcv(H~F(LO(VcIU&m z&l&~%qt_TI_IF>DqwA&~Mvhe*Nbn|Z4eT~uxJ$DCP@>Dje>8~LJJ6<9Cm*^rwr@bb z@hE8mRa}x@noBaHRGW5mm;Jly|+_MX%6cK&@+64Ak>YDCivWMFmwjC=Upny!W^p$O$2j0P(KNq8HQwxi2sF zVEtc5IkTyQSUo5G^FZUdvSTR&G)DNWkZRXebsS%K&leet`rM87-0r)) zgCs}M-Gf-Dd?_a6; za9B8^I$w9pKo1%?P`2S zYY_Jfab`Q*Hd874MUhkp{gVk(e)}==+==FCtn(NR=-%zfC_L=(0DdAmIHGg+K3xAr zo-)EeD_zY;fbV;y!=H1*h4?oysTL&0EC1;)qDido(6P3 zDN1wH9XsFCAmZMpW+$MV*T(IuNesDV{iFf&GrBSVY>H8IjQB-nS!v zw8xdRuU*y?e&a=I!M}Hh_zVg9fatfkR@ZE;E}h*HJZ2P{U`B0iE@V08864tQCVcjG zQ;07;?kaPyyGSbvf^TK!vKk(pzGZ!pGL%{xlJ6ewyMW`|JoiW&HrLKS+$XTmlR*vH zVuBzJRokOXuEwwLZc|0~@QLwP!-HL3P|1V6A2reVpfJ-SRB6Ady?!dy=6PYOX2K?_ zQ%;?1HMFNHeCQ($B9^|dKg6Z?wTJj7LW(oV^W0x1D~81f=4{X0fE|9ioLup%5Gbmb zqW!ZxL)MG$>k;Fh=&>gS9;lHqEE;x8Ib-La!^t~M5fG<5(q1!evQRJ1c^`kluiPwFB-} zjgk+WG@tEWDz0h&o(Y9>VP3!D>)neYwqoU``xHX@K2b->wrZ43@JGE>81-wG=B~*7 zBhkT=-dO1`q7=hZLAtO!o9B~F&go{lR_bO)7jtl$MQrh!Kg!pfkx;P_yYWTf^RxW%JWJtsy>zqd{+y z=D@v;NLxq$(3+%iZbhQiFuzb@vnE`y=89Fqh8p5bbv52}D404Huh=w{*D(M(kvK9P z0rAJTx*E(N7AQv)p}d1#79a%nP|K5~fc-JotwZ3H_)7H;3^oBVfWd~CJ_7ojW_felHz^Im2`11ek@tGw5@ouv*(x2gGZ!A zF(w()8*GM@U+nw8=m7yPaCE5b$7|+wtvGMeOLK`v9ll3)gDLcgJnBW%%1Pnp>}!Mi ziLJLsE=@hEiZOM^Csoe`@%qyF4x&ATCfX`xwYLs3&I>xH01*cj|M4j?Jvl|v4L)RYjz^;Crfceg|9Xocc z2flr^8Jd4=C*97iFLyEa>&b_4%hya|a0b-L2EcNJhvbhcI;Zi&Hpz#)@+$PrOaI75 zh9)Ioe38eQ^yH;{;2Sfg;;Xb&N;}cmzBHKr9pE;l!-%{~F7)prn~V}!-T`+>Kx6P2 z&=@4t5MOBwR{3#zC%DLNT>Z3R2jlWT`aJxS>LR^YKO8@nSiiE+Of>B!!#oQkCv_jb zwz1J^i^o2qJ552|6gvLgnjN*jS}_%|mbt3qi}t8SDE(PDEadXsToXe-LmpJOcQ9+K zzhNL;Fhpgoi5tbr-gAFD{t(`SKskj25_WS+nU^_K%GA;Qkjsj-^Ne*qJF|E+ z<4M!W*X)$cJO4hJ`!{N=+s;T0C|C*}pNS8hKPuXw0de~2lbza;ZO8qsUNbSAT4Up0 zF^RQK&ERplZ}p=aXH{pV4K?}yxtpO=3@ zB-HS-7i)yxvaD%3R~L5BNHXYF%PN3W06s}=s4K11zI)ctULw@7)qy9+Ls`cd7NyY4 z(95OO|A)Od4QT3W+l3>FmSP<%s32IiP6!k!h>ZF;phZQCG9*B(5fDN^KxPt9+iI(T zRsm%SPN0xM2s_M)RwYV+s6avzB$NmdLWmF&NJ7F{5pC`Cyx;fhoFA`$1@>NR-|L>% zbzQd~-NExSC@X4yAy4@v+R1!?gXz=8B5o58`uX3Ibc~ZFf>x^x!>{!Ju+cW}dPQ~J z%i0_MnOmosLh7);nBj#DYhgECpXTbLc3CD29cq|A%s%sA6*ZkjQHE=xFlL4es-W^% zzdVPkb);KF;`2^#bCHc|Xumv(_K7{dnSHIr;+S$3nZF7njPdk8YZjue;%v#AfArQL zALIaMD(Ov2i`XIfB+jLO+q)|%|DAs|^L;imo*S8x^+VBp8{4iGN1`77cF|YFAnPZp zXQdMN^UZ`^NrZ}v1Pp&NjEwcA(~{5kL9*eqEtZ9_icx^(y)@{C7*``N$%3TSag@)Zf^oRd4j$s0+w~T0yxdc``&ibq;3r+F zSB$!Pa+Hutv_g~+nbLsH z7(8r2+-w!+4W%l<4D;CT)4W^gz?K`E>G)lNRl9gr(XAM@4}xx;cJB{=JydeS@E60W zj1+Ry4=z41R}Z7dqnjL%hMkO2sQL6euU~!nukq&C&jxAx3_s=Qk;}Wz)D-Jgl&9;T zLm`$u>u+I;&vKS={fh^A&nIcvxOqQDuEPZIVunIQJf`I7xSg%&_%Q8j9cOgy{u#2+X6mBQec3vj({n(tlASIszhcGfiLt2N+n$7#b1 z*z-AtgX7;_rozhR{eBMa^P#mcw$K`ObItTz_$bm}7jtG7tobt#otS^bgQ1c${htPe$XFeEIJC_8n$W99}mWVdg;Q_gesBIp3Lp>9T$Ar>m00i zO)~Wm9@$IpGtdP)FcsSApo&8O^&kLf>TTGL9eS{%TmRUL3(KCJd0R*WS9mr0>K_Iv z(T~VM#F)GL+2+&s8~*3etm|M6{IR5WZfNJ@zs6+{l=sd5-9F#bUjG`D!4Dlx`s1v> zd)&gPZ~n58;HTQo{(khPmv;WI@eKUXHM2D^$NPC}ZR^V4U*Y8cqHuc863yiLejB6f zkBZj~_TKPtK?cNwd;Cjly@=p84%R@=t%x zeE9id*s+T)o;EX9R^aESxlSML_a{gcJk8ghK8a&rCU1$coN*}&@$CabgDt#|7LdK~ zpo!W{&vR2I{!s)AgQbyJs&+xuGj`9w;<;7vkKGAfh#jXR1+8bqeh0f6j}&|-{+i;t z(W}R~YQ$JKtCl-6G-#|D+$_p69Y~w$2ToO_06EKR6gq zllG^R+9K;u;~3k55k-PI4E3xL3hqBa0oZh362tWpS;RHPvP(p`O$!-6jT!u?POG>f zf{s$nnT;$x?yA{O_>BhoK4&^zC)9< z80E41V*}Q~mVvE3zvY7(bIf}Mymv(kOm(v--g3r*^v6eQ&p(^l!GP7hS)9M+SfZ&H zD<=SNRu;Z+Q_s-MCkqWt5hnTtsFl2fHS?3Ipe3&B%|tf6*M99DkaBK|u)e{%S77+{ zbiV!@$w>2G_81?_d%GV28<2U$$7l1&|ug@3v6dUKwa{G zQ!~F90drHN_a&Jwp1YgC)Kjd=7MIVbHHvOZRqdWEO<>*qw3xX&lQ$KGzbS9pTtUU2 z>4l17EmxW``FgJ}?*fMUSuP#ZMQZq&=fBa5K9}yj5T9J(7~nRNJM+y<5Yu{FJ}A-q zzZVaDSDmEM)}LQ?_H~lk*r>VuuC3CBi%u_O0F0K#!4TF>0 z15d{p9%DqQFMjdkKGZL|ODq7%Be0Nigh z+I*&LS=bf*Z!q)R;*FjfhlxZ#Ny0RT*${0HMrvm0AQsHkC!mftSay=4r-l_1&NtI4 z(~lTlj8E6S!ijtbZ@k^ka5sBTd;^bnOs@!&8ig@>%~Iq@c5oy&IYwz92yU-W{17HD zOvCY~i~i?1Lj}#4?I-nJj;tdTXyp?lg!K8@@KxJYv$ok6HvX)Ucd{1ZO|WbcV+mC5 z3>~e`3fV4#7w9oJj{6ol%`TAC%>UWYFi`!VI(^~UUK+lU$<8frE>x2qF6Oj{kXKnC zUN>X9d<&r^wYw)F!{^5T%^1s9)-akXW~J#%E%!uV8fv@+8CY@3?c3y-^bSI_fTveZ#GD4rncP(rxdx zR;Rt=A8+$nUu3G9@0TZe|G7%ui+cVk%L4|!{2RmDkpfyn_^VpTAK>M$c%$3ldtocz zWqz%Ue|w2{k^}%!ADIX+cebI>ZX#%aO&6CbAG@iKwr>Yee{HA>oS~S~u|sZmEQh=o zy_Zsz{mI3Dw1_Va(&Vvpjlu$C5ni{?xkO;3kz*egOBlvOL#}Vw058ZY!f;ua0{wET^rU^AEBkQNL7afLs2&^=n zsEhQAkY;d*Sg&v-+*bw~9f1DK#hB5&rk{04v8 z9Eh+*)5F-LD{$pO)rj0S7t%eQ{->bvJ{tzs`eQWZOW3iZO|vl-MWy5%*FDv5>b_^p z-NUW!CcH|5^QF7%+jxQMrDNUap-rVk)|@*O^br*>E8}J{UCkbF_Jrsl&RgvUcGYbZS7o*+&j62qIn{w5hVvB z4(n}$n_t(=eM~`&i4s0#2Tr}&J=DT->$eLATM$IX?;3MMpjto$TfOnWJ)5hTryUA- zN!vg7wu*)|wOF}?0Wq{IgeJfFssj!q&iZGjy*^0QH^#!M#rfE;x{*Ru;S&(zj9fB( z-C~8Q=Z;TCUT^Q-3v;eZIiYbjiRuP5#-Fo=k4z~j8#bW^1fkJMksH0fN8kF*SfWlg z_{FG~JoMG1q1yt7XNNdCXatj!jKCQ>B!Qa#dwkUex?z z!3Fb2V#Yn_vb}Tx+J;gT@4tghE;hFg^caCxGG10)Q8*4Dr*eZHa(5}vjY_+SIHT^M z)Iil6*6zln)Y*ZZ$GuZOus>{TJiS6nQ`^%tlE}yuKEK;r z(VZ-<00IJb!!-49dh$>?qll*JAa`Frv2@jpp0jqFEyhoOVg6=h#+T;nN4MX+JO2}< zHpyR{qhAxIg2MJ?Jt;aeL}_;X@lD$iGx5#1ejMvM^+#%Xcy|zI6-qq;Z&#^ZF)G`P zSZz{zj1uh?@?9SsZ{AjQ1(N5Mj!S|hj&D&5NO zV^rlDyT!=NT&TQuOw9z)og|m4^hlICW=x_ksCX*^v2we~PY%tb#av;tp+k#vjw!m|1U;A2vuMX?2oGq+4T3)DrkO@6&I(BJa z5Jbgg*rV>3?sv=7U!cjYNNe9L_C@1e`*5$W<5FGs7^_t_V7gV!5PTm!BS=*lDxq+m z&&h*^C%Sk_y8*{$QcfqSB}jolWLisAi6a=buNaY+dfhduI3hBPcS zIMrJbBVwe-vb)LU`{~wh2Xbhh`AjmGW0~xtu1#pfkqF%!dBD3JLR_x|eIVJub5}T+p!aT*Dps1T>izr&Xu9zE`YJT*0f2}5QQhhr40_$Pox=S+Q-#UH8~9X= z1%evBfrCuNwlUgcvIHrzmOfJ5a2QYA&-?|p+yaoBqb`D=!e0MeI5XR5V&t?vG>+MH z?KP8EX``vP|8W^(aPiL38D$QI^ZmJ#{hP&0D?GgeO>PyNuWqZ7_t~UXHN(T?TKV~h z%NqEO$g7P#I4)#8$iy_tvT5CH5%ZWjoCXoN zO+z*0vIf@*kjT0ymQ$ChJN-^|sAD%pyC7;Vie((+P}Ptl8vU$ExYSM}KY<`~SRJBw zyK%8`o5ojn-(lpN{Pv;yf`#ig7^HnSo&PRxg6s8EFs&^3RgsYqMThBqKU($y7`>ko zQ1X2gg4C%|zz6O6e9~wswo~Q(Pp|RI`NBVB&N}s zHj7}NKKH%9dxn|$o6(0Rg2wT3dm3TC;acU&%UOw7{L;y$v4{8UJ6gvP!7I>`TMV|n zMP^7S##TMVuNv>u%CoreW0#&+ZNWB3I7oLKJs|eF*11CAhutKL;Vsv2xqh1{0+K5i zr%~}L#U2_$Gyb$W|01V)Ow&;!-bYay1;pe(!e1H07DSdYs2NnvlbEVRzJI^`$aSQ< zGnwjWk%L3NM5abbm?SS5;yTj9oAyS`r3RAm7Q?!cGE=wbzs$TheF3+y#OjZ|0;!b6 zUD8o4V0PC=PyBXni}W?eNlOOPU`7EQquMl~=X76yG|5M%f$8WMOr7k=D3IVN2ct3~ zLsf5TCUq30wF^%^m@((7PNu%^XA9E$cmXy(aj2X=X}8Vjb!5!NS=;7*t?WsU6rFXW zrRx_S`|8V$6A zzR|wSp;gucQiJu>nCH~tz_FXgSzx>m(KPDujOjUIIA@{5cR<(D#lBErOm)*5vSiK9{FCQ#5fDO!aQgqJAygfhK&qRZk z+pJuoF6+(#wl{YAX0@3G8JyB+qRxx+CTU$w`z&&jEI+R=(>K#xD<@lLZm$RKi|me} zLr`o-N2MYPH!$-$&Y5oBCgqY}%?ZJ(X=*uka`~}K9fRyqfVog~utejRp_YEcsg{>4 z6pDvlK%S}Qj7wi;ey8HRYHz4L9kHpoP9yPL!wM2Yd%8xII%Xmrt(gHaq zAA*wy_(5_I|M%#@1~0+3J-+9mcXa7=?epVHAf3>q)u}G^b;YnSXQo62@qtQ^%D38$uGB=4Y5ouK(??Wc<$TB+lnvFxD{?njudpT z!wtW_j^#0wVPIx^weHwnxEeAje;RmYpNW^M2aE=0vu|Q26n5C2j`0x`*t~GVjjEWp z!XOc9`%#b#5F7Rj82ErZ95w(OhQTUV1;ua%F>CNx&-2Xd`b#j~ zRA{2MxwD%^*%Po|ur4rO3#AMFYA%w0auYc8-&A+R=0I04YPsYljfnI#y+zjMH&;he zFs=f(<@{h#uNV~|5mhm%_$6(blJT5n zW9N<5X>|PaRz++yD9Y5laGL6KcT>HH?#S}VQA?A122#lzb>a_AznxnV7*Quzj6TrJ zw+BKY$zsc@tVi?RZq@^_9V;K#SHlnIm~BK*yQ)_k6wzlrk2myB8o1N4pS#*H#r%P< zK^kdg!LqaAekKEF_Xp2)e3Ew9e@8g7E%TN<2-6%s8N{~Pi6=$d8uC=w#+nY-Y~{%D zx!;sFH0AhRsMH3!xto>|NyP%MAt7gpc&uyi*tVBQ7Vt#RbXhlbqnJlVqKE~NSJGej zxSea}JtZkqum~qEyOBOSz>SU_i%ArstvTW(h5TjXcruF}VpVZqs&)cuZ=$H+b*^H$ zuu_u`>fnetR1t2|G>+oDL+oDI-08Ml+d)+ieey*nu6-7NYQ%i197s&yF=w>nUD(Jg zujf4I#_F_0>EX`P{`c&%sc-af5fZP zKKGsa)tGj$aJ*iWB?96TeUixJ%^t#XJl(jdd*lx|An-v*Fk+~ zq&kV4I;CMUToohH%`cD^z%(xC<%CmP$TBNHB(G=Vn^hyaa)(au{Mnqk_k z2XCzwHzSMZ&qMJUnw7ncZ>I9DVe^eZ72(>p$=B^ifZEXiyR)ES_*8J#Q)>;{nRtzw z)ua>^AaRL}*38V*Qz^>!b#4K10&M1JuQC00eeV+T`sAUJ+_mfJjJ6;J*;OxMVzT)M%7R9REx1D>R zt{Ak|AB%DWaWP)`tB8KEb+XT|#rPAk;TbY*Fn1KNbE}nRFzn^~u3MBN4DFZ;jBnlw zG*S%Ge*1D-O!2%J4C6N60iaLd_IA~Q0AK{u-LbDe<-KXKto6U6Z!zvw9I&!gH2mH+~MYW?I`$&~hDEoO`0+YFE;RLmV~~a{j0)a5dH+$~N}R+RHg?EOl#h)7 zdY!Jk6a}4Jr=jxm=$|HtoCJQrWX8d8pq#7c%#!ZbY+wC;U#oc^@^Elp9yRz2Z0YQG zZQqg`V+Jsdewv;HuO1RLZ58DsNDckG3VCB*lceg^Apo|jjPCsIoE`ELf>b9W5|%u; zp(G2)g$et<7p8tYT%+#pC+m$x{l_>zb^F%dx2u~>y5Ih|!XWLOIj;Ku+w;?Ov($n> zVqs;SIO5R+3LjoQVyfrte5-ZZ-p8X5ipEZ%($7qYG=r0)Ju~NL0hgEHekm|BHD(~F z4=650T!Bq=$I}JQKC61X@T$XC{1cQ+WcNk#N>{;$^(TVHA?hx`q5VUKv!(0gjzlJ+ z`{k@RQv-PIy_8-dem!{qok|{u7D$t~L~cRO1XU;Ve^q7rwq|CN0dN#J>p87*0*umWW(BEaABNR_Jqq#|IPb{!q{MXTuy62!WLddGZka-1)MP3OP`m=%(WJ zAp|OKZU`RR1e8olM`ie_o8dLTHAasIjDL+BF02nXhMIt{>(d7XqRb8Daa~@FhsDw}Jtsm@;S?jV(Gjj6#a8%A&5d(r z8-Z?6q7n!c1_T1RnXk=%iviF?=|uk2oZ-~_1`|?96xiZEbHEUHWUYKcC5~8+bRA>9 z3wSl7O=Y>#PwvCCHKKg}n$NUf51-SW9j{@!R6F`+b*AJ*8@PLThs}7L2mqMx>XfI8 zU_ODdn8hbRP3ymLf>gWde&n+mVt267=Pv!Je7O^m4P3X>E_KFR5N+?L3=~=0rRoloc!ZA%!y7Y8(8#|8) za;ff=%1h3QP83r!E|@wsg=hi+LNIH*&bjZZ7qbkh3H#s&ZS7_cGQI^>6?oeUqZ6Du z^^$fUEP?VmZPASKi1mNnN!6^hdLU%P{O;Te_AK#|aJRP)&gQO3(=IA9=+_;f#w{6^ zfLfinzXy35r$0%b_`y1Rb>`$ZvR5;_Ns4cb-guYA^M{{7ahja&Tbck<%~L;HZ1W2v&*Tz^7t zHN~{9yIGH-$6qDm`pWimb$+nbW!$I5X$s(uL#CwkDQ%w)eW3H_TQy^C%sjzl|GU<& z!Jzf358qw+p+3F;06w=mNZMbOIr}9_UnQYvTbAZ$8q7$JFkf<vgVv2VD9pqgA0LIiA>2ufESB6Hqm8e!Y;#(z+>cU&%ZE5Trndfx6|-{lc_)4n1l8 z0aH4yjl3Q@?dU|SlQjIyIAcY;zYNIp$&BT?>lZG7LS#U}$(0 z{p>AhXjK8QvsDXYq8>;rYc`gp#Q_HI^$N==Llb*mjc{YFK&`QSQvC+CaaiH~xSl)-x?rCK02!e3bL z^VJj^5ox)lI{_s-YW;y?|!fym9XmUA4q6FdI# zl`a___33e%O+P|P!mocT52FK!I0El7E>&>y*{ok?cq5am=p7-++a8as`J;@uuHSK| z!y>^NpECMvce1Df>zU@tpBk={T4g$qKFt7KPHbI2{DQsxy9>!x2RQFz_bwm3ZKtC{ zPsbobW{l8IYiN=&2Xx3!v(4X<(>EL;seFTfnqfG`cRd_v!X$j@v>?j)kARd^x~=ZZ z8Dr$`4s$m)qbbEnZ*1D>t*0E-EY)>S0}Nn>*_<=o-o`T}n`evA4^_Sq+vD7d^#|^F z!h91=eXvJ{nYZ{tFkQNlPGz{LzpU zZjj*CR^Ivuhod->`xS1|U#8fYd~9n=rR<>jlrvRU8YnrYyctsQ#-GPp%2DRGC!W%D z?R)Xh*`dL?L-g03)@2Gq*5@n4#s#|+E^^ynR8LM`k6E4+3E!bG94XB$5cqP2uC^CK z464|@uQZc>yUf|}u(Id8Ss6hBufSo@=Vc)=9hG+NjigZY&wV@(e4-C`LU6Af=Uu_U z5NaB~LZGQ7K~r_~(u^oG$Cz}kLZFvbRyf7hJi9kpMPk+L<Jjculnf;s(2K?u;W1Z=4&1g}csAcIk-`6>>f>Lb)BXbg0Fgo)BeEeROZp}fX z=Bg*hcl4FA2J0Q&3Q%)1PD~QIDsj0xrh+kthsg|{|8-_Pjao>U$60r@;b*rT$c4yA zY<*_axJS_M{w5h%QbJg9JLOM^-s2aQZiV~o%*GI&vW+FFSl?>;f+W$x#0y~ zr}cLu#xd$27-BJT|4;~>kXzn;QQYRs&ELpW#X}PKIX4SIYvXy1&@p=}8ksE-RE@`$ z)1=Gt6w8x^xQeaV2Iz%9gkDPlVC{0%5ZRv8tXL$HW8}`Qe(LKo%x$??X3L`n*Svvm z?qEwjGb!3!4-}f@D}p%dsFY}pn2BmILuC2%I$mz zG9K$>xDI+&9+)X{?p?Z3hAwN#3Jp1&=T;hXp6rzqx4WB=-bjVilq$Pi8mZWArY5f; zP8%*KyUi?<1<|_jlFcE#0mrSJ)(J?G6dsRZ`;+=P$}Ix#5_Xa5N-eDJACg~=s^{@U zV6NIf^(($dZ|Qarmp7&4<+9lkzoKfU`kvsTp5necm^k^vW1c!nVyvHB_-dl8oAn*0 zw_edTD71!Ohp1TgZ>**!0$%f<#Y{~CjXsD}j%3y0O5y~X(_JktaCX_3G+vP0FpQRwu@hw8go?CMqU0&V`=PN#E zRBRP)-G$jFI3PT+FWHQ<5RWF2IFA$-#O8jsuU{fDH7-NDFHF?WxR4x9p&AJq57&&z z+$GS6`VvO?jW~p5=brB_#}T2L&64~{KX!9#r3aKL?m#c#ganPqpY;#P996b=3(C#i zeB|hQPbs{hwouhYM$cI z7&YNhYg1v~ppV74IB<->S8PJ%K|{o1RU@*A$2JnZM70R{?cpXq>_&K8Y7`AHpW>() z4sq0R01{+vrVm-wW#@9YcC_6xr2o~8x|Q7 z9HgjK+GEEnhiWVAsq@?lThQq9F}s9347nVMkwDrg>1M!{QV-kMqDvSMv zzIn*_Dm(x~qMD3TZNlispNtaHtLzU1v#Cx0K?IDzPU6iRdf9vR7A z+on=(CO*s=D0kZ;ZnL8j8fe!qRAxm51UjutE-XmI&~~wJ*mSVRVjkNipk4ulILoT)4kt^+kIkk074PmP#HI3=$_7q$`pftI}X60P~$`OR}=LPf75Pf!A=Vo>k&#`_ONLk_d^C8u`F-gu-QU%^t)u zP9G*&)67f3vKO*eW{^c%Xvo&n)D}%4fStyfLp7*GDyMTd`J9`%OKZRMmfTKQqZUEY z^0ELYOsv~P+kgj?^QM5+F8++`5m3mepoPJxIY+g4>p|T z*iMS`#xl{8irNHr5-ABPgZ!A?VPPq5C5P$0!C}rFd>PMfu|&2!7$tuts1W5qWs(iq z3}rngHW+U=9^kP*T~OS*Ml3qwhM7SKXo2IFf|5(Tny%6$eKiQ?8C zF&ZyQGGVeiilK4ggglsq?u#;wM7+8RSf2kFyAxw6guH%2EAFQ^wKpP6R{a+58D^uF>_fxMDkX{taM0>7py? zb#HjhaJqxL|Je_l8ZWsg<*BJ&CPY@1O&$Bykzu*`P;#CZtAjHrC(Hffz{Un+>i0p1 z5a}ZRcz~Bg^#&1$&goFr7;{mTm;)w0n2MxGQ%38zsEN1$INdiw7=nf$C+%XDidCbH zv57+EaiLYMePrD1mNGF*X!0GC)&Vci&HuYhPSIki9**7lKQ5yN2gkR-%+qp1r%kUSV-ZZ-vpgAlR-MeQq88|eT(ongK)s03UYG`e0 zGQM7>fU_$VI9l$A-AHK{K8A=1=WvGR6851Q<($?B3N$$+uJ}U!-aKso&!YD6lyDZ# zpB~{B9L%u`LOro;jIa$8huj={mV*z-Z@N};A((-hb%3fPDsMd~Nf+UoAP8LY|o*I`-j5`0ypaw_u zbdJfgq*UdGEoLB?;#a{OvA;kxbP6N-zH`wrKVR^K@F6@xTfgp zAJd!)-pFJxVj6{-j4#6T3lB#Gu@6i&IszhX7p19}<&lp*&nfaY>wvdgQ9ER==qxNB z%1T!IyDfKDIZpX&K$F7zy7?p0{AAh*-6Aj~-+obGf5>eXt05hXfsa~2OHXY%M$d&K zsq+Pmm2xYmoFR(nZaTi;PT-t8PGg2dRgWufS;EPIJZt^#i3^$GXdwek?jq>Y z{(>yv2U9FVR;W)9NEH9$k#=^p{?ZQRNH6?2wb4p*?IoLQ@6FM&qjBW{m=%7B`QX%7 z$B}@)wyrQD584HLi;kE;5aT+$M2ZSo%De@~BX7xNn0kPci{OeQR2(EPv2oNjtRO0d z+hLXb880v|+$}&X0ls@*Y&mfZWy!N|_2MH;8H)B0$xHl&!6V*z9znQf!hT{T(K$@4 z;M}aFTp)AdJ(q=qg2&IW}-U{}y=vu0lpliis^ho^NK05%?AOVA|Pc zAu7rhYPPRghuNen0Us%Z?8F4ZCVthj@yHNOdO`Ge)kv-hd0H;z@EiKB3!j zU9zMegW|=$VO0kUZ0~XHeBusZTN!~O2U3eMUk#!(G{Q42Zp;u98(RGmO<9AOa6#O> z=?f5mZhl8O1R(2^CtzjCY}rcA1tTFIjTe zl1KBL2t$=^2SQ(!-ou8`{Q?e?&+;O(DfeoIw!W2t5zS>_uCuOm18aH5Zw2I&b1(D~ zUI0w~7Z|r#RL_ZTPOmYaTNWx&5&SUr9+xhr9d+ZV^Y_4<`EutgR}MIaGE$xDxpoK9 z7AS-~6B91QPB~GtW8TE9;N!xk$lulsb{t@-33bx$un?|D)p;V8BvuMO*|{^Ncsizm zN52Qmuk)`nsyyHK>6wcKu;=wg*Ot9p>M*!?5APGy$tDnrcIZbpCRzS?ipzvBex4A^bq1zjs^YYC7g7JFgf}j}3&~3ZIS0LSxC-0pO^=t9 zU@#!rMC9?hu#LNRK5lt`J^0ZV&ha^&wd;)Yw~{5DZ-X&kQ}ws+GoRJeSPuE78j>Ev zp07gRb;*gsa-E^r$98XOq&N5L&TseW5xrLf8scYR!E^Cr^R#9wf*-|wq zg6s<~s2Y_hb2plqy4F_!RoV0VF=bbhNcK@$+Ub`xA)|r{W}7YJAE!3_$U}wGn`_GU zQ~L?^XfjsBQrt}C2d+~~f2cxZUvdy8El9Pr2z)|HYZDsNK&4Ub1D%Z1F+uj3oYpUr zTPmWRW(wBwAbdCmJJ?LMhiZuRpq>|nH`clo4@2I3oU5@+S)PLF_Om~1~JW(Br&Z*16VVzcTV#(S6{(;P8pYI1u6 zkBAt*L`_0NmTjshaf*6YZo79-lr`7!7M3xN5|^h&U?yeNW})ISvPW^hcU>pDNmH2Z zG7iu4C5gDMLs57onq1y=Opv=A6sKCQ>hLhDwW)XcW(jXZgHC?R3ocE+h;FH@sX%XW zI+xH5MY{~=($Q`hG`h@|&ui~z<3MZtCeNoUPf*vwk1H4~=S^%zc=<OpkfNx>eM9Y+tM>}jci zPDopjDEhUnB7bKeh>sx?S7*mdAl775OL2gQ>nCt84XTb;y_w{ZX_pfTAll{uw=vF( zL&;?XB7#?QTvS-FqYF*+&*b-KL7JTu2qN;s(Wn@HtdPlTyc&S1u>DzfFOY>b0dIxw zVQntNaQw#oJn>jy5BPtu2ZcdOLI>4otYYP57qb4MV~Lp0AT8SOY-(WMmTV6D#%738 z#DIqN%mV&XyGd$=*eh;B3LjAuOpDeb~aeh{;;H!b%!Io1RQG1uEr`V51*BI zq=eEs$O|;5NYT~VF&wi>GHI0BpeR6QqD3#fMIDaE>Zmkr{_9noGi)La$4V+J@L^Lu z5C|et;vW<@Z^W)FYkce3-@O?s#vP3w2}43uXe%mFlF|#Uk$2JOl}Fm+x$!O-aB=xK zB=_Cz`v>U(KuY_yFMY;oQ11=qq=J$aesC4ISNU{$fe|uxrM#W}T`W5=lVXo06r3is zm@_GH7f99!cR@_knf({8>gqFY_Yra&r2CeY68UB|VS}r5 zRYlCxKnkIrwd~aI?u=AZ*RE|xsz4rThp~iYKcT6yDtlTaXX{u%CP8-_hkp;7`q{LtiTUOnf6~UMlfhJ{T0WDOhy+4wVsFbQIV#i!c z5)>DvOHfb<>q^kdGNiz+BalMnd`pT=2}MmLxp4f{alw2sN`d_>$0h!rJPe6t26dqY z%8ueVGfZq?%Q8MBmy6cak@U%mTQnZtnzIzQ&kxOKRPUxp{3$Va8-mOKvOslMOlKev zgP|5=lG{+Jq;eXXMiY-T>Q1HYbV&`?_In;R%Cmk0rCqJEd|ni7?td3b?}Li|BhYq} z>>i8CvBCV5ZfMqNo}LAytWy|CC^VjlyVTkyGOx-{wa`6nfBAd%5OLHe( z>!IivqA+hz%Bm+eG@;dY#)+S)FXs3mZuMhKtcSs247<`2gbJmXTa{`-syu%)sf>vE zdiX`9_zC$Io0tX#Q@l>7IbAWvbKWVG|SwOVnZPTRt}m)?Z(!_@nd zXxOtm(0)5ohR?3{UdvZaj81e_wFwExV#x;54r+^(Nf9X=%E;FnjDSzZ_A0HvjbNb= zL?;VbOj);-qk60<4Zq$H1b1^ISBkLg+ZEx3@S6DRBUm*7cNtG?-WB)=Dy);1xNelG zL5B;kB&M4)TlX}gH+Tu3#O;`j|GJG`Hi8N;ts@ebaaIwL)Ofy+v)A>4v*~^OvVx|` z>mQ%eHoN#d9A42S?P$yZ6U+ldw;XNR9sNvppSX@K6!)4!5V%0xJ$+LIzVZi3tiwgs z9e;Y4dmS%`-poL%_)V5~S6U_<6h~T7ek9fGH}ASjT&?&CGv+ML;Trjuwt&D(l6Qc6 z9^VL+9R8M5Xbq2GNjBBf@E4QQv0r<~MKFhnEpWOkx{2NCJsc36A_!#nA56r@z1S7F zqh_dv?@Y^N-_^iPkk%BJvFmQbPa0pKh>xmT4y)l#9YH8iEE*O|+|e1a)cGbB{JPMP zOC8U`Q$k}N+g^oY-pJsJt!JqXOezF*T*qK)`y;$G^;}m>3K{9nQFbm1L6hZ}JTls) z+zNE?FydW1yY~Gp|5^~$4ZpOpY=;g!~(7OH;3s{ytO_YsT z`~UM7-(AY;L>Y9~%^!V(KVR1V=~@5#E9cMu?~eVi!Tj%e`NL(OFYDjCuHdjv=JWK{0(gV7nkL-Md9u`|NFT7Z>b07d+f~d3)j*^ zWRn1|WZ~(mJT4=gw$-{(!|s zO+!vTN=f07*loBIb|igG5Fr&{vz8NyW{7WBBG5<_Eb!qe{YR3TDF-}|6&Q=fE{472 z_|dDa!1cJiBa^bHNPs`PjPsite2)Y}&OY&0uHAIUT)0q${9N9BZo}yMrTK4Dgu7{cM@9h)b?VdAk*+aH5 z!%h4a4RB#ub;Gq~?`Z8m@*v-N*9wi%|d z5+KTDYGY?B{1APP3ND^lbGlU>jIRFAV89R z$K}(_`kY6msRp9~FxqY}%uve&ymQGiNxP@UE(1FBTrgF(Z3>J%^=fqxUVKN5%#Uu` z0PxZ*YaM#bD@0NO#VwoJW`|u+s~DD@nCo8!1QQM-FhXZER+N-4s9cF{$EOP}%qJku z=!Pwo3j*%!s}2 zcb{gImI+$w>M!)z81&oZtF+b}bx$o2cU%jr(5UU%EHVR6XCLds1$YO;YubJ7BZ>Q| zAIxK#i3EcG2N8!apdPyZgk^Q0>{mnUO}Z(RO&$O$-KZNGoIW+ln(_~v>^08WLRYrz zU-aON%6&!b;l$RMLNBe3u@p*C57*`RfSE~sN61M>7QZ=iMmN7Tl4sF_eSO(ITQ_p4 zZ^v{;>-05zOjfwJV{co$DkEO;AQvJ$2AM{nr{*82V>&PR*MS<}^*N04w^?xc%{E>Ocg(hpr<% zB)^K~*x|sGD+?WZ|H`ZhK(whA3X`tF02F<%9`wR#Qb(K00k}uHj(>APySxX?ynY8l zmnG=<$Y-X$S#u%nnNN z>hy-`0JxtEo2;VAiKCCqwfB|(2?Sh~lY%oNC3swt?6QlF2b`CwdLhz?JyJV%Zx?K- z|LwEB5;x62M!d>mZ;?&6W;i}anCV9IKlxC9|8u0l_kbmH%kOMIuQnE413n)!eM@&| z3M-AaGXe1P=Wk7(n6v85t^M1OcoCTj zUOEyGb#5^M9f6bb^>ZdtJ30ym5Z+b(=R3nOPP3x@&iv2SD^usL8s7{2esxAHb5`+^ zedE~MjXz0F6+>y&p&C?T{tn?|7nR1NLtQ~LfVue~%u_RPW)`+s^Yj}Ozf+QTxoRoegNyFbVCZik32Jhz9vs#}P$$aQro|NZd7#$N;LTgBEv4NK;Gz6l8*3dXT2ixJqPnUN}TVX8``NPcBYM*GG&{*8bxXx>C!@(xhLX!9p5 zi_JrvRSz7Jp9z6(ANmb45&bsqZNp~BN!-TjCG%o-?Wfm``Mxz)THE7M=bz8to|~ukJE-`9+79D~p1P+=km7F2+-t>SoFa~%HZKX`C9>)_Kr4*2Tz0?7-v$|Y zJ@YeEdEDUp1LMw{vJEj~9g_JYTHV+tL&i=)HRZ2A52YpbN4!@>+yWxmC0HOekRJAu zR|uo~0;PphnpzQ=-DFL94_xMT!)=0IN^aY@LK86UdnHQR*9beRp1WeLGt0*ce-W#% z-?ZZ94@d4>1h=nHO}Y-b3?Smr#7`07<%UmWf^UMLRliA=d8%{>^P^Py`3;ePt2g** zS$mlQlyxYC%@A#MLeel;mWBE-aX3_EOhJXnPV90H=y8c6EK~VyH(;O(0%Y?o4ni>g z@m&|>iXB+7`!^w0Dz?*zy3|>|Q3J<#e?aH`cwUY^xnO!D|8VwS=CMrKLNM-lRyHlE zaDgIL&tOnw!lo6=nADYM;Iiy5`_qE0lc~2J z)*Ume9{7E}GnA`Xpi3#KNm3wY0?O*HPw-=~i+;WfY&qhhTpcHfq{@IAr-MR{y*EBm z4|sSN$z>8_K{bQ=q3@kY#KvNO?4t}k$*o6~z9Vf=*ApIv8NWMcJL)V|1Y$Rwj-+el zm))P_DK))k`T8X&0?NrL`3)Obxgtd3+zDWX8C^>Y}}vc*yk7)u~A`s#x?L^e&Vs+H@LY_Z_ zkOzL6Vgw^|xw3dH@<|f&=XR{1N@RqzeOprpFfo!>TX0sQFJfrNC=K{a-(HF;8lwBE z>Ch?IQ?3_O;xt-l3W%T7>40sTYYJ2)h?7BxO)5WK7AZ}vYrBOKlRy&-R(((J0FC=4 zx4H14GH-q#3jslcfC5DxWGI5{2H=(bzBem;OgH-75od_(aZbi>RJZ-AePOqS`=-08 z_Vm9GA5*|`m5TGCZ4u(!9hjez&SbYb#D=TLFYR>I_{3nyzo>r%p7PK4+IC9-_pwxx zJ!(rFZpKbO;8!=yjPt|Z(}LbUY zr{|tX{XTyFj-~L;+VCAI;A@Qf-;XFdr&b{$3V0p=?^~?aw*nl%lkbLgnc!Umh$(kN znUD2zrw`BnlG{AHi@W53{gJ3`vHYJ+lV?{0)*z{WmOK~TlmWODrm~9nP2;Y}T;xWQ zAzysu6NSQxcLQ9R_`olXAzgi>Z^cCSS%G($ZpVbM#||xZe!-VV-R&JGxoS(78qZj% zeq5BLd{_+vQsYfOt=8IF{F0m#y+5d9cJ*t3h{*GWQ;l3D(Ev z*au#RFn83D5({*?or4pqu0xzqNO@I3ao>-vSGhh)A#9(OC^xBVy6Y3P&b*j1*`qHM zhS}9exbccDX-1~v88J8J+F~`mWhKIzjlvc$gEK4H`s5k+ zh<7>|<>fOvt^_GbE823CuR9$veT~`^-|1cr|wbPNG_9~BG zjLL&aauc^ypr+#%ZZ|DuIMAKg7228D%;@X%;orS1<>FgO>NM(aYt z64UXo0M*KtFw$PT9*O|nXy~jm-_m=Bsbc`n z&{uZ{0q=^*%cH}Q;G+P8AP&VBCIzmB+t_h-c--iM@n|K{<8HyV5q1KGOS)D|vlXT& zQm})YJ04gSx=%0ckYuB{yY)NJJg40;MVG&pI^x59`cdU06d-~bkT^)!0)9=?&MNnjr*GY zuak=Skw?oBpHS&_p>M~zv>i-hGpt9qX!BhPJ9mJUVJXR*yL9QBnRnjIJQc$t&;8jd zP2$$J-eVfjsS#4*QB|M+D}eLf^`m}-Z7p3G4gQOabh^=igx-AiDAG5t$RFiVF{g(q z&VzqJp9eC^>27~Ds+qIPbP0EFnA4gojS#qy_K@_ud)R?U#vZqd)?f;d*iNUpHNb$o zMevNh_8IYU_pj;BA77-a9P+#WwBW0beY&pr*bqUrZSiNyoc zVBQzS^x(E!cW^fb7$!XulZWCLJ8XL%cV#g0Z=b?3wrk`HWGUv9Ja?2$p;X=JmZq{bCYE!f1XH5P^4hU~unz;1#A+wY5&Tr0cbW7dHB{EYmS` z;9Qx*c4^i_Ik7j=&U&`_^+c{svR~F?Sh7vjbV<1H3UO`angmh93@W0-v=ez6t8y zk8CSjdS26`jS;scd+~`EPj`_QKMF^3ijWCTxQ;fT>)qCP6fUGTrsF=RAtQv9hPQUC z$ggU%L*QAdlf->JZYWfiJ1;M>tt|l0UBSfzj0klYz{A0GiIn6k`T}n?I!Q9Z;z)1u z1nd1kF4z}maBbCIUIBOdB@~$Dp|I=agO#mYa+7p}$V8<5XW(#Y-msN8fkleeAcWEj z0~qMNd_^~0n%ND_usvBWp0&Aa|70FOjKmK<{6r)n!iF2|NsV28Ppnr5=n%rv-3h^p)jqywAdoaS`GvGD0?E6~ z>4+X2EQ+{aNB~L8bXLX7O1hCG;P)n98jHCfkK*6)^J?GS2G30mToavGXw9yQB=!!5 zjG?St1x3NHU{P0@6YgB37d3R4NG$R<11AhUB(E)eI3hG3)kCMBeA1i{LYyoLnG}=2 zu?65m{$;sOwcQi1Uj3?3S<^!W-&!}fsIlE>j@|tyqtaqhhq_w$aNXL3|0^h4wxRF% zUB-CsxPuQt)&6_tT@CGZQ0aT%I8gtt_=w<-GzAO{!2yEP( z-QFyq`B#vNr04L)BwF3js#0Dg<2DuMgAZV#-Fa`qQM^6i1-)kMXT}bynI}WM+Lym} z_GU=(0-x4Ze~2tUI;x1v^Z%UD?VU~x)2;Y!%AXKG%>=R_533r&uZO)|{C$o%!sEB_Di~a9M6ivegTIT<4 zv2T&T|GNX`^|Z{60#~e10FegIv%0RhABecS5z;tQNPn7Ye{_3ST$R_{-kc0bLGkO| z6$NX{+3{jwzp3}tT^}y{ARybZGlb@+DW!E3mTS_bYUO^{(lgTFSGZe;lrxcuOh@{e z<;x&0*w8grlOeNWR?m>{|MXN(hB714Y_<{I4QN-aExQ-?$_As?a36CTt9dB=8o07u zF~fpEL4=$#f8P>cS(S8{-uiPUuTB^8DY-j!D!2 zR|StL7eE<>TVYDqRI2ce4r<2g$Aq;g@IIAW6a4M>4uBp^FS4mzLH#%}>q zV8GX}=TQxQ}{_-A<-?{GAc|j$zPyDXyFtldn>PS<;~_ zB{wo(sc(0v@Sk!iPxNv!h2vh*kM9|DxfZq5-v*}CP213XFNl(={+i*H-1cY_#E)|y z*;sZ7JY?lONKBi;Qx0f%7AxF@lDFW{MMsmo>5D$C206%2t0b`DtS!3O=331V4Q~t2 z!y@NFTIvc%)DMtCFRI)@iXj+qxyJ)tu#&}8Uz$8wRqI)ixZ?aE2z`wG<%P}7tQ(1Z ziO!CcBNc<%ZKTjT$ac^{3Tp|6J*s_CURBC+pi3K|A)HX;U$5?FgItE9eDi#Y{@KC8 z%%{Lj(BGDZtO--yEg}6<<1Ozj2wkdW?6t(TmF@{}=NlnALqk3Mc%u789jj0avxSd| z#)FlOFfT?O&miSUL}*H=Q4yc16x07n45nn;woC!Bnhb=MRiwD^4_EdpR7j+T7OPc1 zS78R~;`DO67`C!FyWY-MAj1No_lBx4n3Jwa@S*blG}Ew+v(QDKr0tgG%s}6t9@-X8 zu#oj6nR{qPc3&TPIc|wt+FtrsH6{#hmtWT1JCeNk?y!K8i!v5Jc2jPW2%ogfCe2VT;Ww2IW(PR06v1uWY=y9kJl#=qJg; zFM2xP#OA1y`Mv4$2f`*3y5&6-og{y3o`3ns)u7&ajw#U9=rf~B;VF=7N#^44a#8-J zdKx7#aI#v9VmmG-Aarq^yt1JBFg+A(*~?`r9n4ShMWD-!z=Q6pI?nP^9b}mfSJ+j1 zD9QMX;VwhvJ+VccKUfVmSDzNFE}+fh6bG1*r$#2ULZ|Gjy^>(0o?tm;>?$tVT~5<8 zB=h!BQwZ3Bgdl2@h<`w>HsmS?kY7rBSRCOlXl?iN{ z0b#-Cs7;l|P^u2G<36gD39`s9MXds9_UegoTuNBgM-6W_ca81UaQQ(FgHn0iQbSdS z9kQmT8q41~hHiv(jlr*K&#j#Ny@-FYB0Ykb;$P)1jzRVU1*xe#So%68Abet+H>F8+ zU|hX>JamnBzM)b#!Mf_Av&M9)GVv1?`J21D5>0V6MMe4$mchLzDNQvcy$v$WuADpol6DIncp}OE=w;*U6(#PQEK8AT+MArB zVD$u19i?g2Rmzi*#uQD8wA@l~WL_*oR{A_+_>H+?+u?)1+f)r%a-{MpzK^!l-hxhF zZ3^_E9{~&$xtYhBSQ}-H&$Yp6m+|1r`+M3g-_%OI#iK_kq{sj_OS~L)B1>gL$bg=b;9?7TV4rh82lV&P$_i1L92rtWSsdXjy(^L=W@8OfV>*dtxi z4_*zfa@nIIkvu9q0t|q(Iisn8jX-3*OtKcKQ{bxlL%N#!RWDz9Z$m=t2lZX0R7@O; z9N_BSx&^{yPI{hW?Cyzhp|qD8`JB66Ug4jfW22l&2co!d1x+PS$)A+j-1KJT>h>am zz*sLOPQKXu;{g-trBq|wI|_}BAn1_B@&KitTi}VK$s$z0B5%?1~44@Sr z8|y#ppOIi*bxcM65c6Ju2{X4l3?CX9c~L4YsT{_x?m(|2C=0|p*f@;zL(rRkMk-RT z{NcP2+-Pxb!)bV#|0Un4i9dpBer6=I?-Uc=qPwg)oj8O$S^h9MO|bAaV$s;-sZ1jV zfaA@|FH&o7vO7X&(&HKe7s9Rq`5G*=TNpxitDC*wnnEulkTOe4>2-pmN%nN#yW~XS zC~{ar+Hu-DsG}S?ZXVAJ`5+MsC8McCn8W7cs@u`BTdSuXfjbZUOJCq5@{i|}ZszKd zAEF}#P-EOH3KwfqQt6dSNcDmRMwU+`Xw>6fhkiD8i*_~PvI*NPv4bVO@lo)P^@72V z8!Dm+t4jow)E@FwZqWPFjMQ{OMegLGScB+uK);fQwHu#AAn?&O0jc8X7*W*}%bV90 zb~OWX4R*v;b+GQK72BaMld$+h-Ba~ie4C^@)D4jiD_A3WQEo-ac1b^__B#RJLV?li zQahaX()ir%{8fFyYR7t9?lvuz)B(4H74OpfxrmK5)4s90NHeC20w`A5%P74mSQ8#P zdVxH@jKaY}?W504L~sV;OATw}H^`WSqu$jLX%C}5UB-2+=gG%E_Ug^H!W0U+7DX-$#PN7Daxt{dhWoIbhM zPpv%}_Q4W(&rT>w~vqA*aoP_%FRi{oLR#tWmf!bfkEi8!CfU2j2W&tx{7H-i^5`?f7mY_rAC3x*sx&(%9}oIa zs(ZTY6=7}FpO8zHqg>7(s%LZ^-AnLyrrxn{(yE3hM(Ett$#eR$#9a`KOuh~{y_j&K zC}1E3Mj6Pqj87epcqhj=F>{*2$lZWgxTZ6Dw5q8>PCWoQAb*ZjqHBXSD5F#b?X{#M zuEPhoV34)S+*^{kq9sC!v7yZZJ6}u{2I#s^8j2anyz+{?yZiErNAs$DI>PC`Z@|FM z+qL-9Oa^&q&fdl5Zqc%MgBDNh*kuBm;1ED$NPL;=N`Wp8sH{@QtduRdrNoT5a z^$ykhOp_-`TY#FUv%kihPI6)sn@jwIuYH-h9Acz>b~UZG&s65Z(BE`!v&Kp^y*$L- zAY&hm%r`70XAGLP=F<$3@LAEi#4EvLcUNT0n?6>x9AU1IpTSPN32GsRr4XVgZWghy z;$s~>ghfBkt?Zu|X@I(SRYoC{rjq0)X9N(lhNdnqmGcMDa56n zf=>BgNUWW%$!J|re}{1j6dEYQ$)0)EP?RV7z}6@S2Nli`3wkO}?h*#D9Lw|C7C#BggjB%j;T`Fy-;I=YSH*Q)yw<+P~yRsaZexK zAZSs#675&+!(d*+dS5ozkhW}bs7~0XO-01k{McP`m)>`cUu-nw9}to|(E!SIp$fk1 zug=YYwqCu0J$?gxlPN{Y#MgT7N)htE`kPXx1`b7JQDmHypw8o50LsPOe685_Mu<6p zCKfZcX4d>(J+ULi<@tpiH%HAf(R-hFzj>UD8hAT5wW0(zpX72|#l!0($;arTUedTb zZqt^(T;f>7%)+`PuSrtqqCmt^eF7G%wwQeJ7jBT^p$56E!&UmhJ$un~cAS ztqqsgy-=*_HxX;m6qGT#(W&0Bssw6-{$Tj(eRHW+Qm(d1I)aT^{VsPX{~SkbU1HjNxHA z_tr@#spjI)H|=yn;2Y`m+50Lu$t882Yr%8U*|Jx~%OJiPnBz>CEyyMu@wBEioQ$nm zfD|O2(oUv&W~i*fTx(8sKC*p|Sr>fKdlQ-h|>51(zBrNwZ)<1B--?N>pfIbc=|D7v0p8 zv#vBzrB2)BxlogblfS$-uqi82oYiPQj4?V#0~YBBCUd+RUa`wd4mupDl3?>@TZ|9& zlVjagj(go^zVHn7akXIN4r5HqQ@TkA0%9*pR(7}rcNEWG&r2ZOpx+?g*h^c(k5Y?X zQ+QZRKIR>bbB4lw*r6SUaf$_?>^eA1T48Dkhg)p7-+v*>iweoUTb```y*aEC7xt*p^ZUzQ9Y#_hd{VpDya5j zxfxv~7D661DrdO2PuBZeFLm`Y+j1P)ALWpyM?Q?9LjBf+W_0Y@t%2Pf>adh}#TUxB zMtsv5h?ZB<$|478NBAh4i^5l@a&rq)iWwOnkQv8&PNImGZ3nR)nx?ZT`?YQuGJ7vj zzUc6#KwfjlS(YP%@;HLAl1!_a@_4m~gD}MP5JpPjqFX`C#kyLlcgi0|7|TpUCnGzg zgpA33rcEcK^{I1B*mtXHT0h`nXUBxhV^ttLCizI^DW$Jv|s1Zwmj=l z&1fCW%eWd06>)M+nkB7jznP6qUQ5VwS~lsbQ$|x3H(DM&MeYGAq+Rx@P3}?FURWD` zryugiZMJurCr?>XxC`)>UgwBEl2ZJ!BsJTfgXYanC%c*!ecs!*O~~85l2Unk6nrIb z9~J;%muCJR18YG*d0AoOxo9~TTjdr>PnkX)c)=wNBfS(!y+NF?NK5HstRp&S>f>uf za>bb{3R-@MYnByou2habYru7cqy5UI*->F=x1}}mz%gj>-esOJaW|Gl-8j7femNcH z%~3mhW^110j#hdAFZu<+D*eH!U!pcH{n~{5ieFDF1rZ#S^z9j14}|x5u-q&x-;A;-vFQS|2?QK`KX8 z*r#9@E$78#!9$rXocJw}F6n)*bUg^Ur&r#Uv@qbCoqvZ=Tl*XPpW)E>Fe^%CFwgfJRQGJf9t z&}cvO!|LlUOB}t42F;H?FXSZIlv$y!swNBhcFW}<39oQ$LJZz6bRd9xkGra2pqRJL z!!$m#Fx5oj0>4Kr5u)~DkUfz_lZ+h#pHF7Mr?&!|8rjFJCa#n+dVzf^P9TVUV_Y9X zDaX47c3C%3#|B5aVPal|QnQ(?z8655ITZ1fd}66Zl$>%Yl_m)O#Y9kxtY5<#(xOK9 zrkcWB4n%*nXY0Us4^{@TtVJmT^zfkXn2;v2`*qOZCz5fNj+0gi zsf?_BIhR|Qrw7Y)+skWiKIq-i!FWUzn97#$j#MyjBUj6rrNAM*t$|P}wdR3Pop)A%SNCObM0TTkt zo71PRxpQ&0`ANs{Cy*gRjPn$n=C{ZMH zL|5FIXgXAH&FGv=NRqwp!G216az8_-M)$^+q`~@pl`7I;+x_-bJW?5&DvMm*kiguf zR-4y$2)dEDgHos43Oh0C&0R(%jc9kLsTi`DQAOfBTn2Rqag=+)SMW+4VV7FvaGy4D zKcHe29X4LbYsf0{hmWu7L)g&i%^P#$dqis-qh8jv1`7jBdtBV1t=KokjI<&XN&cpx zqmKdr&O^q16q28yysIr%^_%y7D`ZwRUCn) z+YtN!lsW@D62eK*5#4M_s;G>(gk2zOuo;|u4kG4IF>iJh7hdxTOj{fA3AR%+RRHna zIj1DCT~~Ezo@&?a$TPu{-R=&(h1F%osz2;EcW_|YUW7JiP+!tPlBl@&O1pDwvz^m5 zR{Gt$b&pg$n)1kW+7Wj?ahZFM28QL`ZsP3=eY^?sYvq3LO49F5scqgpqLmD~Canmi z3y_pLarlGdCQ-y!9>MU#*>6N?#42#{mcI3`FF}8te0~8t==nQNe1PQOsIJ^tmb9T^ zsQ~`i?QDGrN8E5m3x{oJ;b29{MG`EmEFz2y`@nq=fN;?@=hpQ~AYdl`u{o14E^c2d zm9%*2ZeyE&9NgTEot!jI*3zpipVY>h!xS6S9*I<9K-RE;ZW^1;H~!^8HN*&;n(^VHh++)Wjf{3!o4_!10=l9K9!7)mae{+lK$8+j( zhqT$S?!1v~dBn*Zv)iSo5fb(yWZbww!Uf?IC-`MWwBo=DUGbn>=7AmM^!EHd=7i9k z8d|Z2g?{ysg^RMX&DK|N*5rH}22}W_B`xWvW9#F>WS`cr{FKkxn(u0LO$xB>+TgOI zBw~fU5NDD#c?*i^q|HSL-vxE1(vUDJLNF+=zjXL#0lLOGt($^5N6V0NUXNUq3oeh) zDexziV9{hB?aId7ye4B>TshyXH?O(#*ia>B+5yF|28)Bdq$esOSYY1qNoH3WqOQ0| zj{nCk>t&i6xQzka0`Tvb60`jG*X%b$xFg^ZgN>EH`& z^qk;0#-cCn?CEp>qJ258Xa1j-NtD4Zc_R`l* zuP(R-ae}ChTmCfV_%Y}xT`O?=IpwvkBD=WG^q-XqUJ8pn7)%$Zabo)Ot}l;)7%4A< zm><0sczZ225jhm;|4unI&9`H=#YuBU)q-@6`(N>ui)^t?3EmzR<%0{qe9UtLNWINc zsa<|@^|ED<9t)st_RWB5zXO)WSmlIxvV^UCBYUyGpEhDkMV+G@#`iLHwNz^rw9w~z zv*>(QL=kK$PlJ|6OG8CxkrpM@*&~)x<6}>1*Z|>uFTEnT4NLg`%4c2nK0g+55!Qix z7x1{LA=<(841f8>Y4tE}LXSEb{-tu&o$Hid$Eqw{5pk(dIIQHa0xj-7i3@DoJm-1O zgptPr&nNymsJ6PfhmpLi{NI@`b`WjL>-6&)OWP&_Ghp0n_zm~R2UakSbD|Hsrppo^ zRSINiQ`5baGi?%+JnK7*3|9<#%?>|>gf%YtxU|(sOVl$ddt#htmO+H)zz8Cj@oa81 zY$;9SON~66L4#zfc><&2bl5fZS&7e>u1iXc&LB<{?1UK?S@eMzm;Nry{1?s>8k_71{5X359$%Ng+fsU1IDN z9-Bl+7Ip3>B;P9n7q}s9FUAV`Lt8MkOjP@HA9H+RSzRb9_>r4%{~)rp-acEF9bn7r zxiT6h&bLOTbRgKg4agqnzr?SY#oYR(jRT$W}+i<7$J<1uh7bc9K{!XF(NeoTf(A zT*`XE)l8O*J|+q|7}`CQ$8%-cDuesv_Pr8xnZ;`G0mEP)psEhTfAqiDaAgzFz^_H3?rsWS`4D=7YB zOsAAvh{6RQt6~#`SA6q}yvKW~YJt&To*q-aSJ`vVPiyTw^;fYC{gn;`EZ8qL(pT>v zu8DZ;2}08ZeqNV2Tuf@}eMNUy&3MwttXHUzY72rF5ev-*a%6#KEBja3gpjdxBaJMY za2=C5Ru%m#9>o9>!s{^&j37G3BcO1w>xBC_^Y0C)apf{dLH{Ea0(HHrOMn_(lK1zI zy7jI>Vyvl=b003B5(%u>R^KiwyAD9Av%SpEza7`#Dc+Ud^vy;TlX!kM#D6z^!&ZEl z6nV92^%THr{auU}{l^_l{Q@u^TBIMMbFydMZ{bE?KjisS5oFDMH`R{t%gZtre%?gNqMM`onh#H1008VusouKe(Tlz% zu`c;q35x>V@!P(A*bl8I&Rw?9VJzQ&sVv_Cpw+&V?ek~*>F@qEGle%lYp zv9i1~=JxkvXIJ-vG5Vz>JnK{@qI~AXxLDZNL?x#ay94m=_8%6XGV^}S4f%?v%v zun$dawKFA_BAXDiLYr=po9%7~^l*vDM-FV?sh>^1AGnIYdPuc?zhpKC+_Oh%3gpjqq#UwddZ-_P1-ca(|lE^A?0qcsucq8bcP*Ir!f0%tb^>J|=C zzzxhO2TK9y+GLe>NoAQctXREjk6sLe)yI^<`%NiCg_-4mI0QMM`ZfwvO%C|*DyiqkIqp3+?`FKB+brU) zjQTb@r`pZE3HcZN&3>InyZFtT@{3yL-kZpE8jFuUEBVz*ZKmC_8mBk|2%1m8!D?w6g(ak96REw|7HGM8Lx-#PMKXOISwzdTDJh|m=a7ag}WLDD( zSr>-AfipImueHK0)OK`JHSJU|)qvF*%Gleq>mQxIxfVM`6{IJPluKlm^*`Fch&{l# zx05_86TguC?T9OQW~TKyefuf%m%HIJjQi6KQ}XCvBl5Yw(Y7ql`0MxSVRCTa;a~HA H@r?UlrLZ$8 literal 0 HcmV?d00001 From 08786791ec3e1bac0a1a1659a5d4dd4096e6b9b3 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sat, 15 Jun 2019 22:59:50 -0700 Subject: [PATCH 17/56] More changes to descriptions --- docs/1. Create BackEnd API project.md | 15 +++++++++------ docs/4. Add auth features.md | 16 +++++++++++----- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/docs/1. Create BackEnd API project.md b/docs/1. Create BackEnd API project.md index ded989a2..a67febbd 100644 --- a/docs/1. Create BackEnd API project.md +++ b/docs/1. Create BackEnd API project.md @@ -1,15 +1,18 @@ -## Creating a basic EF model - +## Creating a new project using Visual Studio 1. Create and add a new project named `BackEnd` and name the solution `ConferencePlanner` using File / New / ASP.NET Core Web Application. Select the Web API template, No Auth, no Docker support. ![](images/vs2019-new-project.png "Creating a new solution in Visual Studio") ![](images/vs2019-name-backend-project.png "Adding a project to the solution") ![](images/vs2019-new-web-api.png "Web API Project settings") - > ***Note:* If not using Visual Studio, create the project using `dotnet new webapi` at the cmd line, details as follows:** - > 1. Create folder ConferencePlanner and call `dotnet new sln` at the cmd line to create a solution - > 2. Create sub-folder BackEnd and create a project using `dotnet new webapi` at the cmd line inside the folder BackEnd - > 3. Add the project to the solution using `dotnet sln add BackEnd\BackEnd.csproj` +## Creating a new project using the Command Line + +1. Create folder ConferencePlanner and call `dotnet new sln` at the cmd line to create a solution +1. Create sub-folder BackEnd and create a project using `dotnet new webapi` at the cmd line inside the folder BackEnd +1. Add the project to the solution using `dotnet sln add BackEnd\BackEnd.csproj` + +## Creating a basic EF model + 1. Add a new `Models` folder to the root of the application. 1. Add a new `Speaker` class using the following code: ```csharp diff --git a/docs/4. Add auth features.md b/docs/4. Add auth features.md index e7d95240..aeeada4f 100644 --- a/docs/4. Add auth features.md +++ b/docs/4. Add auth features.md @@ -12,15 +12,15 @@ In this module we're going to add the capability for users to register and sign- 1. In the same dialog, click the '+' button to add a user class. Call it `FrontEnd.Data.User`. 1. Click the "Add" button -### Adding Identity via the Command Line +### Adding Identity using the Command Line 1. Open a command line to the **FrontEnd** project folder 1. If you haven't done this already, install the command-line scaffolding tool. ``` dotnet tool install -g dotnet-aspnet-codegenerator ``` -1. Add the Microsoft.VisualStudio.Web.CodeGeneration.Design package to the project. +1. Add the `Microsoft.VisualStudio.Web.CodeGeneration.Design` version `3.0.0-preview5-19264-04` package to the project. ``` - dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design --version 2.2.0 + dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design --version 3.0.0-preview5-19264-04 ``` 1. Run this command to generate the code to use Identity. ``` @@ -77,7 +77,7 @@ In this module we're going to add the capability for users to register and sign- ### Add the authentication middleware > We need to ensure that the request pipeline contains the Authentication middleware before any other middleware that represents resources we want to potentially authorize, e.g. Razor Pages 1. Open the `Startup.cs` file -1. In the `Configure` method, add a call to add the Authentication middleware before the call that adds MVC: +1. In the `Configure` method, add a call to add the Authentication middleware before the Authorization middleware: ``` c# public void Configure(IApplicationBuilder app, IHostingEnvironment env) { @@ -94,9 +94,15 @@ In this module we're going to add the capability for users to register and sign- app.UseHttpsRedirection(); app.UseStaticFiles(); + app.UseRouting(); + app.UseAuthentication(); + app.UseAuthorization(); - app.UseMvc(); + app.UseEndpoints(endpoints => + { + endpoints.MapRazorPages(); + }); } ``` From 66188152972c27d17c4969618d54b0feaf902a1d Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sun, 16 Jun 2019 00:41:34 -0700 Subject: [PATCH 18/56] Streamline project creation from the command line --- docs/1. Create BackEnd API project.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/1. Create BackEnd API project.md b/docs/1. Create BackEnd API project.md index a67febbd..3d8a76c1 100644 --- a/docs/1. Create BackEnd API project.md +++ b/docs/1. Create BackEnd API project.md @@ -8,8 +8,8 @@ ## Creating a new project using the Command Line 1. Create folder ConferencePlanner and call `dotnet new sln` at the cmd line to create a solution -1. Create sub-folder BackEnd and create a project using `dotnet new webapi` at the cmd line inside the folder BackEnd -1. Add the project to the solution using `dotnet sln add BackEnd\BackEnd.csproj` +1. Create a project using `dotnet new webapi -n BackEnd` at the cmd line inside the folder BackEnd +1. Add the project to the solution using `dotnet sln add BackEnd` ## Creating a basic EF model From 841770959d78d4707118624313bb326ca87c7472 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sun, 16 Jun 2019 00:49:56 -0700 Subject: [PATCH 19/56] Fixe dotnet ef global tool instructions --- docs/1. Create BackEnd API project.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/1. Create BackEnd API project.md b/docs/1. Create BackEnd API project.md index 3d8a76c1..68be3ee0 100644 --- a/docs/1. Create BackEnd API project.md +++ b/docs/1. Create BackEnd API project.md @@ -104,8 +104,7 @@ ### Visual Studio: Package Manager Console -1. Add a reference to the NuGet package `Microsoft.EntityFrameworkCore.Tools`. Note that you'll need to resolve several references by adding missing `using` statements (`Ctrl + .` is your friend). - > **If you're not using Visual Studio** install the package from the command line with `dotnet add package Microsoft.EntityFrameworkCore.Tools --version 3.0.0-preview6.19304.10` +1. Add a reference to the NuGet package `Microsoft.EntityFrameworkCore.Tools` version `3.0.0-preview6.19304.10`. 1. In Visual Studio, select the Tools -> NuGet Package Manager -> Package Manager Console @@ -117,7 +116,10 @@ ### Command line -1. TODO: Install the global tool +1. Install the EntityFramework global tool `dotnet-ef` using the following command: + ``` + dotnet tool install -g dotnet-ef --version 3.0.0-preview6.19304.10 + ``` 1. Open a command prompt and navigate to the project directory. (The directory containing the `Startup.cs` file). From 26d119578a862bb2a36c24537514b88c6c75d2b6 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sun, 16 Jun 2019 00:51:34 -0700 Subject: [PATCH 20/56] Add conosle coloring --- docs/1. Create BackEnd API project.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/1. Create BackEnd API project.md b/docs/1. Create BackEnd API project.md index 68be3ee0..073755b8 100644 --- a/docs/1. Create BackEnd API project.md +++ b/docs/1. Create BackEnd API project.md @@ -117,7 +117,7 @@ ### Command line 1. Install the EntityFramework global tool `dotnet-ef` using the following command: - ``` + ```console dotnet tool install -g dotnet-ef --version 3.0.0-preview6.19304.10 ``` From d31a7639c73854e86eeebafb17a21f9d28aabe26 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sun, 16 Jun 2019 01:17:06 -0700 Subject: [PATCH 21/56] Half updated section 4 --- docs/4. Add auth features.md | 92 ++++++++++-------------------------- 1 file changed, 24 insertions(+), 68 deletions(-) diff --git a/docs/4. Add auth features.md b/docs/4. Add auth features.md index aeeada4f..37a00daf 100644 --- a/docs/4. Add auth features.md +++ b/docs/4. Add auth features.md @@ -107,39 +107,40 @@ In this module we're going to add the capability for users to register and sign- ``` ### Allow creation of an admin user -> Let's make it so the site allows creation of an admin user when there isn't one already, but only if the user also has a special single-use creation key. That way, we can easily create an admin user without access to the database when we first run the app in any environment. +> Let's make it so the site allows creation of an admin user when there isn't one already. The first user to access the site will be deemed the administrator. 1. Create a new class `AdminService` in the `Services` folder. This class will be responsible for managing the creation key generation and tracking whether the site should allow creating admin users. 1. Add code to the class that will create an appropriately long creation key and expose it via a property: ``` c# - private readonly Lazy _creationKey = new Lazy(() => BitConverter.ToInt64(Guid.NewGuid().ToByteArray(), 7)); - private readonly IdentityDbContext _dbContext; - private bool _adminExists; - - public AdminService(IdentityDbContext dbContext) + public class AdminService { - _dbContext = dbContext; - } + private readonly IdentityDbContext _dbContext; - public long CreationKey => _creationKey.Value; + private bool _adminExists; - public async Task AllowAdminUserCreationAsync() - { - if (_adminExists) + public AdminService(IdentityDbContext dbContext) { - return false; + _dbContext = dbContext; } - else + + public async Task AllowAdminUserCreationAsync() { - if (await _dbContext.Users.AnyAsync(user => user.IsAdmin)) + if (_adminExists) { - // There are already admin users so disable admin creation - _adminExists = true; return false; } + else + { + if (await _dbContext.Users.AnyAsync(user => user.IsAdmin)) + { + // There are already admin users so disable admin creation + _adminExists = true; + return false; + } - // There are no admin users so enable admin creation - return true; + // There are no admin users so enable admin creation + return true; + } } } ``` @@ -147,8 +148,6 @@ In this module we're going to add the capability for users to register and sign- ``` c# public interface IAdminService { - long CreationKey { get; } - Task AllowAdminUserCreationAsync(); } ``` @@ -164,7 +163,7 @@ In this module we're going to add the capability for users to register and sign- ``` dotnet aspnet-codegenerator identity --dbContext FrontEnd.Data.IdentityDbContext --files Account.Register ``` -1. Update the `RegisterModel` class in the `Register.cshtml.cs` file to accept `IAdminService` and `IdentityDbContext` parameters and save them to local members: +1. Update the `RegisterModel` class in the `Register.cshtml.cs` file to accept `IAdminService` as a parameter and it them to a local member: ``` c# [AllowAnonymous] public class RegisterModel : PageModel @@ -174,52 +173,30 @@ In this module we're going to add the capability for users to register and sign- private readonly ILogger _logger; private readonly IEmailSender _emailSender; private readonly IAdminService _adminService; - private readonly IdentityDbContext _dbContext; public RegisterModel( UserManager userManager, SignInManager signInManager, ILogger logger, IEmailSender emailSender, - IAdminService adminService, - IdentityDbContext dbContext) + IAdminService adminService) { _userManager = userManager; _signInManager = signInManager; _logger = logger; _emailSender = emailSender; _adminService = adminService; - _dbContext = dbContext; } ... ``` -1. Add a `bool` property to the page model to indicate to the page whether admin creation is currently allowed: - ``` c# - public bool AllowAdminCreation { get; set; } - ``` -1. Add an `AdminCreationKey` property to to the page's `InputModel` class to capture the submitted key for creating the admin user: - ``` c# - [DataType(DataType.Password)] - [Display(Name = "Admin creation key")] - public long? AdminCreationKey { get; set; } - ``` -1. Add code to the `OnGet` method to use the `IAdminService` to see if admin creation is enabled and log the creation key if so. You'll also need to change the method to be async by updating the method signature to the following: `public async Task OnGetAsync(string returnUrl = null)` + +1. Add code to the `OnPostAsync` that marks the new user as an admin if the `IAdminService.AllowAdminUserCreationAsync` returns true before creating the user: ``` c# if (await _adminService.AllowAdminUserCreationAsync()) - { - AllowAdminCreation = true; - _logger.LogInformation("Admin creation is enabled. Use the following key to create an admin user: {adminKey}", _adminService.CreationKey); - } - ``` -1. Add code to the `OnPostAsync` that marks the new user as an admin if the admin creation key was submitted and matches the in the `IAdminService`, before creating the user: - ``` c# - if (await _adminService.AllowAdminUserCreationAsync() && Input.AdminCreationKey == _adminService.CreationKey) { // Set as admin user user.IsAdmin = true; - // In the event user creation fails in the next few lines, set this so the admin key box still shows up on the retry page - AllowAdminCreation = true; } var result = await _userManager.CreateAsync(user, Input.Password); @@ -235,26 +212,6 @@ In this module we're going to add the capability for users to register and sign- _logger.LogInformation("User created a new account with password."); } ``` -1. Update the registration form to allow entering the admin creation key by adding a text input to the end of `Register.cshtml`: - ``` html - ... -
    - - - -
    - @if (Model.AllowAdminCreation) - { -
    - - - -
    - } - - - ... - ``` > If you run the app at this point, you'll see an exception stating that you can't inject a scoped type into a type registered as a singleton. This is the DI system protecting you from a common anti-pattern that can arise when using IoC containers. Let's fix the `AdminService` to use the scoped `IdentityDbContext` correctly. @@ -262,7 +219,6 @@ In this module we're going to add the capability for users to register and sign- ``` csharp public class AdminService : IAdminService { - private readonly Lazy _creationKey = new Lazy(() => BitConverter.ToInt64(Guid.NewGuid().ToByteArray(), 7)); private readonly IServiceProvider _serviceProvider; private bool _adminExists; From 23c106c0982e0f2d311f72a9eba24e9419a36038 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sun, 16 Jun 2019 02:40:02 -0700 Subject: [PATCH 22/56] Updated auth features --- docs/4. Add auth features.md | 140 ++++++++++++++++------------------- 1 file changed, 65 insertions(+), 75 deletions(-) diff --git a/docs/4. Add auth features.md b/docs/4. Add auth features.md index 37a00daf..b87c5561 100644 --- a/docs/4. Add auth features.md +++ b/docs/4. Add auth features.md @@ -289,21 +289,6 @@ In this module we're going to add the capability for users to register and sign- } } ``` -1. Register the custom `UserClaimsPrincipalFactory` in the `IdentityHostingStartup` class. You can also take this opportunity to tweak the default password policy to be less or more strict if you wish: - ``` c# - services.AddDefaultIdentity(options => - { - options.Password.RequireDigit = false; - options.Password.RequiredLength = 1; - options.Password.RequiredUniqueChars = 0; - options.Password.RequireLowercase = false; - options.Password.RequireUppercase = false; - options.Password.RequireNonAlphanumeric = false; - }) - .AddDefaultUI(UIFramework.Bootstrap4) - .AddEntityFrameworkStores() - .AddClaimsPrincipalFactory(); - ``` 1. Add a new class file `AuthHelpers.cs` in the `Infrastructure` folder and add the following helper methods for reading and setting the admin claim: ``` c# namespace FrontEnd.Infrastructure @@ -340,6 +325,14 @@ In this module we're going to add the capability for users to register and sign- } } ``` + +1. Register the custom `UserClaimsPrincipalFactory` in the `IdentityHostingStartup` class: + ``` c# + services.AddDefaultIdentity() + .AddDefaultUI(UIFramework.Bootstrap4) + .AddEntityFrameworkStores() + .AddClaimsPrincipalFactory(); + ``` 1. Add authorization services with an admin policy to the `ConfigureServices()` method of `Startup.cs` that uses the just-added helper methods to require the admin claim: ```csharp @@ -352,7 +345,7 @@ In this module we're going to add the capability for users to register and sign- }); }); ``` -1. Add `Microsoft.AspNetCore.Authorization` to the list of usings in `Index.cshtml.cs`, then use the helper method in the page model to determine if the current user is an administrator. +1. Add `System.Security.Claims` to the list of usings in `Index.cshtml.cs`, then use the helper method in the page model to determine if the current user is an administrator. ```csharp public bool IsAdmin { get; set; } @@ -378,21 +371,20 @@ In this module we're going to add the capability for users to register and sign- @if (Model.IsAdmin) {
    } ``` 1. Add a nested `Admin` folder to the `Pages` folder then add an `EditSession.cshtml` razor page and `EditSession.cshtml.cs` page model to it. -1. Next, we'll protect pages in the `Admin` folder with an Admin policy by making the following change to the `services.AddMvc()` call in `Startup.ConfigureServices`: +1. Next, we'll protect pages in the `Admin` folder with an Admin policy by making the following change to the `services.AddRazorPages()` call in `Startup.ConfigureServices`: ```csharp - services.AddMvc() - .AddRazorPagesOptions(options => - { - options.Conventions.AuthorizeFolder("/Admin", "Admin"); - }) + services.AddRazorPages(options => + { + options.Conventions.AuthorizeFolder("/Admin", "Admin"); + }); ``` ## Add a form for editing a session @@ -415,8 +407,7 @@ In this module we're going to add the capability for users to register and sign- var session = await _apiClient.GetSessionAsync(id); Session = new Session { - ID = session.ID, - ConferenceID = session.ConferenceID, + Id = session.Id, TrackId = session.TrackId, Title = session.Title, Abstract = session.Abstract, @@ -430,59 +421,58 @@ In this module we're going to add the capability for users to register and sign- 1. Add the "{id}" route to the `EditSession.cshtml` form: ```html - @page "{id:int}" + @page "{id}" @model EditSessionModel ``` 1. Add the following edit form to `EditSession.cshtml`: ```html -

    Edit Session

    - -
    -
    - - - -
    - -
    - - -
    -
    -
    - -
    - - -
    -
    -
    - -
    - - -
    -
    -
    - -
    - - -
    -
    -
    -
    - - -
    -
    -
    - - @section Scripts { +

    Edit Session

    + +
    +
    + + +
    + +
    + + +
    +
    +
    + +
    + + +
    +
    +
    + +
    + + +
    +
    +
    + +
    + + +
    +
    +
    +
    + + +
    +
    +
    + + @section Scripts { - } + } ``` 1. Add code to handle the `Save` and `Delete` button actions in `EditSession.cshtml.cs`: @@ -624,7 +614,7 @@ We're currently using `if` blocks to determine whether to show parts of the UI b public bool RequiresAuthentication { get; set; } [HtmlAttributeName("authz-policy")] - public string RequiredPolicy { get; set; } + public string RequiredPolicy { get; set; } ``` 1. Add a `ViewContext` property: ```csharp @@ -672,7 +662,7 @@ We're currently using `if` blocks to determine whether to show parts of the UI b { output.SuppressOutput(); } - } + } ``` 1. Register the new Tag Helper in the `_ViewImports.cshtml` file: ```html @@ -687,11 +677,11 @@ We're currently using `if` blocks to determine whether to show parts of the UI b @foreach (var speaker in session.Speakers) {
  1. - @speaker.Name + @speaker.Name
  2. }
  3. - Edit + Edit
  4. From 5c2c238db1548c465e711bf6ff827437f999868d Mon Sep 17 00:00:00 2001 From: DamianEdwards Date: Sun, 16 Jun 2019 12:31:54 +0200 Subject: [PATCH 23/56] Make the MyAgenda page work again --- src/FrontEnd/Pages/Index.cshtml | 6 ++- src/FrontEnd/Pages/Index.cshtml.cs | 27 ++++++---- src/FrontEnd/Pages/MyAgenda.cshtml | 69 +++++++++++------------- src/FrontEnd/Pages/MyAgenda.cshtml.cs | 6 +-- src/FrontEnd/Pages/Shared/_Layout.cshtml | 3 -- 5 files changed, 54 insertions(+), 57 deletions(-) diff --git a/src/FrontEnd/Pages/Index.cshtml b/src/FrontEnd/Pages/Index.cshtml index e5bae0ea..f5c54ab6 100644 --- a/src/FrontEnd/Pages/Index.cshtml +++ b/src/FrontEnd/Pages/Index.cshtml @@ -30,6 +30,9 @@
    @foreach (var session in timeSlot) { + var inUserAgenda = Model.UserSessions?.Contains(session.Id) ?? false; + if (inUserAgenda || Model.ShowSessionsNotInAgenda()) + {
    @session.Track?.Name
    @@ -49,7 +52,7 @@

    Edit - @if (Model.UserSessions?.Contains(session.Id) ?? false) + @if (inUserAgenda) {

    + } } } diff --git a/src/FrontEnd/Pages/Index.cshtml.cs b/src/FrontEnd/Pages/Index.cshtml.cs index 1d6b7114..42e9f727 100644 --- a/src/FrontEnd/Pages/Index.cshtml.cs +++ b/src/FrontEnd/Pages/Index.cshtml.cs @@ -61,7 +61,9 @@ public async Task OnPostRemoveAsync(int sessionId, int day = 0) return RedirectToPage(new { day }); } - protected virtual Task GetConferenceDataAsync() + public virtual bool ShowSessionsNotInAgenda() => true; + + protected Task GetConferenceDataAsync() { return _cache.GetOrCreateAsync(CacheKeys.ConferenceData, async entry => { @@ -72,26 +74,27 @@ protected virtual Task GetConferenceDataAsync() var numberOfDays = ((endDate - startDate)?.Days + 1) ?? 0; - var dict = new ConferenceData(numberOfDays); + var confData = new ConferenceData(numberOfDays); for (int i = 0; i < numberOfDays; i++) { var filterDate = startDate?.AddDays(i); - dict[i] = sessions.Where(s => s.StartTime?.Date == filterDate) - .OrderBy(s => s.TrackId) - .GroupBy(s => s.StartTime) - .OrderBy(g => g.Key); + confData[i] = sessions.Where(s => s.StartTime?.Date == filterDate) + .OrderBy(s => s.TrackId) + .GroupBy(s => s.StartTime) + .OrderBy(g => g.Key); } entry.SetSlidingExpiration(TimeSpan.FromHours(1)); - dict.StartDate = startDate; - dict.EndDate = endDate; - dict.DayOffsets = Enumerable.Range(0, numberOfDays) - .Select(offset => (offset, (startDate?.AddDays(offset))?.DayOfWeek)); + confData.StartDate = startDate; + confData.EndDate = endDate; + confData.DayOffsets = Enumerable.Range(0, numberOfDays) + .Select(offset => + (offset, (startDate?.AddDays(offset))?.DayOfWeek)); - return dict; + return confData; }); } @@ -102,7 +105,9 @@ public ConferenceData(int capacity) : base(capacity) } public DateTimeOffset? StartDate { get; set; } + public DateTimeOffset? EndDate { get; set; } + public IEnumerable<(int Offset, DayOfWeek? DayofWeek)> DayOffsets { get; set; } } } diff --git a/src/FrontEnd/Pages/MyAgenda.cshtml b/src/FrontEnd/Pages/MyAgenda.cshtml index eadeacff..4667db12 100644 --- a/src/FrontEnd/Pages/MyAgenda.cshtml +++ b/src/FrontEnd/Pages/MyAgenda.cshtml @@ -25,57 +25,52 @@ } - @*@foreach (var timeSlot in Model.Sessions) + @foreach (var timeSlot in Model.ConferenceModel[Model.CurrentDayOffset]) {

    @timeSlot.Key?.ToString("HH:mm")

    @foreach (var session in timeSlot) { -
    -
    -
    @session.Track?.Name
    - - + } }
    - }*@ + }
    \ No newline at end of file diff --git a/src/FrontEnd/Pages/MyAgenda.cshtml.cs b/src/FrontEnd/Pages/MyAgenda.cshtml.cs index 59ccf9c0..bee77d30 100644 --- a/src/FrontEnd/Pages/MyAgenda.cshtml.cs +++ b/src/FrontEnd/Pages/MyAgenda.cshtml.cs @@ -18,10 +18,6 @@ public MyAgendaModel(IApiClient client, IMemoryCache cache) } - protected override Task GetConferenceDataAsync() - { - throw new Exception("later asshole"); - //return _apiClient.GetSessionsByAttendeeAsync(User.Identity.Name); - } + public override bool ShowSessionsNotInAgenda() => false; } } \ No newline at end of file diff --git a/src/FrontEnd/Pages/Shared/_Layout.cshtml b/src/FrontEnd/Pages/Shared/_Layout.cshtml index 3074cc3e..20ac3173 100644 --- a/src/FrontEnd/Pages/Shared/_Layout.cshtml +++ b/src/FrontEnd/Pages/Shared/_Layout.cshtml @@ -33,9 +33,6 @@ - From af6b9c0014dd2d86777168cbe68d2304605da9c1 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sun, 16 Jun 2019 05:40:11 -0700 Subject: [PATCH 24/56] Updated session5 --- docs/5. Add personal agenda.md | 153 ++++++++++++++++----------------- 1 file changed, 76 insertions(+), 77 deletions(-) diff --git a/docs/5. Add personal agenda.md b/docs/5. Add personal agenda.md index 4058de9f..0f2aa76e 100644 --- a/docs/5. Add personal agenda.md +++ b/docs/5. Add personal agenda.md @@ -140,133 +140,132 @@ In this section we'll add features that track attendees who have registered on t [DataType(DataType.EmailAddress)] public override string EmailAddress { get => base.EmailAddress; set => base.EmailAddress = value; } } - } + } ``` 1. In `Welcome.cshtml.cs`, add logic that associates the logged in user with an attendee: ```csharp - using System.Threading.Tasks; - using FrontEnd.Services; - using FrontEnd.Pages.Models; - using Microsoft.AspNetCore.Mvc; - using Microsoft.AspNetCore.Mvc.RazorPages; - using System.Security.Claims; - using Microsoft.AspNetCore.Authentication; - using Microsoft.AspNetCore.Identity; - - namespace FrontEnd + using System.Threading.Tasks; + using FrontEnd.Services; + using FrontEnd.Pages.Models; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.RazorPages; + using System.Security.Claims; + using Microsoft.AspNetCore.Authentication; + using Microsoft.AspNetCore.Identity; + + namespace FrontEnd + { + public class WelcomeModel : PageModel { - public class WelcomeModel : PageModel + private readonly IApiClient _apiClient; + + public WelcomeModel(IApiClient apiClient) { - private readonly IApiClient _apiClient; + _apiClient = apiClient; + } - public WelcomeModel(IApiClient apiClient) - { - _apiClient = apiClient; - } + [BindProperty] + public Attendee Attendee { get; set; } - [BindProperty] - public Attendee Attendee { get; set; } + public IActionResult OnGet() + { + // Redirect to home page if user is anonymous or already registered as attendee + var isAttendee = User.IsAttendee(); - public IActionResult OnGet() + if (!User.Identity.IsAuthenticated || isAttendee) { - // Redirect to home page if user is anonymous or already registered as attendee - var isAttendee = User.IsAttendee(); + return RedirectToPage("/Index"); + } - if (!User.Identity.IsAuthenticated || isAttendee) - { - return RedirectToPage("/Index"); - } + return Page(); + } - return Page(); - } + public async Task OnPostAsync() + { + var success = await _apiClient.AddAttendeeAsync(Attendee); - public async Task OnPostAsync() + if (!success) { - var success = await _apiClient.AddAttendeeAsync(Attendee); - - if (!success) - { - ModelState.AddModelError("", "There was an issue creating the attendee for this user."); - return Page(); - } + ModelState.AddModelError("", "There was an issue creating the attendee for this user."); + return Page(); + } - // Re-issue the auth cookie with the new IsAttendee claim - User.MakeAttendee(); - await HttpContext.SignInAsync(IdentityConstants.ApplicationScheme, User); + // Re-issue the auth cookie with the new IsAttendee claim + User.MakeAttendee(); + await HttpContext.SignInAsync(IdentityConstants.ApplicationScheme, User); - return RedirectToPage("/Index"); - } + return RedirectToPage("/Index"); } } + } ``` 1. Logged in users can now be associated with an attendee by visiting this page. -## Add a filter to force logged in users to sign up on welcome page -1. Add a folder called `Filters`. +## Add a middleware to force logged in users to sign up on welcome page +1. Add a folder called `Middleware`. 1. Add a new attribute `SkipWelcomeAttribute.cs` to allow certain pages or action methods to be skipped from enforcing redirection to the Welcome page: ```csharp using System; - using Microsoft.AspNetCore.Mvc.Filters; - namespace FrontEnd.Filters + namespace FrontEnd { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] - public class SkipWelcomeAttribute : Attribute, IFilterMetadata + public class SkipWelcomeAttribute : Attribute { } } ``` -1. Add a new class called `RequireLoginFilter.cs` that redirects to the Welcome page if the user is authenticated but not associated with an attendee (does not have the `"IsAttendee"` claim): +1. Add a new class called `RequireLoginMiddleware.cs` that redirects to the Welcome page if the user is authenticated but not associated with an attendee (does not have the `"IsAttendee"` claim): ```csharp - public class RequireLoginFilter : IAsyncResourceFilter + public class RequireLoginMiddleware { - private readonly IUrlHelperFactory _urlHelperFactory; + private readonly RequestDelegate _next; + private readonly LinkGenerator _linkGenerator; - public RequireLoginFilter(IUrlHelperFactory urlHelperFactory) + public RequireLoginMiddleware(RequestDelegate next, LinkGenerator linkGenerator) { - _urlHelperFactory = urlHelperFactory; + _next = next; + _linkGenerator = linkGenerator; } - public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) + public Task Invoke(HttpContext context) { - var urlHelper = _urlHelperFactory.GetUrlHelper(context); + var endpoint = context.GetEndpoint(); // If the user is authenticated but not a known attendee *and* we've not marked this page // to skip attendee welcome, then redirect to the Welcome page - if (context.HttpContext.User.Identity.IsAuthenticated && - !context.Filters.OfType().Any()) + if (context.User.Identity.IsAuthenticated && + endpoint?.Metadata.GetMetadata() == null) { - var isAttendee = context.HttpContext.User.IsAttendee(); + var isAttendee = context.User.IsAttendee(); if (!isAttendee) { + var url = _linkGenerator.GetUriByPage(context, page: "/Welcome"); // No attendee registerd for this user - context.HttpContext.Response.Redirect(urlHelper.Page("/Welcome")); + context.Response.Redirect(url); - return; + return Task.CompletedTask; } } - await next(); + return _next(context); } } ``` -1. Register the `RequireLogin` filter globally with MVC using its options in the `ConfigureServices` method in `Startup.cs`: +1. Add the `RequireLoginMiddleware` in `Configure` method in `Startup.cs` before `UseEndpoints()`: ```csharp - services.AddMvc(options => + app.UseMiddleware(); + + app.UseEndpoints(endpoints => { - options.Filters.AddService(); - }) + endpoints.MapRazorPages(); + }); ``` -1. Register the filter in DI in the `ConfigureServices` method in `Startup.cs` - - ```csharp - services.AddTransient(); - ``` 1. Update the `Welcome.cshtml.cs` class with the attribute to ensure it is skipped when the global filter runs: ```csharp @@ -345,9 +344,9 @@ dotnet aspnet-codegenerator identity --dbContext FrontEnd.Data.IdentityDbContext return new List(); } - var sessionIds = attendee.Sessions.Select(s => s.ID); + var sessionIds = attendee.Sessions.Select(s => s.Id); - sessions.RemoveAll(s => !sessionIds.Contains(s.ID)); + sessions.RemoveAll(s => !sessionIds.Contains(s.Id)); return sessions; } @@ -364,15 +363,15 @@ dotnet aspnet-codegenerator identity --dbContext FrontEnd.Data.IdentityDbContext ```csharp var sessions = await _apiClient.GetSessionsByAttendeeAsync(User.Identity.Name); - IsInPersonalAgenda = sessions.Any(s => s.ID == id); + IsInPersonalAgenda = sessions.Any(s => s.Id == id); ``` 1. Add a form to the bottom of `Session.cshtml` razor page that adds the ability to add/remove the session to the attendee's personal agenda: ```html
    - +

    - Edit + Edit @if (Model.IsInPersonalAgenda) { - @Model.Message -

    -} - -
    -

    My Conference @System.DateTime.Now.Year

    + - +

    My Conference @System.DateTime.Now.Year

    - @foreach (var timeSlot in Model.ConferenceModel[Model.CurrentDayOffset]) - { -

    @timeSlot.Key?.ToString("HH:mm")

    -
    - @foreach (var session in timeSlot) - { - var inUserAgenda = Model.UserSessions?.Contains(session.Id) ?? false; - if (inUserAgenda || Model.ShowSessionsNotInAgenda()) - { -
    -
    -
    @session.Track?.Name
    - - -
    -
    - } - } -
    - } -
    + diff --git a/src/FrontEnd/Pages/Index.cshtml.cs b/src/FrontEnd/Pages/Index.cshtml.cs index 42e9f727..3981aaa9 100644 --- a/src/FrontEnd/Pages/Index.cshtml.cs +++ b/src/FrontEnd/Pages/Index.cshtml.cs @@ -24,7 +24,7 @@ public IndexModel(IApiClient apiClient, IMemoryCache cache) public ConferenceData ConferenceModel { get; private set; } - public List UserSessions { get; set; } + public List UserSessions { get; set; } public int CurrentDayOffset { get; set; } @@ -39,9 +39,7 @@ public async Task OnGetAsync(int day = 0) if (User.Identity.IsAuthenticated) { - var userSessions = await _apiClient.GetSessionsByAttendeeAsync(User.Identity.Name); - - UserSessions = userSessions.Select(u => u.Id).ToList(); + UserSessions = await _apiClient.GetSessionsByAttendeeAsync(User.Identity.Name); } ConferenceModel = await GetConferenceDataAsync(); @@ -61,41 +59,43 @@ public async Task OnPostRemoveAsync(int sessionId, int day = 0) return RedirectToPage(new { day }); } - public virtual bool ShowSessionsNotInAgenda() => true; - - protected Task GetConferenceDataAsync() + protected virtual Task GetConferenceDataAsync() { return _cache.GetOrCreateAsync(CacheKeys.ConferenceData, async entry => { - var sessions = await _apiClient.GetSessionsAsync(); + entry.SetSlidingExpiration(TimeSpan.FromHours(1)); - var startDate = sessions.Min(s => s.StartTime?.Date); - var endDate = sessions.Max(s => s.EndTime?.Date); + var sessions = await _apiClient.GetSessionsAsync(); + return GenerateConferenceData(sessions); + }); + } - var numberOfDays = ((endDate - startDate)?.Days + 1) ?? 0; + protected static ConferenceData GenerateConferenceData(List sessions) + { + var startDate = sessions.Min(s => s.StartTime?.Date); + var endDate = sessions.Max(s => s.EndTime?.Date); - var confData = new ConferenceData(numberOfDays); + var numberOfDays = ((endDate - startDate)?.Days + 1) ?? 0; - for (int i = 0; i < numberOfDays; i++) - { - var filterDate = startDate?.AddDays(i); + var confData = new ConferenceData(numberOfDays); - confData[i] = sessions.Where(s => s.StartTime?.Date == filterDate) - .OrderBy(s => s.TrackId) - .GroupBy(s => s.StartTime) - .OrderBy(g => g.Key); - } + for (int i = 0; i < numberOfDays; i++) + { + var filterDate = startDate?.AddDays(i); - entry.SetSlidingExpiration(TimeSpan.FromHours(1)); + confData[i] = sessions.Where(s => s.StartTime?.Date == filterDate) + .OrderBy(s => s.TrackId) + .GroupBy(s => s.StartTime) + .OrderBy(g => g.Key); + } - confData.StartDate = startDate; - confData.EndDate = endDate; - confData.DayOffsets = Enumerable.Range(0, numberOfDays) - .Select(offset => - (offset, (startDate?.AddDays(offset))?.DayOfWeek)); + confData.StartDate = startDate; + confData.EndDate = endDate; + confData.DayOffsets = Enumerable.Range(0, numberOfDays) + .Select(offset => + (offset, (startDate?.AddDays(offset))?.DayOfWeek)); - return confData; - }); + return confData; } public class ConferenceData : Dictionary>> diff --git a/src/FrontEnd/Pages/MyAgenda.cshtml b/src/FrontEnd/Pages/MyAgenda.cshtml index 4667db12..f1ab8f3d 100644 --- a/src/FrontEnd/Pages/MyAgenda.cshtml +++ b/src/FrontEnd/Pages/MyAgenda.cshtml @@ -4,73 +4,8 @@ ViewData["Title"] = "Home Page"; } -@if (Model.ShowMessage) -{ - -} - -
    -

    My Conference @System.DateTime.Now.Year

    - - @if (Model.UserSessions.Count == 0) - { -

    - You have not yet added any sessions to your agenda. Add sessions to your personal agenda - by browsing the conference agenda or searching - for sessions and speakers and clicking the star button. -

    - } + - +

    My Agenda - My Conference @System.DateTime.Now.Year

    - @foreach (var timeSlot in Model.ConferenceModel[Model.CurrentDayOffset]) - { -

    @timeSlot.Key?.ToString("HH:mm")

    -
    - @foreach (var session in timeSlot) - { - var inUserAgenda = Model.UserSessions?.Contains(session.Id) ?? false; - if (inUserAgenda) - { -
    -
    -
    @session.Track?.Name
    - - -
    -
    - } - } -
    - } -
    \ No newline at end of file + \ No newline at end of file diff --git a/src/FrontEnd/Pages/MyAgenda.cshtml.cs b/src/FrontEnd/Pages/MyAgenda.cshtml.cs index bee77d30..36866743 100644 --- a/src/FrontEnd/Pages/MyAgenda.cshtml.cs +++ b/src/FrontEnd/Pages/MyAgenda.cshtml.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using ConferenceDTO; using FrontEnd.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Caching.Memory; @@ -15,9 +14,12 @@ public class MyAgendaModel : IndexModel public MyAgendaModel(IApiClient client, IMemoryCache cache) : base(client, cache) { - } - public override bool ShowSessionsNotInAgenda() => false; + protected override Task GetConferenceDataAsync() + { + var sessions = UserSessions; + return Task.FromResult(GenerateConferenceData(sessions)); + } } } \ No newline at end of file diff --git a/src/FrontEnd/Pages/Shared/_AgendaPartial.cshtml b/src/FrontEnd/Pages/Shared/_AgendaPartial.cshtml new file mode 100644 index 00000000..134a1331 --- /dev/null +++ b/src/FrontEnd/Pages/Shared/_AgendaPartial.cshtml @@ -0,0 +1,61 @@ +@model IndexModel + +
    + + + @foreach (var timeSlot in Model.ConferenceModel[Model.CurrentDayOffset]) + { +

    @timeSlot.Key?.ToString("HH:mm")

    +
    + @{ + var userSessionIds = Model.UserSessions?.Select(s => s.Id).ToList(); + } + @foreach (var session in timeSlot) + { +
    +
    +
    @session.Track?.Name
    + + +
    +
    + } +
    + } +
    \ No newline at end of file diff --git a/src/FrontEnd/Pages/Shared/_AlertPartial.cshtml b/src/FrontEnd/Pages/Shared/_AlertPartial.cshtml new file mode 100644 index 00000000..4d54e6b9 --- /dev/null +++ b/src/FrontEnd/Pages/Shared/_AlertPartial.cshtml @@ -0,0 +1,8 @@ +@model (bool ShowMessage, string Message) +@if (Model.ShowMessage) +{ + +} \ No newline at end of file diff --git a/src/FrontEnd/Services/ApiClient.cs b/src/FrontEnd/Services/ApiClient.cs index 7ca0b415..61e877cd 100644 --- a/src/FrontEnd/Services/ApiClient.cs +++ b/src/FrontEnd/Services/ApiClient.cs @@ -145,26 +145,11 @@ public async Task RemoveSessionFromAttendeeAsync(string name, int sessionId) public async Task> GetSessionsByAttendeeAsync(string name) { - // TODO: Would be better to add backend API for this + var response = await _httpClient.GetAsync($"/api/attendees/{name}/sessions"); - var sessionsTask = GetSessionsAsync(); - var attendeeTask = GetAttendeeAsync(name); - - await Task.WhenAll(sessionsTask, attendeeTask); - - var sessions = await sessionsTask; - var attendee = await attendeeTask; - - if (attendee == null) - { - return new List(); - } - - var sessionIds = attendee.Sessions.Select(s => s.Id); - - sessions.RemoveAll(s => !sessionIds.Contains(s.Id)); + response.EnsureSuccessStatusCode(); - return sessions; + return await response.Content.ReadAsAsync>(); } public async Task CheckHealthAsync() From cf1de7fd911e09fa680cfc71dd79c0d83c8f3342 Mon Sep 17 00:00:00 2001 From: DamianEdwards Date: Sun, 16 Jun 2019 18:45:12 +0200 Subject: [PATCH 29/56] Make EditSession use AlertPartial --- src/FrontEnd/Pages/Admin/EditSession.cshtml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/FrontEnd/Pages/Admin/EditSession.cshtml b/src/FrontEnd/Pages/Admin/EditSession.cshtml index cb55684a..8c7508f5 100644 --- a/src/FrontEnd/Pages/Admin/EditSession.cshtml +++ b/src/FrontEnd/Pages/Admin/EditSession.cshtml @@ -3,13 +3,7 @@

    Edit Session

    -@if (Model.ShowMessage) -{ - -} +
    From 1665f205308a4476272d074e80d77c731b549042 Mon Sep 17 00:00:00 2001 From: DamianEdwards Date: Sun, 16 Jun 2019 19:08:03 +0200 Subject: [PATCH 30/56] Fix the Session page so unauthenticated users can view it --- src/BackEnd/Controllers/SearchController.cs | 42 ++----------------- .../Infrastructure/EntityExtensions.cs | 2 +- src/FrontEnd/Pages/Session.cshtml.cs | 7 +++- 3 files changed, 10 insertions(+), 41 deletions(-) diff --git a/src/BackEnd/Controllers/SearchController.cs b/src/BackEnd/Controllers/SearchController.cs index f868c05b..a21a12b3 100644 --- a/src/BackEnd/Controllers/SearchController.cs +++ b/src/BackEnd/Controllers/SearchController.cs @@ -41,49 +41,15 @@ public async Task>> Search(SearchTerm term) ) .ToListAsync(); - var results = sessionResults.Select(s => new SearchResult + var results = sessionResults.Select(session => new SearchResult { Type = SearchResultType.Session, - Session = new SessionResponse - { - Id = s.Id, - Title = s.Title, - Abstract = s.Abstract, - StartTime = s.StartTime, - EndTime = s.EndTime, - TrackId = s.TrackId, - Track = new ConferenceDTO.Track - { - Id = s?.TrackId ?? 0, - Name = s.Track?.Name - }, - Speakers = s?.SessionSpeakers - .Select(ss => new ConferenceDTO.Speaker - { - Id = ss.SpeakerId, - Name = ss.Speaker.Name - }) - .ToList() - } + Session = session.MapSessionResponse() }) - .Concat(speakerResults.Select(s => new SearchResult + .Concat(speakerResults.Select(speaker => new SearchResult { Type = SearchResultType.Speaker, - Speaker = new SpeakerResponse - { - Id = s.Id, - Name = s.Name, - Bio = s.Bio, - WebSite = s.WebSite, - Sessions = s.SessionSpeakers? - .Select(ss => - new ConferenceDTO.Session - { - Id = ss.SessionId, - Title = ss.Session.Title - }) - .ToList() - } + Speaker = speaker.MapSpeakerResponse() })); return results.ToList(); diff --git a/src/BackEnd/Infrastructure/EntityExtensions.cs b/src/BackEnd/Infrastructure/EntityExtensions.cs index 36635121..41a10d35 100644 --- a/src/BackEnd/Infrastructure/EntityExtensions.cs +++ b/src/BackEnd/Infrastructure/EntityExtensions.cs @@ -17,7 +17,7 @@ public static ConferenceDTO.SessionResponse MapSessionResponse(this Session sess Id = ss.SpeakerId, Name = ss.Speaker.Name }) - .ToList(), + .ToList(), TrackId = session.TrackId, Track = new ConferenceDTO.Track { diff --git a/src/FrontEnd/Pages/Session.cshtml.cs b/src/FrontEnd/Pages/Session.cshtml.cs index e86ba00e..d377f7b5 100644 --- a/src/FrontEnd/Pages/Session.cshtml.cs +++ b/src/FrontEnd/Pages/Session.cshtml.cs @@ -33,9 +33,12 @@ public async Task OnGetAsync(int id) return RedirectToPage("/Index"); } - var sessions = await _apiClient.GetSessionsByAttendeeAsync(User.Identity.Name); + if (User.Identity.IsAuthenticated) + { + var sessions = await _apiClient.GetSessionsByAttendeeAsync(User.Identity.Name); - IsInPersonalAgenda = sessions.Any(s => s.Id == id); + IsInPersonalAgenda = sessions.Any(s => s.Id == id); + } var allSessions = await _apiClient.GetSessionsAsync(); From dad1df3ac38b60f0161c0fd98c582af8fa723510 Mon Sep 17 00:00:00 2001 From: DamianEdwards Date: Sun, 16 Jun 2019 19:49:29 +0200 Subject: [PATCH 31/56] Fix scaffolding package reference --- src/BackEnd/BackEnd.csproj | 1 - src/FrontEnd/FrontEnd.csproj | 1 - 2 files changed, 2 deletions(-) diff --git a/src/BackEnd/BackEnd.csproj b/src/BackEnd/BackEnd.csproj index 9c2da783..05b64911 100644 --- a/src/BackEnd/BackEnd.csproj +++ b/src/BackEnd/BackEnd.csproj @@ -17,7 +17,6 @@ all - runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/FrontEnd/FrontEnd.csproj b/src/FrontEnd/FrontEnd.csproj index c9af7a9f..650c1b51 100644 --- a/src/FrontEnd/FrontEnd.csproj +++ b/src/FrontEnd/FrontEnd.csproj @@ -19,7 +19,6 @@ all - runtime; build; native; contentfiles; analyzers; buildtransitive From bcc4f258cfe2b5cf1c27c1dd2b732857f1c4c885 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sun, 16 Jun 2019 11:21:23 -0700 Subject: [PATCH 32/56] Updated docs --- docs/4. Add auth features.md | 6 +- docs/5. Add personal agenda.md | 186 ++++++++++++++++----------------- 2 files changed, 91 insertions(+), 101 deletions(-) diff --git a/docs/4. Add auth features.md b/docs/4. Add auth features.md index b87c5561..82da35a4 100644 --- a/docs/4. Add auth features.md +++ b/docs/4. Add auth features.md @@ -680,10 +680,8 @@ We're currently using `if` blocks to determine whether to show parts of the UI b @speaker.Name } -
  5. - Edit -
  6. - + + Edit ``` diff --git a/docs/5. Add personal agenda.md b/docs/5. Add personal agenda.md index 0f2aa76e..1b780674 100644 --- a/docs/5. Add personal agenda.md +++ b/docs/5. Add personal agenda.md @@ -329,25 +329,26 @@ dotnet aspnet-codegenerator identity --dbContext FrontEnd.Data.IdentityDbContext public async Task> GetSessionsByAttendeeAsync(string name) { - // TODO: Would be better to add backend API for this + var response = await _httpClient.GetAsync($"/api/attendees/{name}/sessions"); - var sessionsTask = GetSessionsAsync(); - var attendeeTask = GetAttendeeAsync(name); - - await Task.WhenAll(sessionsTask, attendeeTask); - - var sessions = await sessionsTask; - var attendee = await attendeeTask; - - if (attendee == null) - { - return new List(); - } - - var sessionIds = attendee.Sessions.Select(s => s.Id); - - sessions.RemoveAll(s => !sessionIds.Contains(s.Id)); + response.EnsureSuccessStatusCode(); + return await response.Content.ReadAsAsync>(); + } + ``` +### Add the BackEnd API to get sessions by an attendee +1. Add an action called `GetSessions` to the `AttendeesController` in the `BackEnd` project: + ```c# + [HttpGet("{username}/sessions")] + public async Task>> GetSessions(string username) + { + var sessions = await _db.Sessions.AsNoTracking() + .Include(s => s.Track) + .Include(s => s.SessionSpeakers) + .ThenInclude(ss => ss.Speaker) + .Where(s => s.SessionAttendees.Any(sa => sa.Attendee.UserName == username)) + .Select(m => m.MapSessionResponse()) + .ToListAsync(); return sessions; } ``` @@ -361,9 +362,12 @@ dotnet aspnet-codegenerator identity --dbContext FrontEnd.Data.IdentityDbContext 1. Compute the value of that property in `OnGetAsync`: ```csharp - var sessions = await _apiClient.GetSessionsByAttendeeAsync(User.Identity.Name); + if (User.Identity.IsAuthenticated) + { + var sessions = await _apiClient.GetSessionsByAttendeeAsync(User.Identity.Name); - IsInPersonalAgenda = sessions.Any(s => s.Id == id); + IsInPersonalAgenda = sessions.Any(s => s.Id == id); + } ``` 1. Add a form to the bottom of `Session.cshtml` razor page that adds the ability to add/remove the session to the attendee's personal agenda: @@ -470,70 +474,37 @@ dotnet aspnet-codegenerator identity --dbContext FrontEnd.Data.IdentityDbContext } } ``` -1. Add the HTML to render the list of sessions on the attendee's personal agenda to `MyAgenda.cshtml`: - +1. Refactor the `Index.cshtml` into a `_AgendaPartial.cshtml` under the `Pages\Shared` folder. It should have the following content: ```html - @page - @model MyAgendaModel - @{ - ViewData["Title"] = "My Agenda"; - } - - @if (Model.ShowMessage) - { - - } + @model IndexModel
    -

    My Conference @System.DateTime.Now.Year

    - - @if (Model.UserSessions.Count == 0) - { -

    - You have not yet added any sessions to your agenda. Add sessions to your personal agenda - by browsing the conference agenda or searching - for sessions and speakers and clicking the star button. -

    - } - - - @foreach (var timeSlot in Model.Sessions) {

    @timeSlot.Key?.ToString("HH:mm")

    @foreach (var session in timeSlot) { -
    -
    -
    @session.Track?.Name
    - - }
    }
    ``` +1. Update the `Index.cshtml` to use the new `_AgendaPartial`. Replace the entire div with the "agenda" css class and replace it with the following: + ```html +

    My Conference @System.DateTime.Now.Year

    + + + ``` +1. Next, use the `_AgendaPartial` on the `MyAgenda.cshtml` page. + ```html + @page + @model MyAgendaModel + @{ + ViewData["Title"] = "My Agenda"; + } + + @if (Model.ShowMessage) + { + + } + +

    My Agenda - My Conference @System.DateTime.Now.Year

    + + + ``` ## Add the My Agenda link to the Layout 1. Go to the layout file `_Layout.cshtml`. @@ -581,21 +578,14 @@ dotnet aspnet-codegenerator identity --dbContext FrontEnd.Data.IdentityDbContext
    - ``` -1. Add a `[TempData]` backed `Message` property to `IndexModel`, similar to the property we added to the `EditSession` page: - ```csharp - [TempData] - public string Message { get; set; } - - public bool ShowMessage => !string.IsNullOrEmpty(Message); - ``` + ``` 1. You should be able to login as an attendee, add/remove sessions to your personal agenda and click on MyAgenda to have them show up. ## Update IndexModel to include User Sessions 1. Add a `UserSessions` property to the `IndexModel`: ```csharp - public List UserSessions { get; set; } - ``` + public List UserSessions { get; set; } = new List(); + ``` 1. Update the `OnGet` method to fetch the `UserSessions`: ```csharp @@ -603,28 +593,30 @@ dotnet aspnet-codegenerator identity --dbContext FrontEnd.Data.IdentityDbContext { CurrentDayOffset = day; - var userSessions = await _apiClient.GetSessionsByAttendeeAsync(User.Identity.Name); - UserSessions = userSessions.Select(u => u.Id).ToList(); + if (User.Identity.IsAuthenticated) + { + var userSessions = await _apiClient.GetSessionsByAttendeeAsync(User.Identity.Name); + UserSessions = userSessions.Select(u => u.Id).ToList(); + } var sessions = await GetSessionsAsync(); //... ``` 1. Add the following two methods to the `IndexModel` to handle adding and removing sessions from your agenda fron the `Index` page: ```csharp - - public async Task OnPostAsync(int sessionId) - { - await _apiClient.AddSessionToAttendeeAsync(User.Identity.Name, sessionId); + public async Task OnPostAsync(int sessionId) + { + await _apiClient.AddSessionToAttendeeAsync(User.Identity.Name, sessionId); - return RedirectToPage(); - } + return RedirectToPage(); + } - public async Task OnPostRemoveAsync(int sessionId) - { - await _apiClient.RemoveSessionFromAttendeeAsync(User.Identity.Name, sessionId); + public async Task OnPostRemoveAsync(int sessionId) + { + await _apiClient.RemoveSessionFromAttendeeAsync(User.Identity.Name, sessionId); - return RedirectToPage(); - } + return RedirectToPage(); + } ``` 1. Run the application and test logging in and managing your agenda from the `Index` page, individual session details, and from the `My Agenda` page. From 0545b675eb6fc38fbcffc55d37d75ea79df97191 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sun, 16 Jun 2019 20:00:24 -0700 Subject: [PATCH 33/56] Add NDC Oslo data --- src/BackEnd/Data/Import/NDC_Oslo_2019.json | 8445 ++++++++++++++++++++ 1 file changed, 8445 insertions(+) create mode 100644 src/BackEnd/Data/Import/NDC_Oslo_2019.json diff --git a/src/BackEnd/Data/Import/NDC_Oslo_2019.json b/src/BackEnd/Data/Import/NDC_Oslo_2019.json new file mode 100644 index 00000000..48db0fde --- /dev/null +++ b/src/BackEnd/Data/Import/NDC_Oslo_2019.json @@ -0,0 +1,8445 @@ +[ + { + "date": "2019-06-19T00:00:00", + "rooms": [ + { + "id": 4479, + "name": "Room 1", + "sessions": [ + { + "id": "98819", + "title": "An introduction to Machine Learning using LEGO", + "description": "Where do you start when you want to learn Machine Learning? Do you start by learning some advanced algorithms or perhaps a Machine Learning framework? In this talk, I will show an alternative approach on how to get started with Machine Learning by using a LEGO car as a model. By using Machine Learning, we can make the LEGO car steer autonomously!\r\n\r\nIn the process of making a LEGO car steer autonomously I will go through the following topics:\r\n- What is Machine Learning?\r\n- Can we make the LEGO car steer autonomously without Machine Learning?\r\n- How does the basic theory behind Machine Learning work?\r\n- How do we connect theory to LEGO bricks?\r\n\r\nThe aim of this talk is not to make you an expert in Machine Learning, however, it will hopefully inspire you to investigate and get familiar with Machine Learning in a playful and simple way.", + "startsAt": "2019-06-19T10:20:00", + "endsAt": "2019-06-19T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "7e84a6a9-f685-4cfa-a31d-9c00ce592b79", + "name": "Jeppe Tornfeldt Sørensen" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + { + "id": "99028", + "title": "How to Steal an Election", + "description": "In this session I'll demonstrate some of the data science techniques that can be used to influence a population to a particular way of thinking, or to vote in a particular way. With all the talk of collusion in the American, and other, elections I think it's about time we explore the art of the possible in this field, and see just how they might have done it.", + "startsAt": "2019-06-19T11:40:00", + "endsAt": "2019-06-19T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "2a5c6285-1012-49e7-a0f6-1efdeea7dba9", + "name": "Gary Short" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + { + "id": "84070", + "title": "Why databases cry at night?", + "description": "In the dark of the night, if you listen carefully enough, you can hear databases cry. But why? As developers, we rarely consider what happens under the hood of widely used abstractions such as databases. As a consequence, we rarely think about the performance of databases. This is especially true to less widespread, but often very useful NoSQL databases.\r\n\r\nIn this talk we will take a close look at NoSQL database performance, peek under the hood of the most frequently used features to see how they affect performance and discuss performance issues and bottlenecks inherent to all databases.", + "startsAt": "2019-06-19T13:40:00", + "endsAt": "2019-06-19T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f70aa2e2-a961-4c7f-bb77-e5ab82692ee9", + "name": "Michael Yarichuk" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + { + "id": "99466", + "title": "Drones & AI - What's all the buzz about ?", + "description": "Drones and AI are changing our world.\r\n\r\nIn this session we will look at some of the real world solutions utilising these emerging technologies, you will get an understanding of the core use cases, learn how to get started with the tech, and find out about the pitfalls to avoid when building solutions with drones and Artificial Intelligence.", + "startsAt": "2019-06-19T15:00:00", + "endsAt": "2019-06-19T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "81ccb948-0157-4ef0-bd80-c11ad108d7cb", + "name": "Adam Stephensen" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + { + "id": "98996", + "title": "Automatic text summarization", + "description": "Automatic text summarization is the process of shortening a text document by automatically creating a short, accurate, and fluent summary with the main points of the original document using software. It is a common problem in machine learning and natural language processing. \r\n\r\nSince humans have the capacity to understand the meaning of a text document and extract the most important information from the original source using their own words, we are generally quite good at making summaries of a text. However, manual creation of summaries is very time consuming, and therefore a need for automatic summary has arisen. Not only are the automatic summarization tools much faster, they are also less biased than humans. \r\n\r\nNowadays, there are several methods of text summary, but there are two basic approaches to text summary that are based on the output type: extractive and abstractive. In an extractive summary, the most important sentences are extracted and joined to get a brief summary. The abstract text summary algorithms create new sentences and sentences that provide the most useful information from the original text - just as humans do. \r\n\r\nThis lecture provides insight into most common algorithms and tools used for automatic text summarization today, together with the methods used to evaluate automated summaries. \r\n", + "startsAt": "2019-06-19T16:20:00", + "endsAt": "2019-06-19T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e47fa275-9f67-4ef4-8571-28d1b17d667a", + "name": "Masa Nekic" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + { + "id": "97550", + "title": "Entity Framework debugging using SQL Server: A Detective Story", + "description": "What happens when the code for your Entity Framework Core LINQ queries looks good, but your app is very slow? Are you looking in the right place? Don’t be afraid to start looking at your database. Knowing how to investigate and debug what your LINQ queries are doing in SQL Server is as important as the actual LINQ query in your .NET solutions. We will be looking at database server configurations, using MSSQL database profiling tools and understanding Query Execution Plans to get the most out of Entity Framework. In the end, learning to be an Entity Framework detective will make your project sound and snappy.", + "startsAt": "2019-06-19T17:40:00", + "endsAt": "2019-06-19T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "215bbd42-ce3a-4744-af1f-7e5f0f30d620", + "name": "Chris Woodruff" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4480, + "name": "Room 2", + "sessions": [ + { + "id": "97632", + "title": "C# and Rust: combining managed and unmanaged code without sacrificing safety", + "description": "Why would you ever want to introduce unmanaged code into your managed codebase when recent versions of C# have made writing high performance code in .NET more accessible than ever before? While C# has been pushing downwards into the realm of \"systems programming\", Rust, a language that already operates in this space, has been pushing upwards. The result isn't a competition where one language must emerge as more universally applicable than the other. It's a broader set of cases where C# and Rust can work together, and integrating them effectively is more idiomatic thanks to this broadening of scope.\r\n\r\nWhen we set out in 2018 to rebuild the storage engine for our log server, Seq, we decided to complement our existing C# codebase with a new one written in Rust. In this talk we'll look at why you might want to add unmanaged code to your managed codebase, using Seq as an example. We'll explore how to use the tools that .NET and Rust give us to design and build a safe and robust foreign function interface. In the end we'll have a new perspective on the implicit safety contracts we're expected to uphold in our purely managed codebases.", + "startsAt": "2019-06-19T10:20:00", + "endsAt": "2019-06-19T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "0029ba03-068c-44eb-bd23-3cdd17fc725a", + "name": "Ashley Mannix" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + { + "id": "119373", + "title": "Hidden gems in .NET Core 3", + "description": "You've likely heard about the headline features in .NET Core 3.0 including Blazor, gRPC, and Windows desktop app support, but what else is there?\r\n\r\nThis is a big release so come and see David Fowler and Damian Edwards from the .NET Core team showcase their favorite new features you probably haven't heard about in this demo-packed session.", + "startsAt": "2019-06-19T11:40:00", + "endsAt": "2019-06-19T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "a2c9a4b0-cb47-414a-a7fb-93d0928e77d2", + "name": "Damian Edwards" + }, + { + "id": "b2959d46-2ae9-494b-865c-fb850e37d24a", + "name": "David Fowler" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + { + "id": "81621", + "title": "C++: λ Demystified", + "description": "C++11 lambdas brought us lambdas. They open a lot of new possibilities. Frequently asked questions are:\r\n- How are they implemented?\r\n- How do they work?\r\n- How can it affect my daily programming?\r\n- Do they generate a lot of code?\r\n- What can I do with them?\r\n- Where can I use them?\r\n\r\nIn this talk I will answer these questions. With the support of C++ Insights (https://cppinsights.io) we will peak behind the scenes to answer questions about how they are implemented. We will also see how the compiler generated code changes, if we change the lambda itself. This is often interesting for development in constrained applications like the embedded domain.\r\n\r\nNext I will show you application areas of lambdas to illustrate where they can be helpful. For example, how they can help you to write less and with that more unique code.\r\n\r\nAfter the talk, you will have a solid understanding of lambdas in C++. Together with some ideas when and where to use them.", + "startsAt": "2019-06-19T13:40:00", + "endsAt": "2019-06-19T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "0871f66f-f085-4b96-a311-bd7570460627", + "name": "Andreas Fertig" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + { + "id": "78447", + "title": "Rust for C++ developers - What you need to know to get rolling with crates", + "description": "The session is about using the Rust language to write safe, concurrent and elegant code, contrasting with C++", + "startsAt": "2019-06-19T15:00:00", + "endsAt": "2019-06-19T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "3b2b49cf-5746-484c-a85e-be960fe76043", + "name": "Pavel Yosifovich" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + { + "id": "98569", + "title": "Securing Web APIs from JavaScript/SPA Applications", + "description": "Modern web development means that more and more application code is running in the browser as JavaScript. This architectural shift requires us to change how we perform authentication and authorization. Fortunately, using modern protocols such as OpenID Connect you don’t need to invent your own solution for this new environment. This session will show you the modern approach for browser-based JavaScript applications to authenticate users, and perform secure web api invocations. As you might expect, security is sufficiently complex and so even modern security comes with its own set of challenges. Luckily, we will show off some libraries that help manage this complexity so your application doesn’t have to.", + "startsAt": "2019-06-19T16:20:00", + "endsAt": "2019-06-19T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "d438622e-8053-4a8f-8df0-af7e9ad32db0", + "name": "Brock Allen" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + { + "id": "98020", + "title": "Mechanical C++ Refactoring in the Present and in the Future", + "description": "In the last few years, Clang has opened up new possibilities in C++ tooling for the masses. Tools such as clang-tidy offer ready-to-use source-to-source transformations. Available transformations can be used to modernize (use newer C++ language features), improve readability (remove redundant constructs), or improve adherence to the C++ Core Guidelines.\r\n\r\nHowever, when special needs arise, maintainers of large codebases need to learn some of the Clang APIs to create their own porting aids. The Clang APIs necessarily form a more-exact picture of the structure of C++ code than most developers keep in their heads, and bridging the conceptual gap can be a daunting task.\r\n\r\nTooling supplied with clang-tidy, such as clang-query, are indispensable in the discovery of the Clang AST.\r\n\r\nThis talk will show recent and future features in Clang tooling, as well as Tips, Tricks and Traps encountered on the journey to quality refactoring tools. The audience will see how mechanical refactoring in a large codebase can become easy, given the right tools.\r\n", + "startsAt": "2019-06-19T17:40:00", + "endsAt": "2019-06-19T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "dae0a4a0-9346-4031-82b0-365633cdd776", + "name": "Stephen Kelly" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4481, + "name": "Room 3", + "sessions": [ + { + "id": "77259", + "title": "I'm Going To Make You Stop Hating CSS.", + "description": "As a formalized language, CSS is over 20 years old and has spent much of that time being maligned by the people who use it. Browser inconsistencies, changing specifications and general weirdness have combined to create this weird pseudo-language that you'd rather avoid.\r\n\r\nUNTIL TODAY. With modern specs and tooling, CSS has never been more straightforward and less reliant on hacks. In this talk, Lemon will show you some common traps people fall in, as well as some general strategies for making a layout grid you can proud to build and confident in releasing.", + "startsAt": "2019-06-19T10:20:00", + "endsAt": "2019-06-19T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f4f1eb31-8574-4e8a-a94a-ee0aef8c28d5", + "name": "Lemon 🍋" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + { + "id": "97811", + "title": "Web components and micro apps, the web technologies peacekeeper", + "description": "Web development can be a bit tiring with all these new innovative technologies and frameworks we get on a regular basis especially if you have to maintain a product for a long time.\r\n\r\nHowever, web components and micro apps has given us a solution which is framework independent. It allows for decomposition of a big project into smaller, more maintainable parts that can be handled by different teams with different technologies.\r\n\r\nLet's go on a journey to find out how we can unite best technologies to form our enterprise apps.", + "startsAt": "2019-06-19T11:40:00", + "endsAt": "2019-06-19T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "a127e924-82ac-42df-8761-ecb106c8ef61", + "name": "Yaser Adel Mehraban" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + { + "id": "83799", + "title": "Responsible JavaScript", + "description": "While the performance of JavaScript engines in browsers have seen continued improvement, the amount of JavaScript we serve increases unabated. We need to use JavaScript more responsibly, which means we must rely on native browser features where prudent, use HTML and CSS when appropriate, and know when too much JavaScript is just that: Too much. \r\n\r\nIn this talk, we'll explore what happens to performance and accessibility when devices are inundated with more JavaScript than they can handle. We'll also dive into some novel techniques you can use to tailor delivery of scripts with respect to a person's device capabilities and network connection quality. When you walk out of this session, you'll be equipped with new knowledge to make your sites as fast as they are beautiful.", + "startsAt": "2019-06-19T13:40:00", + "endsAt": "2019-06-19T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "c3017677-3f20-4b72-8d3f-a2dfa18f4e99", + "name": "Jeremy Wagner" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + { + "id": "97507", + "title": "CSS Grid - What is this Magic?!", + "description": "We’ve all heard a lot in the last year about a new advancement in the world of CSS, called CSS Grid. Starting off at whispers, we’re now starting to hear it as a deafening roar as more and more developers write about it, talk about it, share it and start using it. In the world of front end, I see it everywhere I turn and am excited as I start to use it in my own projects.\r\n\r\nBut what does this new CSS specification mean for software developers, and why should you care about it? In the world of tech today, we can do so many amazing things and use whatever language we choose across a wide range of devices and platforms. Whether it’s the advent of React and React Native, or frameworks like Electron, it’s easier than ever to build one app that works on multiple platforms with the language we know and work with best. The ability to do this also expands to styling apps on any platform using CSS, and therefore being able to utilise the magical thing that is\r\nCSS Grid.\r\n\r\nThe reason CSS Grid is gaining so much attention, is because it’s a game changer for front end and layouts. With a few simple lines of code, we can now create imaginative, dynamic, responsive layouts (yep, I know that’s a lot of buzz words). While a lot of people are calling this the new ‘table layout’, grid gives us so much more, with the ability to spread cells across columns and rows to whatever size you choose, dictate which direction new items flow, allow cells to move around to fit in place and even tell certain cells exactly where they need to sit.\r\n\r\nWhile there is so much to worry about when developing an app, CSS Grid means that you can worry less about building the layout on the front end, and more about making sure the back end works well. Let me show you how the magic works.", + "startsAt": "2019-06-19T15:00:00", + "endsAt": "2019-06-19T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "d387e75c-ed26-4dc6-8612-0f18abdfd9f5", + "name": "Amy Kapernick" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + { + "id": "98750", + "title": "Panel discussion on the future of .NET", + "description": "Join us for a discussion with four leaders in the field on the current state of the art and the where .NET and related technologies are heading.\r\n\r\nWe will discuss cross platform development, new features, performance improvements, .NET Core and EF Core 3, what’s going to happen with full framework, Blazor, how .NET stands up against competing technologies and where it is all going.\r\n\r\nYou won't cram more info into a session than this, come spend a great hour with us.", + "startsAt": "2019-06-19T16:20:00", + "endsAt": "2019-06-19T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "de972e57-7765-4c38-9dcd-5981587c1433", + "name": "Bryan Hogan" + }, + { + "id": "c9c8096e-47a1-41e5-a00c-d49b51d01c4e", + "name": "K. Scott Allen" + }, + { + "id": "282a4701-f128-4b1d-bd67-da5d1f8b3eb0", + "name": "Julie Lerman" + }, + { + "id": "b2959d46-2ae9-494b-865c-fb850e37d24a", + "name": "David Fowler" + }, + { + "id": "a2c9a4b0-cb47-414a-a7fb-93d0928e77d2", + "name": "Damian Edwards" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + { + "id": "98457", + "title": "Testing GraphQL: From Zero To Hundred Percent", + "description": "Testing is important for every project, whether it's a web application or api service. But writing scripts to test your application can be a hassle, especially for specific frameworks or tools like GraphQL. Sure, you could just test using Jest, Enzyme or any other testing tool out there for JavaScript applications. But how do you specifically test your GraphQL schemas and queries?", + "startsAt": "2019-06-19T17:40:00", + "endsAt": "2019-06-19T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "4bb972aa-3d92-45ff-95b4-68ed3ca86e9e", + "name": "Roy Derks" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4482, + "name": "Room 4", + "sessions": [ + { + "id": "83948", + "title": "10 years of microservices at FINN.no - and we still haven’t slain that dragon!", + "description": "At FINN.no we started splitting up the monolith nearly ten years ago. Even though we have a few hundred services, major parts of the monolith is still running. \r\n\r\nHow did we approach it? What have we learned? Why is the monolithic dragon still here?", + "startsAt": "2019-06-19T10:20:00", + "endsAt": "2019-06-19T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "788869df-4013-4126-92a6-8e900cd67013", + "name": "Henning Spjelkavik" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + { + "id": "86697", + "title": "Kill Evil Mutants!", + "description": "How good are your tests? Would they still pass if the tested code was changed much? If so, there's probably a problem with your code, your tests, or both!\r\n\r\nMutation Testing helps reveal these cases. It makes changed versions of your code (mutants) and runs your tests against the mutants to \"kill\" them. Survivors, aka \"*evil* mutants\", imply that there are flaws in your code or tests.\r\n\r\nThis talk will tell you how and why to use mutation testing, and how it works, including some examples and tools for popular languages.", + "startsAt": "2019-06-19T11:40:00", + "endsAt": "2019-06-19T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "be5e2221-855b-4294-9e00-dcd97e0e5bab", + "name": "Dave Aronson" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + { + "id": "100429", + "title": "Chinafy your apps + Lessons you can steal from China", + "description": "Adam Cogan will talk about his experiences getting applications ready for the Chinese market. He has been in the China software world for over 12 years and has seen their ecosystem evolve, and it has been truly amazing. \r\nThere is so much software built in the west, that makes $ in America and $ in Europe but at the same time also has zero users in China. Let’s fix that!", + "startsAt": "2019-06-19T13:40:00", + "endsAt": "2019-06-19T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "7ddee6db-ced0-4c0d-847c-5ea4e1f2a35c", + "name": "Adam Cogan SSW" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + { + "id": "98629", + "title": "Getting out of quicksand, with DevOps!", + "description": "Join me in this talk about why high workload leads to increasing waiting times and is detrimental to your project’s success.\r\n\r\nTeams often find themselves in high workload situations, showing symptoms of overload and being to busy to implement the necessary changes or adopt the state-of-the-art tools to get the upper hand.\r\nThis is a story of how we applied the Three Ways of DevOps to get out of a state we referred to as quicksand (The more you fight it, the more it pulls you in).\r\n\r\nI will not only talk about queuing theory and capacity management, but also about DevOps strategies to cope with high utilization and how to start a virtuous circle.\r\n\r\nKey Takeaways are:\r\n\r\n* Crisis situations are opportunities for change\r\n* Often it takes fresh eyes or at least courage to see the problems\r\n* High workload leads to increasing waiting times\r\n* Get out of the quicksand with devops:\r\n * Quantify the work and set goals\r\n * Measure\r\n * Less is more\r\n * Automate the right things\r\n * Establish a continuous improvement process\r\n * Start a virtuous circle", + "startsAt": "2019-06-19T15:00:00", + "endsAt": "2019-06-19T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "7e1213ec-dc2b-400c-a280-fd5df894e11a", + "name": "Roman Pickl" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + { + "id": "98444", + "title": "Understanding Git — Behind the Command Line", + "description": "Git has become the de-facto version control system of our industry, and for good reason. What you're able to achieve with Git is unmatched by any other version control system that came before it. But for all its power and flexibility, Git has one terrible flaw: its complexity. You won't find me arguing with that. However, I don't believe that Git is hard to understand. In fact, it's quite the opposite — Git is surprisingly simple at its core. The key to unlock its power is to understand it at a fundamental level.\r\n\r\nIn this session, we'll do just that by going through how Git works from the ground up. We'll start out by understanding Git's fundamental concepts and how they're implemented in the object model. From there, we'll work our way up to the user-facing commands and learn to take advantage of Git's unique features to craft a beautiful history without having to compromise on our working style.\r\n\r\nIf you ever wished you knew how Git really works, come to this session and find out.", + "startsAt": "2019-06-19T16:20:00", + "endsAt": "2019-06-19T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "63b2c908-a6f0-41b6-ace8-46a3f5482c54", + "name": "Enrico Campidoglio" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + { + "id": "97531", + "title": "Azure on the cheap", + "description": "Microsoft Azure is a great platform to use when creating your next minimal viable product (MVP). \r\n\r\nBut some services are more expensive than others. And in this talk I will show that instead of going straight to the more expensive options for your MVP, there are many cheap options available on the Azure platform. Some services even have a free-tier. \r\n\r\nUsing Azure Storage Accounts for your data storage needs, Azure Functions or Azure Container Instances for your API and computing needs can make for a very cheap and low maintenance MVP. ", + "startsAt": "2019-06-19T17:40:00", + "endsAt": "2019-06-19T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "4dd872ca-5b4d-49cf-9697-cce19417e431", + "name": "Karl Syvert Løland" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4483, + "name": "Room 5", + "sessions": [ + { + "id": "97582", + "title": "Building APIs Rapidly with Azure Functions", + "description": "APIs are what makes the Internet go around. Every SaaS, data driven and on-demand kitten business exposes their data over an external or internal API. Which means you need one too, right? Of course you do.\r\nCreating an API that conforms with OpenAPI standards, can scale up and out, can be extended easily, and can be easily maintained is the Nirvana of API architecture. This is exactly the promise of building an API with Azure Functions, and it is super fast too! \r\nIn this session, you will learn to quickly create a full blown API using Azure Functions, create a proxy to forward requests, adhere to OpenAPI standards, easily extend and more. At the end of the talk we will have built an API that is (almost) production ready straight away. We then compare this process to other API frameworks to get the real world picture. \t\r\n", + "startsAt": "2019-06-19T10:20:00", + "endsAt": "2019-06-19T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f99fa878-6176-4ff4-b151-c717fa5daf0c", + "name": "Lars Klint" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + { + "id": "99256", + "title": "Getting to DDD: Pragmatic or Principled?", + "description": "Domain-Driven Design is a vast topic. There are so many wonderful concepts, philosophies, patterns, practices and techniques to learn and benefit from. Some of the best minds in the industry have been tuning these practices for years to ensure developers are able to implement proven, successful approaches to software design. Domain modeling in particular is very specific with guidance on designing and coordinating the dance between the myriad moving parts in our system. Yet learning the principals of DDD can be daunting for developers who are new to DDD. To encourage and enable more developers to get on the path of DDD, is it reasonable to allow a more pragmatic approach over a principled approach of adhering strictly to DDD guidelines? Should developers be encouraged to start with low hanging fruit which they can quickly benefit from in their software projects while they continue to learn, to gain a deeper understanding of Domain-Driven Design in order to evolve and adapt their practices as they move closer and closer to the beauty we all know that can be achieved with DDD.", + "startsAt": "2019-06-19T11:40:00", + "endsAt": "2019-06-19T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "282a4701-f128-4b1d-bd67-da5d1f8b3eb0", + "name": "Julie Lerman" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + { + "id": "99520", + "title": "Reactive DDD—When Concurrent Waxes Fluent", + "description": "Rarely achieved in past years, fully utilized hardware can now reach the performance, throughput, and scale possible with Reactive software development's responsive, resilient, elastic, and message-driven solutions. As crucial, fiscally-minded technical stakeholders see the urgent need to partner with business leaders in order to create software that delivers critical, differentiating innovations that are in demand to gain and maintain leadership in today's fast-paced commercial markets. The world of distribution, concurrency, latency, and the uncertainty of time-critical results, must be tackled along with complex business challenges. This talk gives practical guidance on creating your software refinement turning point by using Domain-Driven Design to model business-driven solutions with fluent, type-safe, and Reactive properties. Specific attention is given to moving legacy systems that have deep debt to ones that have clear boundaries, deliver explicit and fluent business models, and exploit modern hardware and software architectures.", + "startsAt": "2019-06-19T13:40:00", + "endsAt": "2019-06-19T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "4f5622e6-b5cd-47c7-a088-eb327ff64c53", + "name": "Vaughn Vernon" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + { + "id": "98397", + "title": "Adding Observability to Distributed Systems", + "description": "Tell me if this sounds familiar: you have a web service, that calls another service, that sends a Kafka message to a third service, that writes something to a database. Except sometimes it doesn’t. Where did the message go? Did the client not send it? Or did Kafka eat it? You don’t know. You look in the logs, but there are so many logs! You try to reproduce the problem, but annoyingly everything works fine. What to do?\r\n\r\nIn this talk we’ll explore mechanisms for observing and debugging distributed systems, with an eye towards taking an existing codebase that lacks observability and evolving it over time. In particular, we’ll focus on distributed tracing tools that let us track transactions which span multiple services and execution contexts. We’ll discuss how tracing differs from logging and monitoring. How to instrument applications to emit trace data, how to collect and store it, how to visualize transactions, and how this benefits developers, devops, and the business itself. We’ll look at leveraging popular open source technologies, like the CNCF OpenTracing project, Jaeger, Zipkin, and the newly released Elastic APM OpenTracing bridge. \r\n", + "startsAt": "2019-06-19T15:00:00", + "endsAt": "2019-06-19T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "1c0406d8-82a1-45b4-a818-7358e0abe7d9", + "name": "David Ostrovsky" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + { + "id": "79682", + "title": "Event Driven Collaboration", + "description": "When we move from a monolith to microservices we abandon integrating via a shared database, as each service must own its own data to allow them it to be autonomous. But now we have a new problem, our data is distributed. What happens if I need one service needs to talk to another about a shared concept such as a product, a hotel room, or an order? Does every service need to have a list of all our users? Who knows what users have permissions to the entities within the micro service? What happens if my REST endpoint needs to include data from a graph that includes other services to make it responsive? And I am not breaking the boundary of my service when all of this data leaves my service boundary in response to a request?\r\n\r\nNaive request-based solutions result in chatty calls as each service engages with multiple other services to fulfil a request, or in large message payloads as services add all the data required to process a message to each message. Neither scale well.\r\n\r\nIn 2005, Pat Helland wrote a paper ‘Data on the Inside vs. Data on the Outside’ which answers the question by distinguishing between data a service owns and reference data that it can use. Martin Fowler named the resulting architectural style; Event Driven Collaboration. This style is significant because it shifts the pattern from request to receiver-driven flow control. \r\n\r\nIn this presentation we will explain how events help us integrate our service architectures. We’ll provide examples in C#, Python and Go as well as using RMQ and Kafka.", + "startsAt": "2019-06-19T16:20:00", + "endsAt": "2019-06-19T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "84ffe422-5bc6-4075-9903-d9ad3526cf86", + "name": "Ian Cooper" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + { + "id": "84004", + "title": "Advanced Serverless Workflows with Durable Functions", + "description": "Azure Functions enable serverless code scenarios that can be triggered by a variety of events and scale automatically without having to configure individual servers or clusters. Durable functions provide state management for long running workflows. See how durable functions address scenarios from asynchronous sequential workflows to fan-out/fan-in scenarios and manual gateways. Learn how to kick-off durable worfklows, monitor progress, troubleshoot, and ultimately recognize significant cost savings by using a service that only bills when it is actively running.", + "startsAt": "2019-06-19T17:40:00", + "endsAt": "2019-06-19T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e4db7e19-394b-4cd9-bc92-9863c54c954f", + "name": "Jeremy Likness" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4484, + "name": "Room 6", + "sessions": [ + { + "id": "86348", + "title": "Unity 101 for C# Developers", + "description": "Recommended by Microsoft for creating mixed reality experiences for the Hololens, Unity has transcended its beginnings as a cross-platform game engine.\r\n\r\nSo whether you are looking to create a 3D game for mobile, or have your sights set on a virtual reality experience for the Oculus Rift, Unity is a tool you'll want to learn.\r\nOne surprise for C# developers getting started with Unity is the level of integration with Visual Studio and how simple it is to add C# code to manipulate their Unity creations.\r\n\r\nIn this demo led session, we’ll go back to basics with Unity, creating a simple 3D game with realistic physics, textures and explosions. We’ll look at the fantastic Visual Studio integration and how cohesively the two editors work together.\r\n\r\nFinally, we’ll look at a more complex 3D experience and how to use Unity's networking features to allow different users to interact in a 3D world.\r\n\r\nKeeping the best news for last: Unity is royalty free until you’re earning $100,000. So if you like the idea of becoming wildly rich from making immersive 3D experiences, this is the talk for you! ", + "startsAt": "2019-06-19T10:20:00", + "endsAt": "2019-06-19T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "ef4df68d-9bdc-471d-aff0-075c77c4a424", + "name": "Andy Clarke" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + { + "id": "98826", + "title": "Chasing holograms - the future of HoloLens development", + "description": "HoloLens development is a unique beast that is evolving quickly - how is developing applications to be used in the real world different for applications designed for screens?\r\n\r\nLearn the tools and processes required for Mixed Reality development, as well as useful tips and resources for giving your applications more and more understanding of the world around it.\r\nLet's explore the Mixed Reality Toolkit, the features of the next generation of the HoloLens, as well as how cloud services can be utilized for Mixed Reality applications. Last but not least, how does development for the next version of the HoloLens differ from the first?\r\n\r\nAt the end of this talk you will be equipped to tackle HoloLens development and take advantage of the latest features of the device, and related libraries and resources.", + "startsAt": "2019-06-19T11:40:00", + "endsAt": "2019-06-19T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "3e52cb3b-ba18-4766-b9bf-d8306bef9505", + "name": "Scott Leaman" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + { + "id": "76208", + "title": "DIY Async Message Pump: Lessons from the trenches", + "description": "Building a message pump that consumes and produces messages from queues is simple in theory. In practice, the picture looks a bit different. Over the years, as a contributor for queue adapters for RabbitMQ, Azure Service Bus, Azure Storage Queues, MSMQ, AmazonSQS, Kafka and SQL Server, I've made plenty of mistakes. Now I can teach you how to make those same mistakes!\r\n\r\nIn this talk, we'll see what a robust and reliable message pump with TPL and async looks like so we can avoid it. We'll examine asynchronous synchronization primitives which smarter people than I use to throttle requests, then compare and contrast different queuing technology message pumps to make sure we aren't building to each one's strengths. With this knowledge, if your message pump keeps on pumping for ages in a highly performant way, don't blame me!", + "startsAt": "2019-06-19T13:40:00", + "endsAt": "2019-06-19T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "7e39dc71-6d7a-477a-bcb6-842be6e533b4", + "name": "Daniel Marbach" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + { + "id": "99524", + "title": "Writing a Neural Net from Scratch", + "description": "The best way to understand neural networks is to get your hands dirty and write one.\r\nIn this session, I'll show you how to code up a neural net for image recognition from scratch - all in C#, and without using any libraries. From the bottom up, we'll discover gradient descent, activation functions, and backpropagation.\r\n\r\nWe'll work entirely in LINQPad - with no complex maths, no Python, and no libraries. And you'll get to keep the code!", + "startsAt": "2019-06-19T15:00:00", + "endsAt": "2019-06-19T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "35dc3b12-726c-47f6-b6b4-13a8d3d0e774", + "name": "Joe Albahari" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + { + "id": "98676", + "title": "Writing Allocation Free Code in C#", + "description": "Performance is a feature. We all want our code to run faster, and there are plenty of ways to do this - caching, using a smarter algorithm or simply doing less stuff. In this session, we’re not going to look at any of that. Instead, we’re going to focus on a recent trend in the C# world - improving performance by reducing memory allocations. We’ll see how recent versions of C# allow using structs without creating lots of copies, and we’ll have a timely reminder on exactly what is the difference between a class and a struct. We’ll also spend some time with the new Span<T> runtime type and find out how that can help work with slices of existing memory, and how it’s already into the types we know and love in the framework. And of course, we’ll take a look at when you should and (more importantly) shouldn’t use these new techniques.", + "startsAt": "2019-06-19T16:20:00", + "endsAt": "2019-06-19T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "d7dedbba-5fed-47fd-be25-4fb9b1342629", + "name": "Matt Ellis" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + { + "id": "82977", + "title": "C# 8 and Beyond", + "description": "One of the most popular programming language on the market is getting even better. With every iteration of C# we get more and more features that are meant to make our lives as developers a lot easier. \r\n\r\nJoin me in this session to explore what's new in C# 8, as well as what we can expect in the near (and far) future of C#!\r\n\r\nWe'll talk about:\r\n- News in C# 8\r\n- Pattern Matching (incl. Record Types)\r\n- Nullable Reference Types and How to Avoid Null Reference Exceptions\r\n- How Async & Await is Improving", + "startsAt": "2019-06-19T17:40:00", + "endsAt": "2019-06-19T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "1f8704d7-04db-4f09-9c0e-d5abcbc7c9ff", + "name": "Filip Ekberg" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4485, + "name": "Room 7", + "sessions": [ + { + "id": "99090", + "title": "Developing privacy", + "description": "In this day and age, privacy is important to our customers, and it should be important to you as well! In some cases, you're legally obligated to ensure your user's privacy and to protect their information, but it's increasingly becoming The Right Thing To Do (tm) as well. So how do we do it? Which traps lie in these waters? How do we, as developers, build solutions that protect our users from the start and all the way into the core of our applications. We'll go through patterns and techniques you can directly apply in your work, we'll talk about questions you should be asking your business and help you make privacy a feature of your system and not an afterthought. Without making your life needlessly difficult. ", + "startsAt": "2019-06-19T10:20:00", + "endsAt": "2019-06-19T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "fb75b901-4842-4858-ba35-8c370db0af14", + "name": "Glenn F. Henriksen" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + { + "id": "97631", + "title": "Adding business logic to your tokens. What could possibly go wrong.", + "description": "When working with an identity servers one of the first things we need to learn is the difference between an Id tokens and access tokens. The fact that we can add additional claims to these tokens may seem nice adding a number of claims that are related to business logic may seem like a great feature for your application you wont need to look up this information all the time. However there needs to be a limit and in fact there is. Adding large numbers of claims to tokens where they don't belong can also cause some problems for your application in the long run and can also be a security risk. \r\n", + "startsAt": "2019-06-19T11:40:00", + "endsAt": "2019-06-19T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "8403871b-1f4f-472b-a4e6-9982a353e1ac", + "name": "Linda Lawton" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + { + "id": "99872", + "title": "Lightning Talks", + "description": "Lightning talks (approx 10-15 minutes each)\r\n\r\nTalk 1: IoT meets IPv6: The Perfect Storm? - Kristian Bognæs\r\n\r\nMirai was for many a wakeup call on what not to do with IoT security. Using default creds, this malware spread itself on thousands of webcams and home routers and became one of the most disruptive DDOS tools in 2016. \r\nNow 3 years on, are we facing a new Mirai with the steady introduction of IPv6 and the number of private devices going online in this space increasing a massive rate? What do we need to consider as developers designing and developing applications for these IoT platforms? \r\nJoin Kristian as he walks you through how IPv6 will affect your security, and what you need to start doing to protect your code and create safer systems.\r\n-----------------------------------\r\nTalk 2: Root-of-trust - What it is and why you need one in IoT - Ole Konstad\r\n\r\nWhether you know it or not, if you have ever implemented any kind of digital security mechanism, your security is rooted somewhere. This is the root-of-trust (RoT) concept. This talk will elaborate on the RoT-concept, the various types of RoTs (one example being the TPM chip found in modern computers), how they can be used, typical implementations mistakes that can happen from the developer side and why you need one if you are deploying devices in IoT.\r\n-----------------------------------\r\nTalk 3: What hit my webservice with 408?! - Paweł Krzywicki\r\n\r\nOn a windy, cold night, a webservice hosted on a popular cloud provider was struck by a mysterious http request and surprisingly did not recover for half an hour. That event triggered an investigation that quickly reminded that if you start hosting a publicly available webservice, you immediately become a target for a number of scanners that relentlessly crawl the internet trying to find vulnerabilities.\r\nThis lightning talk discusses a real-world story of a certain message from such a massive scan that instead of failing gracefully with 404 response code (Not found) started to cause 408 (Request timeout), which poses a bigger threat of Denial of Service. \r\nThe investigation of the message showcased different methods of logging such suspects - both using cloud services, as well as Java application based - when they fail and when they succeed to log all the details required to reproduce the issue. Surprisingly, it also offered a way to optimize the load on the hosting infrastructure and offered an interesting insight into modern scans, as well as individual malware campaigns launched.\r\nThe talk includes also a demo of quick analyses of logged http requests\r\n-----------------------------------\r\nTalk 4: RSA encryption in 10 minutes - Fredrik Meyer\r\n\r\nAlways wanted to understand the idea and mathematics behind RSA encryption, but never had the will to read the Wikipedia article? In this lightning talk, I'll explain RSA encryption in an understandable way.\r\n-----------------------------------\r\nTalk 5: I thought we did things right until I went looking - Security errors in Norwegian websites - Håvard H. Pettersen\r\n\r\nHave you ever thought about bug hunting? Well, here is how I got started, and how I ended up finding security issues in a couple of Norwegian companies' online systems.\r\n\r\n", + "startsAt": "2019-06-19T13:40:00", + "endsAt": "2019-06-19T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "ffb252b1-8907-4b58-9d69-a0b01c16678e", + "name": "Kristian Bognæs" + }, + { + "id": "93cec660-9cdb-4ee8-af10-4eae804e3557", + "name": "Paweł Krzywicki" + }, + { + "id": "e9700b00-6c05-4841-9317-0b20781cee07", + "name": "Fredrik Meyer" + }, + { + "id": "2a137841-ee81-4050-94a0-21dab6b531f3", + "name": "Håvard H. Pettersen" + }, + { + "id": "e780f76e-9b1e-48e6-933b-8dbdbf99f0d7", + "name": "Ole Andreas Rydland" + }, + { + "id": "6cc11479-8b96-442d-b03a-8fe949c72888", + "name": "Ole Alexander Pihl Konstad" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + { + "id": "99316", + "title": "Crash, Burn, Report", + "description": "With the launch of the Reporting API any browser that visits your site can automatically detect and alert you to a whole heap of problems with your application. DNS not resolving? Serving an invalid certificate? Got a redirect loop, using a soon to be deprecated API or any one of countless other problems, they can all be detected and reported with no user action, no agents, no code to deploy. You have one of the most extensive and powerful monitoring platforms in existence at your disposal, millions of browsers. Let's look at how to use them.\r\n\r\nIn this talk we'll look at how to configure the browser to send you reports when things go wrong. These are brand new capabilities the likes of which we've haven't seen before and they're already supported in the world's most popular browser, Google Chrome. We'll look at how to receive reports and how to make use of them after having the browser do the hard work.", + "startsAt": "2019-06-19T15:00:00", + "endsAt": "2019-06-19T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e9c64362-6194-409c-85da-45c8fd40abd6", + "name": "Scott Helme" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + { + "id": "98683", + "title": "Making IoT: An Intro for Web Devs", + "description": "For those of us used to solving problems with software, it can be difficult to branch out to solving problems with technology in the physical world. However, internet connected hardware projects can open up what we build and how people interact with technology in ways that's worth the struggle. In this session, Kristina will go from soldering an LED, connecting it to the internet, and creating a simple web app to monitor sensor data. She'll provide an overview of the different options available and give some pointers for people getting started.", + "startsAt": "2019-06-19T16:20:00", + "endsAt": "2019-06-19T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "945233b4-c513-494c-bcae-c2ccebe07dd5", + "name": "Kristina Durivage" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + { + "id": "97648", + "title": "Indexing and searching NuGet.org with Azure Functions and Search", + "description": "Which NuGet package was that type in again? In this session, let's build a \"reverse package search\" that helps finding the correct NuGet package based on a public type.\r\n\r\nTogether, we will create a highly-scalable serverless search engine using Azure Functions and Azure Search that performs 3 tasks: listening for new packages on NuGet.org (using a custom binding), indexing packages in a distributed way, and exposing an API that accepts queries and gives our clients the best result. Expect lots of live coding!", + "startsAt": "2019-06-19T17:40:00", + "endsAt": "2019-06-19T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "b425717f-25c3-4863-b893-8f8bb943825a", + "name": "Maarten Balliauw" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4486, + "name": "Room 8", + "sessions": [ + { + "id": "98771", + "title": "A Primer on Functional Programming", + "description": "Functional programming languages are gaining in popularity. If you’ve worked in object-oriented languages, you might be baffled at how they work. Maybe hearing the word “recursion” makes you want to scream. Or maybe you’ve just heard the hype and want to know what the hype is about.\r\n\r\nIn this talk, we will briefly explain what functional languages are, and go into some examples of tasks that these languages are suited for. We will look at the major languages in use today and see how they work. We'll see some of the things they have in common, and the many things that make them distinctive. Finally, we’ll offer some suggestions on how to dive into learning these and using them on your own projects.", + "startsAt": "2019-06-19T10:20:00", + "endsAt": "2019-06-19T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "97e1c796-8bf6-468b-b246-0efc6979b9e7", + "name": "Sarah Withee" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + { + "id": "99522", + "title": "Dungeons, Dragons and Functions", + "description": "Dungeons & Dragons, or D&D, is the grand-daddy of all role playing games. While playing D&D is great fun, the rules are a bit daunting for the beginner. The basic rulebook, the PHB, clocks in at a solid 300 pages, and can be extended with multiple additional rule sets. This should come as no surprise to software engineers: this is, after all, documentation for a system that models a complex domain, and has been in use for over 40 years now, going through numerous redesigns over time.\r\n\r\nAs such, D&D rules make for a great exercise in domain modelling. In this talk, I will take you along my journey attempting to tame that monster. We will use no magic, but a weapon imbued with great power, F#; practical tips and tricks for the Adventurer on the functional road will be shared. So... roll 20 for initiative, and join us for an epic adventure in domain modeling with F#!", + "startsAt": "2019-06-19T11:40:00", + "endsAt": "2019-06-19T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "94f08182-51a1-4b1c-960a-2908b58a1c61", + "name": "Mathias Brandewinder" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + { + "id": "79915", + "title": "What is the point of Microsoft? 3.0", + "description": "In 2015, at DDD SouthWest, I first considered what was the point of Microsoft, after it's demise was predicted by many wise beards, and some doubted whether they would be developing with Microsoft tools for much longer.\r\n\r\nIn 2017, I revisited the topic for Get.NET in Łódź. By that time, Windows Mobile was if not dead, mortally wounded and Microsoft was busy open sourcing almost every new project.\r\n\r\nAnother two years on, when the Microsoft market capitalization exceeded that of Apple for most of December 2018 (as well as exceeding Google, Facebook and Amazon) it's time to look at what lies in the future for Microsoft*, and whether by 2020 this session will no longer have a relevance.\r\n\r\nThis will be a subjective stroll across the competitive landscape of technology, how that affects developers and whether Microsoft will remain relevant in cloud, hardware, software and development environments.\r\n\r\n*and github.com", + "startsAt": "2019-06-19T13:40:00", + "endsAt": "2019-06-19T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "1bcc3b50-a8da-47c3-850e-2fc5bde34edf", + "name": "Liam Westley" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + { + "id": "99532", + "title": "The Functional Toolkit", + "description": "The techniques and patterns used in functional programming are very different from object-oriented programming, and when you are just starting out it can be hard to know how they all fit together. \r\n\r\nIn this big picture talk for FP beginners, I'll present some of the common tools that can be found in a functional programmer's toolbelt; tools such as \"map\", \"apply\", \"bind\", and \"sequence\". What are they? Why are they important? How are they used in practice? And how do they relate to scary sounding concepts like functors, monads, and applicatives?", + "startsAt": "2019-06-19T15:00:00", + "endsAt": "2019-06-19T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "89335661-3092-4afa-b53f-3d203cafa2a1", + "name": "Scott Wlaschin" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + { + "id": "98899", + "title": "Terraforming Azure", + "description": "If you are working with resources in Azure and don’t know Terraform, chances are that will benefit from this session. Terraform has made a lot of progress lately in terms of Azure-support and is ready to help you improve how you manage your Azure resources. \r\n\r\nThis session will introduce Terraform and give you a primer on how to use it. Azure Resource Manager is one of the alternatives to Terraform, and you will learn about how they differ and help you choose the right tool. The session will feature a mix live-coding and slides. You will get the most out of the presentation if you know a bit about Azure or Azure Resource Manager.\r\n\r\nI will share my experience with Terraform and Azure Resource Manager, which hopefully will make it easier to understand what might be the right tool in your context. Terraform is not perfect, and you’ll learn about some of the challenges you might face.", + "startsAt": "2019-06-19T16:20:00", + "endsAt": "2019-06-19T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "c0d7c2e8-1f0b-4586-b3a0-dbd18227ca62", + "name": "Torstein Nicolaysen" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + { + "id": "98095", + "title": "Functional Patterns for the Object Oriented", + "description": "Object-oriented languages have during the last decade introduced a number of features originating from the functional programming domain. Most notable are the introduction of lambda expressions and stream processing libraries like LINQ in C# and the Stream API in Java, but other features are emerging as well. C# 7.0 introduced the concepts of tuples and pattern matching, both of which have for a long time been fundamental features of functional languages like Haskell. Why do people consider these features to be functional? And why are people with a background in functional programming thrilled to see these features introduced in the object-oriented world? This talk will focus on a set of case studies that illustrate how functional patterns are typically applied in Haskell and how solutions based on those patterns differ from the traditional OO approach. The talk does not assume a background in functional programming, but hold on to your hat and be prepared for something different!", + "startsAt": "2019-06-19T17:40:00", + "endsAt": "2019-06-19T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "212fd3b5-294e-4624-85f0-40fb54abb1c9", + "name": "Øystein Kolsrud" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4487, + "name": "Room 9", + "sessions": [ + { + "id": "74817", + "title": "DevOps ICU: Improving DevOps Results by (Correctly) Integrating UX", + "description": "UX is driving you crazy, a black throwing off timelines and killing ideas. UX doesn’t seem Lean or Agile. Can’t anybody make wireframes? Can’t we circumvent or exclude these people? \r\n\r\nDevOps is truly about so much more than how developers connect with IT, how infrastructure is managed, and how frameworks can be improved. It’s about recognizing how many teams are truly involved in the software development process and finding better ways to make sure everybody is at the table.\r\n\r\nThis session will explain how the UX process fits into Agile; saves companies money; augments DevOps goals; and increases customer satisfaction.", + "startsAt": "2019-06-19T10:20:00", + "endsAt": "2019-06-19T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "149f7477-e1e8-4db1-a752-e0eee3903306", + "name": "Debbie Levitt" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + { + "id": "98986", + "title": "Shiny objects are cool, but so is building products people use", + "description": "Technology is changing constantly, keeping us on our toes with new frameworks, features, tools, and hardware being released and improved. It gives us new choices and decisions to make that affect our product portfolio, our company’s success, our colleagues, our customers, and our bottom line. But what happens when we give in to all this change and start chasing after all these shiny objects without any sort of strategy or direction? We’ll take a look at the impacts of shiny object syndrome along side real world examples pulled from my experiences in large companies and startups. You’ll leave with a better understanding of how your decisions impact your tech, your company, and your customers and a set of questions to ask as you make these decisions.", + "startsAt": "2019-06-19T11:40:00", + "endsAt": "2019-06-19T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "4f67f397-56c7-41f8-8c03-958b6846d0c5", + "name": "Jenna Pederson" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + { + "id": "98352", + "title": "We are the guardians of our future", + "description": "We wake up one day in the middle of a real episode of Person of Interest, Black Mirror or George Orwell's 1984. \r\nHow did this happen? Who created these AI systems? Surely they should have understood...", + "startsAt": "2019-06-19T13:40:00", + "endsAt": "2019-06-19T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "cb70e0f2-0f0b-4b8f-b3f4-a9326309a1b2", + "name": "Tess Ferrandez-Norlander" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + { + "id": "97335", + "title": "Code Review Etiquettes 101", + "description": "On most software projects, developers spend a good chunk of their time doing code reviews. These are a great opportunity to provide positive and impactful feedback. More often than not it is up to the person whose code is under review to read and interpret code review comments, which makes it very important to consider the structure, tone and value of these comments. Things as simple as saying \"we could change this\" instead of \"you should change this\" and asking for feedback on a suggestion (e.g.: \"I think this could be implemented using tool X. What are your thoughts on that?\") go a long way in ensuring that the comment and the reviewer are received in a positive light. In this talk I will share code review practices that I have found helpful during my tenure as a software engineer.", + "startsAt": "2019-06-19T15:00:00", + "endsAt": "2019-06-19T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "dc7f3459-13dc-447d-a300-32e39fbe99e7", + "name": "Janani Subbiah" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + { + "id": "98096", + "title": "Turing's Toy - The story of a mathematical idea that changed the world", + "description": "Alan Turing's paper from 1936, where he describes what came to be known as the Turing machine, is one of the truly pivotal papers in the history of computer science. Turing's description of what he called the \"universal machine\" is frequently referred to as the starting point of the technological revolution we today call the computer. He wrote his paper during a time when the world was going through a dramatic set of upheavals both scientifically, technologically and politically, and his work is a prime example of how basic research of a seemingly esoteric problem can have far reaching consequences.\r\n\r\nAre you interested in learning more about Turing's ground breaking accomplishment? Then join me and hear the fascinating story of the Turing machine! I will describe both its historical context and its implications, but first and foremost I will explain the details of Turing's fictional machine and what he was trying to accomplish with it. This is the story of how a mathematician thought outside the box and accidentally changed the course of history! ", + "startsAt": "2019-06-19T16:20:00", + "endsAt": "2019-06-19T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "212fd3b5-294e-4624-85f0-40fb54abb1c9", + "name": "Øystein Kolsrud" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + { + "id": "97147", + "title": "Three Rewrites, One Startup - An Architect’s Journey", + "description": "Picture this: you're a senior engineer at your company who, one day, is thrust into the architect role. Suddenly, you're having to think about things that you've never thought about - what's the difference between a microservice and a service bus? How do I design a scalable system for tomorrow without overengineering today?\r\n\r\nBetter yet, if you're at a startup, do all that - and still be responsible for code reviews, development, and coaching of junior devs. How can a fledgling architect possibly \"do it all\" - and more importantly, do it well?\r\n\r\nLuckily, someone has gone down that path (and is still going)... and he's ready to share his story.\r\n\r\nAttend Spencer's talk and hear about how he, as a senior engineer, had to grow into the architect role. We'll discuss the problems faced, the critical \"decision points\" he made from an architecture standpoint, the results of those choices, and how he helped guide the business through three architectural rewrites - all in a span of four years!", + "startsAt": "2019-06-19T17:40:00", + "endsAt": "2019-06-19T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "583e8f08-8316-4ed2-afdf-4cd091e44564", + "name": "Spencer Schneidenbach" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4488, + "name": "Room 10", + "sessions": [ + { + "id": "78157", + "title": "Workshop: Apache Kafka and KSQL in Action : Let’s Build a Streaming Data Pipeline! 1/2", + "description": "Have you ever thought that you needed to be a programmer to do stream processing and build streaming data pipelines? Think again! Apache Kafka is a distributed, scalable, and fault-tolerant streaming platform, providing low-latency pub-sub messaging coupled with native storage and stream processing capabilities. Integrating Kafka with RDBMS, NoSQL, and object stores is simple with Kafka Connect, which is part of Apache Kafka. KSQL is the open-source SQL streaming engine for Apache Kafka, and makes it possible to build stream processing applications at scale, written using a familiar SQL interface.\r\n\r\nIn this workshop you will hear the architectural reasoning for Apache Kafka and the benefits of real-time integration, and then build a streaming data pipeline using nothing but your bare hands, Kafka Connect, and KSQL.\r\n\r\nGasp as we filter events in real time! Be amazed at how we can enrich streams of data with data from RDBMS! Be astonished at the power of streaming aggregates for anomaly detection!\r\n\r\nPrerequisite \r\nParticipants must have their own laptop and complete the prerequisite steps detailed here PRIOR TO THE WORKSHOP:https://github.com/confluentinc/demo-scene/blob/master/ksql-workshop/pre-requisites.adoc.\r\n\r\nComputer Setup\r\nFor reasons of compatibility, we recommend the use of Mac or Linux for the workshop. 8GB memory is required. Knowledge of SQL is assumed. Participants will benefit from existing knowledge of the concepts of Kafka (topics, streaming, etc).", + "startsAt": "2019-06-19T13:40:00", + "endsAt": "2019-06-19T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e16e10b7-f905-4c95-afb6-6d54a47f577e", + "name": "Robin Moffatt" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + { + "id": "128710", + "title": "Workshop: Apache Kafka and KSQL in Action : Let’s Build a Streaming Data Pipeline! Part 2/2", + "description": "Have you ever thought that you needed to be a programmer to do stream processing and build streaming data pipelines? Think again! Apache Kafka is a distributed, scalable, and fault-tolerant streaming platform, providing low-latency pub-sub messaging coupled with native storage and stream processing capabilities. Integrating Kafka with RDBMS, NoSQL, and object stores is simple with Kafka Connect, which is part of Apache Kafka. KSQL is the open-source SQL streaming engine for Apache Kafka, and makes it possible to build stream processing applications at scale, written using a familiar SQL interface.\r\n\r\nIn this workshop you will hear the architectural reasoning for Apache Kafka and the benefits of real-time integration, and then build a streaming data pipeline using nothing but your bare hands, Kafka Connect, and KSQL.\r\n\r\nGasp as we filter events in real time! Be amazed at how we can enrich streams of data with data from RDBMS! Be astonished at the power of streaming aggregates for anomaly detection!\r\n\r\nPrerequisite \r\nParticipants must have their own laptop and complete the prerequisite steps detailed here PRIOR TO THE WORKSHOP:https://github.com/confluentinc/demo-scene/blob/master/ksql-workshop/pre-requisites.adoc.\r\n\r\nComputer Setup\r\nFor reasons of compatibility, we recommend the use of Mac or Linux for the workshop. 8GB memory is required.Knowledge of SQL is assumed. Participants will benefit from existing knowledge of the concepts of Kafka (topics, streaming, etc).", + "startsAt": "2019-06-19T15:00:00", + "endsAt": "2019-06-19T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e16e10b7-f905-4c95-afb6-6d54a47f577e", + "name": "Robin Moffatt" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + { + "id": "98822", + "title": "Workshop: Explore the fundamentals of Rust by creating your own Synthesizer 1/2", + "description": "Rust is a reliable systems programming language providing bare-metal performance in a modern wrapping. It guarantees memory and thread-safety without garbage collection, offers great tooling and an amazing community — in fact, Rust has been voted the most loved programming language according to the Stack Overflow Developer Survey three years in a row. The language is experiencing rapid adaptation in multiple industries ranging from game development to backend systems.\r\n\r\nIn this workshop, we will explore Rust and create a simple synthesizer that can be played with your computer keyboard. We will also implement rudimentary sound effects. The goal of this workshop is to learn some of the basics of Rust through a hands-on project, and no prior knowledge of Rust or audio processing is required.", + "startsAt": "2019-06-19T16:20:00", + "endsAt": "2019-06-19T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "eafc0cc1-0b84-439c-b09a-dc77b4b97459", + "name": "Thomas Tøkje" + }, + { + "id": "e3c7f994-2b3b-493a-b982-811a1a393bc2", + "name": "John-Olav Storvold" + }, + { + "id": "71e76d10-4a45-4a3a-b0af-2f86611bd8b7", + "name": "Sverre Bjørke" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + { + "id": "128712", + "title": "Workshop: Explore the fundamentals of Rust by creating your own Synthesizer - Part 2/2", + "description": "Rust is a reliable systems programming language providing bare-metal performance in a modern wrapping. It guarantees memory and thread-safety without garbage collection, offers great tooling and an amazing community — in fact, Rust has been voted the most loved programming language according to the Stack Overflow Developer Survey three years in a row. The language is experiencing rapid adaptation in multiple industries ranging from game development to backend systems.\r\n\r\nIn this workshop, we will explore Rust and create a simple synthesizer that can be played with your computer keyboard. We will also implement rudimentary sound effects. The goal of this workshop is to learn some of the basics of Rust through a hands-on project, and no prior knowledge of Rust or audio processing is required.", + "startsAt": "2019-06-19T17:40:00", + "endsAt": "2019-06-19T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "71e76d10-4a45-4a3a-b0af-2f86611bd8b7", + "name": "Sverre Bjørke" + }, + { + "id": "e3c7f994-2b3b-493a-b982-811a1a393bc2", + "name": "John-Olav Storvold" + }, + { + "id": "eafc0cc1-0b84-439c-b09a-dc77b4b97459", + "name": "Thomas Tøkje" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4504, + "name": "Room 11", + "sessions": [ + { + "id": "98419", + "title": "Workshop: Rethinking API's with GraphQL 1/2", + "description": "GraphQL is an open-source data query language for API's, and a runtime for fulfilling those queries with existing data. It represent a new way to think about API's compared to traditional methods like REST. \r\n\r\nThis workshop will give you hands-on experience using GraphQL to master common API operations. We will cover basic topics like fetching data from a GraphQL server using queries and mutations, writing schemas to describe what data can be queried and getting to know the schema type system. You can choose to do the hands-on exercises in either .NET or NodeJS. At the end of the workshop you will be well equipped to start implementing a new, or to query an existing GraphQL API.", + "startsAt": "2019-06-19T10:20:00", + "endsAt": "2019-06-19T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "12fec17b-ad6e-48ac-a872-19cb80eda7fe", + "name": "Simen Støa" + }, + { + "id": "de9d6af0-9ac3-48f6-85f2-5b0bc9343d6e", + "name": "Emil Staurset" + }, + { + "id": "cfa86371-d65f-494c-8a03-d74373cbdfd5", + "name": "Sigurd Hagen Falk" + }, + { + "id": "7ed70346-dd77-4ad8-b551-369972631487", + "name": "Thorstein Thorrud" + } + ], + "categories": [], + "roomId": 4504, + "room": "Room 11" + }, + { + "id": "128709", + "title": "Workshop: Rethinking API's with GraphQL 2/2", + "description": "GraphQL is an open-source data query language for API's, and a runtime for fulfilling those queries with existing data. It represent a new way to think about API's compared to traditional methods like REST. \r\n\r\nThis workshop will give you hands-on experience using GraphQL to master common API operations. We will cover basic topics like fetching data from a GraphQL server using queries and mutations, writing schemas to describe what data can be queried and getting to know the schema type system. You can choose to do the hands-on exercises in either .NET or NodeJS. At the end of the workshop you will be well equipped to start implementing a new, or to query an existing GraphQL API.", + "startsAt": "2019-06-19T11:40:00", + "endsAt": "2019-06-19T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "12fec17b-ad6e-48ac-a872-19cb80eda7fe", + "name": "Simen Støa" + }, + { + "id": "cfa86371-d65f-494c-8a03-d74373cbdfd5", + "name": "Sigurd Hagen Falk" + }, + { + "id": "de9d6af0-9ac3-48f6-85f2-5b0bc9343d6e", + "name": "Emil Staurset" + }, + { + "id": "7ed70346-dd77-4ad8-b551-369972631487", + "name": "Thorstein Thorrud" + } + ], + "categories": [], + "roomId": 4504, + "room": "Room 11" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4489, + "name": "Expo", + "sessions": [ + { + "id": "85411", + "title": "Keynote: Leadership Guide for the Reluctant Leader", + "description": "Regardless of the technology you know, regardless of the job title you have, you have amazing potential to impact your workplace, community, and beyond.\r\n\r\nIn this talk, I’ll share a few candid stories of my career failures… I mean… learning opportunities. We’ll start by debunking the myth that leadership == management. Next, we’ll talk about some the attributes, behaviors and skills of good leaders. Last, we’ll cover some practical steps and resources to accelerate your journey.\r\n\r\nYou’ll walk away with some essential leadership skills I believe anyone can develop, and a good dose of encouragement to be more awesome!", + "startsAt": "2019-06-19T09:00:00", + "endsAt": "2019-06-19T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "3884cc4d-8364-4316-9b9a-e16561d87af3", + "name": "David Neal" + } + ], + "categories": [], + "roomId": 4489, + "room": "Expo" + } + ], + "hasOnlyPlenumSessions": false + } + ], + "timeSlots": [ + { + "slotStart": "09:00:00", + "rooms": [ + { + "id": 4489, + "name": "Expo", + "session": { + "id": "85411", + "title": "Keynote: Leadership Guide for the Reluctant Leader", + "description": "Regardless of the technology you know, regardless of the job title you have, you have amazing potential to impact your workplace, community, and beyond.\r\n\r\nIn this talk, I’ll share a few candid stories of my career failures… I mean… learning opportunities. We’ll start by debunking the myth that leadership == management. Next, we’ll talk about some the attributes, behaviors and skills of good leaders. Last, we’ll cover some practical steps and resources to accelerate your journey.\r\n\r\nYou’ll walk away with some essential leadership skills I believe anyone can develop, and a good dose of encouragement to be more awesome!", + "startsAt": "2019-06-19T09:00:00", + "endsAt": "2019-06-19T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "3884cc4d-8364-4316-9b9a-e16561d87af3", + "name": "David Neal" + } + ], + "categories": [], + "roomId": 4489, + "room": "Expo" + }, + "index": 11 + } + ] + }, + { + "slotStart": "10:20:00", + "rooms": [ + { + "id": 4479, + "name": "Room 1", + "session": { + "id": "98819", + "title": "An introduction to Machine Learning using LEGO", + "description": "Where do you start when you want to learn Machine Learning? Do you start by learning some advanced algorithms or perhaps a Machine Learning framework? In this talk, I will show an alternative approach on how to get started with Machine Learning by using a LEGO car as a model. By using Machine Learning, we can make the LEGO car steer autonomously!\r\n\r\nIn the process of making a LEGO car steer autonomously I will go through the following topics:\r\n- What is Machine Learning?\r\n- Can we make the LEGO car steer autonomously without Machine Learning?\r\n- How does the basic theory behind Machine Learning work?\r\n- How do we connect theory to LEGO bricks?\r\n\r\nThe aim of this talk is not to make you an expert in Machine Learning, however, it will hopefully inspire you to investigate and get familiar with Machine Learning in a playful and simple way.", + "startsAt": "2019-06-19T10:20:00", + "endsAt": "2019-06-19T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "7e84a6a9-f685-4cfa-a31d-9c00ce592b79", + "name": "Jeppe Tornfeldt Sørensen" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + "index": 0 + }, + { + "id": 4480, + "name": "Room 2", + "session": { + "id": "97632", + "title": "C# and Rust: combining managed and unmanaged code without sacrificing safety", + "description": "Why would you ever want to introduce unmanaged code into your managed codebase when recent versions of C# have made writing high performance code in .NET more accessible than ever before? While C# has been pushing downwards into the realm of \"systems programming\", Rust, a language that already operates in this space, has been pushing upwards. The result isn't a competition where one language must emerge as more universally applicable than the other. It's a broader set of cases where C# and Rust can work together, and integrating them effectively is more idiomatic thanks to this broadening of scope.\r\n\r\nWhen we set out in 2018 to rebuild the storage engine for our log server, Seq, we decided to complement our existing C# codebase with a new one written in Rust. In this talk we'll look at why you might want to add unmanaged code to your managed codebase, using Seq as an example. We'll explore how to use the tools that .NET and Rust give us to design and build a safe and robust foreign function interface. In the end we'll have a new perspective on the implicit safety contracts we're expected to uphold in our purely managed codebases.", + "startsAt": "2019-06-19T10:20:00", + "endsAt": "2019-06-19T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "0029ba03-068c-44eb-bd23-3cdd17fc725a", + "name": "Ashley Mannix" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + "index": 1 + }, + { + "id": 4481, + "name": "Room 3", + "session": { + "id": "77259", + "title": "I'm Going To Make You Stop Hating CSS.", + "description": "As a formalized language, CSS is over 20 years old and has spent much of that time being maligned by the people who use it. Browser inconsistencies, changing specifications and general weirdness have combined to create this weird pseudo-language that you'd rather avoid.\r\n\r\nUNTIL TODAY. With modern specs and tooling, CSS has never been more straightforward and less reliant on hacks. In this talk, Lemon will show you some common traps people fall in, as well as some general strategies for making a layout grid you can proud to build and confident in releasing.", + "startsAt": "2019-06-19T10:20:00", + "endsAt": "2019-06-19T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f4f1eb31-8574-4e8a-a94a-ee0aef8c28d5", + "name": "Lemon 🍋" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + "index": 2 + }, + { + "id": 4482, + "name": "Room 4", + "session": { + "id": "83948", + "title": "10 years of microservices at FINN.no - and we still haven’t slain that dragon!", + "description": "At FINN.no we started splitting up the monolith nearly ten years ago. Even though we have a few hundred services, major parts of the monolith is still running. \r\n\r\nHow did we approach it? What have we learned? Why is the monolithic dragon still here?", + "startsAt": "2019-06-19T10:20:00", + "endsAt": "2019-06-19T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "788869df-4013-4126-92a6-8e900cd67013", + "name": "Henning Spjelkavik" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + "index": 3 + }, + { + "id": 4483, + "name": "Room 5", + "session": { + "id": "97582", + "title": "Building APIs Rapidly with Azure Functions", + "description": "APIs are what makes the Internet go around. Every SaaS, data driven and on-demand kitten business exposes their data over an external or internal API. Which means you need one too, right? Of course you do.\r\nCreating an API that conforms with OpenAPI standards, can scale up and out, can be extended easily, and can be easily maintained is the Nirvana of API architecture. This is exactly the promise of building an API with Azure Functions, and it is super fast too! \r\nIn this session, you will learn to quickly create a full blown API using Azure Functions, create a proxy to forward requests, adhere to OpenAPI standards, easily extend and more. At the end of the talk we will have built an API that is (almost) production ready straight away. We then compare this process to other API frameworks to get the real world picture. \t\r\n", + "startsAt": "2019-06-19T10:20:00", + "endsAt": "2019-06-19T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f99fa878-6176-4ff4-b151-c717fa5daf0c", + "name": "Lars Klint" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + "index": 4 + }, + { + "id": 4484, + "name": "Room 6", + "session": { + "id": "86348", + "title": "Unity 101 for C# Developers", + "description": "Recommended by Microsoft for creating mixed reality experiences for the Hololens, Unity has transcended its beginnings as a cross-platform game engine.\r\n\r\nSo whether you are looking to create a 3D game for mobile, or have your sights set on a virtual reality experience for the Oculus Rift, Unity is a tool you'll want to learn.\r\nOne surprise for C# developers getting started with Unity is the level of integration with Visual Studio and how simple it is to add C# code to manipulate their Unity creations.\r\n\r\nIn this demo led session, we’ll go back to basics with Unity, creating a simple 3D game with realistic physics, textures and explosions. We’ll look at the fantastic Visual Studio integration and how cohesively the two editors work together.\r\n\r\nFinally, we’ll look at a more complex 3D experience and how to use Unity's networking features to allow different users to interact in a 3D world.\r\n\r\nKeeping the best news for last: Unity is royalty free until you’re earning $100,000. So if you like the idea of becoming wildly rich from making immersive 3D experiences, this is the talk for you! ", + "startsAt": "2019-06-19T10:20:00", + "endsAt": "2019-06-19T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "ef4df68d-9bdc-471d-aff0-075c77c4a424", + "name": "Andy Clarke" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + "index": 5 + }, + { + "id": 4485, + "name": "Room 7", + "session": { + "id": "99090", + "title": "Developing privacy", + "description": "In this day and age, privacy is important to our customers, and it should be important to you as well! In some cases, you're legally obligated to ensure your user's privacy and to protect their information, but it's increasingly becoming The Right Thing To Do (tm) as well. So how do we do it? Which traps lie in these waters? How do we, as developers, build solutions that protect our users from the start and all the way into the core of our applications. We'll go through patterns and techniques you can directly apply in your work, we'll talk about questions you should be asking your business and help you make privacy a feature of your system and not an afterthought. Without making your life needlessly difficult. ", + "startsAt": "2019-06-19T10:20:00", + "endsAt": "2019-06-19T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "fb75b901-4842-4858-ba35-8c370db0af14", + "name": "Glenn F. Henriksen" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + "index": 6 + }, + { + "id": 4486, + "name": "Room 8", + "session": { + "id": "98771", + "title": "A Primer on Functional Programming", + "description": "Functional programming languages are gaining in popularity. If you’ve worked in object-oriented languages, you might be baffled at how they work. Maybe hearing the word “recursion” makes you want to scream. Or maybe you’ve just heard the hype and want to know what the hype is about.\r\n\r\nIn this talk, we will briefly explain what functional languages are, and go into some examples of tasks that these languages are suited for. We will look at the major languages in use today and see how they work. We'll see some of the things they have in common, and the many things that make them distinctive. Finally, we’ll offer some suggestions on how to dive into learning these and using them on your own projects.", + "startsAt": "2019-06-19T10:20:00", + "endsAt": "2019-06-19T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "97e1c796-8bf6-468b-b246-0efc6979b9e7", + "name": "Sarah Withee" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + "index": 7 + }, + { + "id": 4487, + "name": "Room 9", + "session": { + "id": "74817", + "title": "DevOps ICU: Improving DevOps Results by (Correctly) Integrating UX", + "description": "UX is driving you crazy, a black throwing off timelines and killing ideas. UX doesn’t seem Lean or Agile. Can’t anybody make wireframes? Can’t we circumvent or exclude these people? \r\n\r\nDevOps is truly about so much more than how developers connect with IT, how infrastructure is managed, and how frameworks can be improved. It’s about recognizing how many teams are truly involved in the software development process and finding better ways to make sure everybody is at the table.\r\n\r\nThis session will explain how the UX process fits into Agile; saves companies money; augments DevOps goals; and increases customer satisfaction.", + "startsAt": "2019-06-19T10:20:00", + "endsAt": "2019-06-19T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "149f7477-e1e8-4db1-a752-e0eee3903306", + "name": "Debbie Levitt" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + "index": 8 + }, + { + "id": 4504, + "name": "Room 11", + "session": { + "id": "98419", + "title": "Workshop: Rethinking API's with GraphQL 1/2", + "description": "GraphQL is an open-source data query language for API's, and a runtime for fulfilling those queries with existing data. It represent a new way to think about API's compared to traditional methods like REST. \r\n\r\nThis workshop will give you hands-on experience using GraphQL to master common API operations. We will cover basic topics like fetching data from a GraphQL server using queries and mutations, writing schemas to describe what data can be queried and getting to know the schema type system. You can choose to do the hands-on exercises in either .NET or NodeJS. At the end of the workshop you will be well equipped to start implementing a new, or to query an existing GraphQL API.", + "startsAt": "2019-06-19T10:20:00", + "endsAt": "2019-06-19T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "12fec17b-ad6e-48ac-a872-19cb80eda7fe", + "name": "Simen Støa" + }, + { + "id": "de9d6af0-9ac3-48f6-85f2-5b0bc9343d6e", + "name": "Emil Staurset" + }, + { + "id": "cfa86371-d65f-494c-8a03-d74373cbdfd5", + "name": "Sigurd Hagen Falk" + }, + { + "id": "7ed70346-dd77-4ad8-b551-369972631487", + "name": "Thorstein Thorrud" + } + ], + "categories": [], + "roomId": 4504, + "room": "Room 11" + }, + "index": 10 + } + ] + }, + { + "slotStart": "11:40:00", + "rooms": [ + { + "id": 4479, + "name": "Room 1", + "session": { + "id": "99028", + "title": "How to Steal an Election", + "description": "In this session I'll demonstrate some of the data science techniques that can be used to influence a population to a particular way of thinking, or to vote in a particular way. With all the talk of collusion in the American, and other, elections I think it's about time we explore the art of the possible in this field, and see just how they might have done it.", + "startsAt": "2019-06-19T11:40:00", + "endsAt": "2019-06-19T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "2a5c6285-1012-49e7-a0f6-1efdeea7dba9", + "name": "Gary Short" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + "index": 0 + }, + { + "id": 4480, + "name": "Room 2", + "session": { + "id": "119373", + "title": "Hidden gems in .NET Core 3", + "description": "You've likely heard about the headline features in .NET Core 3.0 including Blazor, gRPC, and Windows desktop app support, but what else is there?\r\n\r\nThis is a big release so come and see David Fowler and Damian Edwards from the .NET Core team showcase their favorite new features you probably haven't heard about in this demo-packed session.", + "startsAt": "2019-06-19T11:40:00", + "endsAt": "2019-06-19T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "a2c9a4b0-cb47-414a-a7fb-93d0928e77d2", + "name": "Damian Edwards" + }, + { + "id": "b2959d46-2ae9-494b-865c-fb850e37d24a", + "name": "David Fowler" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + "index": 1 + }, + { + "id": 4481, + "name": "Room 3", + "session": { + "id": "97811", + "title": "Web components and micro apps, the web technologies peacekeeper", + "description": "Web development can be a bit tiring with all these new innovative technologies and frameworks we get on a regular basis especially if you have to maintain a product for a long time.\r\n\r\nHowever, web components and micro apps has given us a solution which is framework independent. It allows for decomposition of a big project into smaller, more maintainable parts that can be handled by different teams with different technologies.\r\n\r\nLet's go on a journey to find out how we can unite best technologies to form our enterprise apps.", + "startsAt": "2019-06-19T11:40:00", + "endsAt": "2019-06-19T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "a127e924-82ac-42df-8761-ecb106c8ef61", + "name": "Yaser Adel Mehraban" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + "index": 2 + }, + { + "id": 4482, + "name": "Room 4", + "session": { + "id": "86697", + "title": "Kill Evil Mutants!", + "description": "How good are your tests? Would they still pass if the tested code was changed much? If so, there's probably a problem with your code, your tests, or both!\r\n\r\nMutation Testing helps reveal these cases. It makes changed versions of your code (mutants) and runs your tests against the mutants to \"kill\" them. Survivors, aka \"*evil* mutants\", imply that there are flaws in your code or tests.\r\n\r\nThis talk will tell you how and why to use mutation testing, and how it works, including some examples and tools for popular languages.", + "startsAt": "2019-06-19T11:40:00", + "endsAt": "2019-06-19T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "be5e2221-855b-4294-9e00-dcd97e0e5bab", + "name": "Dave Aronson" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + "index": 3 + }, + { + "id": 4483, + "name": "Room 5", + "session": { + "id": "99256", + "title": "Getting to DDD: Pragmatic or Principled?", + "description": "Domain-Driven Design is a vast topic. There are so many wonderful concepts, philosophies, patterns, practices and techniques to learn and benefit from. Some of the best minds in the industry have been tuning these practices for years to ensure developers are able to implement proven, successful approaches to software design. Domain modeling in particular is very specific with guidance on designing and coordinating the dance between the myriad moving parts in our system. Yet learning the principals of DDD can be daunting for developers who are new to DDD. To encourage and enable more developers to get on the path of DDD, is it reasonable to allow a more pragmatic approach over a principled approach of adhering strictly to DDD guidelines? Should developers be encouraged to start with low hanging fruit which they can quickly benefit from in their software projects while they continue to learn, to gain a deeper understanding of Domain-Driven Design in order to evolve and adapt their practices as they move closer and closer to the beauty we all know that can be achieved with DDD.", + "startsAt": "2019-06-19T11:40:00", + "endsAt": "2019-06-19T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "282a4701-f128-4b1d-bd67-da5d1f8b3eb0", + "name": "Julie Lerman" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + "index": 4 + }, + { + "id": 4484, + "name": "Room 6", + "session": { + "id": "98826", + "title": "Chasing holograms - the future of HoloLens development", + "description": "HoloLens development is a unique beast that is evolving quickly - how is developing applications to be used in the real world different for applications designed for screens?\r\n\r\nLearn the tools and processes required for Mixed Reality development, as well as useful tips and resources for giving your applications more and more understanding of the world around it.\r\nLet's explore the Mixed Reality Toolkit, the features of the next generation of the HoloLens, as well as how cloud services can be utilized for Mixed Reality applications. Last but not least, how does development for the next version of the HoloLens differ from the first?\r\n\r\nAt the end of this talk you will be equipped to tackle HoloLens development and take advantage of the latest features of the device, and related libraries and resources.", + "startsAt": "2019-06-19T11:40:00", + "endsAt": "2019-06-19T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "3e52cb3b-ba18-4766-b9bf-d8306bef9505", + "name": "Scott Leaman" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + "index": 5 + }, + { + "id": 4485, + "name": "Room 7", + "session": { + "id": "97631", + "title": "Adding business logic to your tokens. What could possibly go wrong.", + "description": "When working with an identity servers one of the first things we need to learn is the difference between an Id tokens and access tokens. The fact that we can add additional claims to these tokens may seem nice adding a number of claims that are related to business logic may seem like a great feature for your application you wont need to look up this information all the time. However there needs to be a limit and in fact there is. Adding large numbers of claims to tokens where they don't belong can also cause some problems for your application in the long run and can also be a security risk. \r\n", + "startsAt": "2019-06-19T11:40:00", + "endsAt": "2019-06-19T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "8403871b-1f4f-472b-a4e6-9982a353e1ac", + "name": "Linda Lawton" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + "index": 6 + }, + { + "id": 4486, + "name": "Room 8", + "session": { + "id": "99522", + "title": "Dungeons, Dragons and Functions", + "description": "Dungeons & Dragons, or D&D, is the grand-daddy of all role playing games. While playing D&D is great fun, the rules are a bit daunting for the beginner. The basic rulebook, the PHB, clocks in at a solid 300 pages, and can be extended with multiple additional rule sets. This should come as no surprise to software engineers: this is, after all, documentation for a system that models a complex domain, and has been in use for over 40 years now, going through numerous redesigns over time.\r\n\r\nAs such, D&D rules make for a great exercise in domain modelling. In this talk, I will take you along my journey attempting to tame that monster. We will use no magic, but a weapon imbued with great power, F#; practical tips and tricks for the Adventurer on the functional road will be shared. So... roll 20 for initiative, and join us for an epic adventure in domain modeling with F#!", + "startsAt": "2019-06-19T11:40:00", + "endsAt": "2019-06-19T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "94f08182-51a1-4b1c-960a-2908b58a1c61", + "name": "Mathias Brandewinder" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + "index": 7 + }, + { + "id": 4487, + "name": "Room 9", + "session": { + "id": "98986", + "title": "Shiny objects are cool, but so is building products people use", + "description": "Technology is changing constantly, keeping us on our toes with new frameworks, features, tools, and hardware being released and improved. It gives us new choices and decisions to make that affect our product portfolio, our company’s success, our colleagues, our customers, and our bottom line. But what happens when we give in to all this change and start chasing after all these shiny objects without any sort of strategy or direction? We’ll take a look at the impacts of shiny object syndrome along side real world examples pulled from my experiences in large companies and startups. You’ll leave with a better understanding of how your decisions impact your tech, your company, and your customers and a set of questions to ask as you make these decisions.", + "startsAt": "2019-06-19T11:40:00", + "endsAt": "2019-06-19T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "4f67f397-56c7-41f8-8c03-958b6846d0c5", + "name": "Jenna Pederson" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + "index": 8 + }, + { + "id": 4504, + "name": "Room 11", + "session": { + "id": "128709", + "title": "Workshop: Rethinking API's with GraphQL 2/2", + "description": "GraphQL is an open-source data query language for API's, and a runtime for fulfilling those queries with existing data. It represent a new way to think about API's compared to traditional methods like REST. \r\n\r\nThis workshop will give you hands-on experience using GraphQL to master common API operations. We will cover basic topics like fetching data from a GraphQL server using queries and mutations, writing schemas to describe what data can be queried and getting to know the schema type system. You can choose to do the hands-on exercises in either .NET or NodeJS. At the end of the workshop you will be well equipped to start implementing a new, or to query an existing GraphQL API.", + "startsAt": "2019-06-19T11:40:00", + "endsAt": "2019-06-19T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "12fec17b-ad6e-48ac-a872-19cb80eda7fe", + "name": "Simen Støa" + }, + { + "id": "cfa86371-d65f-494c-8a03-d74373cbdfd5", + "name": "Sigurd Hagen Falk" + }, + { + "id": "de9d6af0-9ac3-48f6-85f2-5b0bc9343d6e", + "name": "Emil Staurset" + }, + { + "id": "7ed70346-dd77-4ad8-b551-369972631487", + "name": "Thorstein Thorrud" + } + ], + "categories": [], + "roomId": 4504, + "room": "Room 11" + }, + "index": 10 + } + ] + }, + { + "slotStart": "13:40:00", + "rooms": [ + { + "id": 4479, + "name": "Room 1", + "session": { + "id": "84070", + "title": "Why databases cry at night?", + "description": "In the dark of the night, if you listen carefully enough, you can hear databases cry. But why? As developers, we rarely consider what happens under the hood of widely used abstractions such as databases. As a consequence, we rarely think about the performance of databases. This is especially true to less widespread, but often very useful NoSQL databases.\r\n\r\nIn this talk we will take a close look at NoSQL database performance, peek under the hood of the most frequently used features to see how they affect performance and discuss performance issues and bottlenecks inherent to all databases.", + "startsAt": "2019-06-19T13:40:00", + "endsAt": "2019-06-19T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f70aa2e2-a961-4c7f-bb77-e5ab82692ee9", + "name": "Michael Yarichuk" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + "index": 0 + }, + { + "id": 4480, + "name": "Room 2", + "session": { + "id": "81621", + "title": "C++: λ Demystified", + "description": "C++11 lambdas brought us lambdas. They open a lot of new possibilities. Frequently asked questions are:\r\n- How are they implemented?\r\n- How do they work?\r\n- How can it affect my daily programming?\r\n- Do they generate a lot of code?\r\n- What can I do with them?\r\n- Where can I use them?\r\n\r\nIn this talk I will answer these questions. With the support of C++ Insights (https://cppinsights.io) we will peak behind the scenes to answer questions about how they are implemented. We will also see how the compiler generated code changes, if we change the lambda itself. This is often interesting for development in constrained applications like the embedded domain.\r\n\r\nNext I will show you application areas of lambdas to illustrate where they can be helpful. For example, how they can help you to write less and with that more unique code.\r\n\r\nAfter the talk, you will have a solid understanding of lambdas in C++. Together with some ideas when and where to use them.", + "startsAt": "2019-06-19T13:40:00", + "endsAt": "2019-06-19T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "0871f66f-f085-4b96-a311-bd7570460627", + "name": "Andreas Fertig" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + "index": 1 + }, + { + "id": 4481, + "name": "Room 3", + "session": { + "id": "83799", + "title": "Responsible JavaScript", + "description": "While the performance of JavaScript engines in browsers have seen continued improvement, the amount of JavaScript we serve increases unabated. We need to use JavaScript more responsibly, which means we must rely on native browser features where prudent, use HTML and CSS when appropriate, and know when too much JavaScript is just that: Too much. \r\n\r\nIn this talk, we'll explore what happens to performance and accessibility when devices are inundated with more JavaScript than they can handle. We'll also dive into some novel techniques you can use to tailor delivery of scripts with respect to a person's device capabilities and network connection quality. When you walk out of this session, you'll be equipped with new knowledge to make your sites as fast as they are beautiful.", + "startsAt": "2019-06-19T13:40:00", + "endsAt": "2019-06-19T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "c3017677-3f20-4b72-8d3f-a2dfa18f4e99", + "name": "Jeremy Wagner" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + "index": 2 + }, + { + "id": 4482, + "name": "Room 4", + "session": { + "id": "100429", + "title": "Chinafy your apps + Lessons you can steal from China", + "description": "Adam Cogan will talk about his experiences getting applications ready for the Chinese market. He has been in the China software world for over 12 years and has seen their ecosystem evolve, and it has been truly amazing. \r\nThere is so much software built in the west, that makes $ in America and $ in Europe but at the same time also has zero users in China. Let’s fix that!", + "startsAt": "2019-06-19T13:40:00", + "endsAt": "2019-06-19T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "7ddee6db-ced0-4c0d-847c-5ea4e1f2a35c", + "name": "Adam Cogan SSW" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + "index": 3 + }, + { + "id": 4483, + "name": "Room 5", + "session": { + "id": "99520", + "title": "Reactive DDD—When Concurrent Waxes Fluent", + "description": "Rarely achieved in past years, fully utilized hardware can now reach the performance, throughput, and scale possible with Reactive software development's responsive, resilient, elastic, and message-driven solutions. As crucial, fiscally-minded technical stakeholders see the urgent need to partner with business leaders in order to create software that delivers critical, differentiating innovations that are in demand to gain and maintain leadership in today's fast-paced commercial markets. The world of distribution, concurrency, latency, and the uncertainty of time-critical results, must be tackled along with complex business challenges. This talk gives practical guidance on creating your software refinement turning point by using Domain-Driven Design to model business-driven solutions with fluent, type-safe, and Reactive properties. Specific attention is given to moving legacy systems that have deep debt to ones that have clear boundaries, deliver explicit and fluent business models, and exploit modern hardware and software architectures.", + "startsAt": "2019-06-19T13:40:00", + "endsAt": "2019-06-19T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "4f5622e6-b5cd-47c7-a088-eb327ff64c53", + "name": "Vaughn Vernon" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + "index": 4 + }, + { + "id": 4484, + "name": "Room 6", + "session": { + "id": "76208", + "title": "DIY Async Message Pump: Lessons from the trenches", + "description": "Building a message pump that consumes and produces messages from queues is simple in theory. In practice, the picture looks a bit different. Over the years, as a contributor for queue adapters for RabbitMQ, Azure Service Bus, Azure Storage Queues, MSMQ, AmazonSQS, Kafka and SQL Server, I've made plenty of mistakes. Now I can teach you how to make those same mistakes!\r\n\r\nIn this talk, we'll see what a robust and reliable message pump with TPL and async looks like so we can avoid it. We'll examine asynchronous synchronization primitives which smarter people than I use to throttle requests, then compare and contrast different queuing technology message pumps to make sure we aren't building to each one's strengths. With this knowledge, if your message pump keeps on pumping for ages in a highly performant way, don't blame me!", + "startsAt": "2019-06-19T13:40:00", + "endsAt": "2019-06-19T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "7e39dc71-6d7a-477a-bcb6-842be6e533b4", + "name": "Daniel Marbach" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + "index": 5 + }, + { + "id": 4485, + "name": "Room 7", + "session": { + "id": "99872", + "title": "Lightning Talks", + "description": "Lightning talks (approx 10-15 minutes each)\r\n\r\nTalk 1: IoT meets IPv6: The Perfect Storm? - Kristian Bognæs\r\n\r\nMirai was for many a wakeup call on what not to do with IoT security. Using default creds, this malware spread itself on thousands of webcams and home routers and became one of the most disruptive DDOS tools in 2016. \r\nNow 3 years on, are we facing a new Mirai with the steady introduction of IPv6 and the number of private devices going online in this space increasing a massive rate? What do we need to consider as developers designing and developing applications for these IoT platforms? \r\nJoin Kristian as he walks you through how IPv6 will affect your security, and what you need to start doing to protect your code and create safer systems.\r\n-----------------------------------\r\nTalk 2: Root-of-trust - What it is and why you need one in IoT - Ole Konstad\r\n\r\nWhether you know it or not, if you have ever implemented any kind of digital security mechanism, your security is rooted somewhere. This is the root-of-trust (RoT) concept. This talk will elaborate on the RoT-concept, the various types of RoTs (one example being the TPM chip found in modern computers), how they can be used, typical implementations mistakes that can happen from the developer side and why you need one if you are deploying devices in IoT.\r\n-----------------------------------\r\nTalk 3: What hit my webservice with 408?! - Paweł Krzywicki\r\n\r\nOn a windy, cold night, a webservice hosted on a popular cloud provider was struck by a mysterious http request and surprisingly did not recover for half an hour. That event triggered an investigation that quickly reminded that if you start hosting a publicly available webservice, you immediately become a target for a number of scanners that relentlessly crawl the internet trying to find vulnerabilities.\r\nThis lightning talk discusses a real-world story of a certain message from such a massive scan that instead of failing gracefully with 404 response code (Not found) started to cause 408 (Request timeout), which poses a bigger threat of Denial of Service. \r\nThe investigation of the message showcased different methods of logging such suspects - both using cloud services, as well as Java application based - when they fail and when they succeed to log all the details required to reproduce the issue. Surprisingly, it also offered a way to optimize the load on the hosting infrastructure and offered an interesting insight into modern scans, as well as individual malware campaigns launched.\r\nThe talk includes also a demo of quick analyses of logged http requests\r\n-----------------------------------\r\nTalk 4: RSA encryption in 10 minutes - Fredrik Meyer\r\n\r\nAlways wanted to understand the idea and mathematics behind RSA encryption, but never had the will to read the Wikipedia article? In this lightning talk, I'll explain RSA encryption in an understandable way.\r\n-----------------------------------\r\nTalk 5: I thought we did things right until I went looking - Security errors in Norwegian websites - Håvard H. Pettersen\r\n\r\nHave you ever thought about bug hunting? Well, here is how I got started, and how I ended up finding security issues in a couple of Norwegian companies' online systems.\r\n\r\n", + "startsAt": "2019-06-19T13:40:00", + "endsAt": "2019-06-19T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "ffb252b1-8907-4b58-9d69-a0b01c16678e", + "name": "Kristian Bognæs" + }, + { + "id": "93cec660-9cdb-4ee8-af10-4eae804e3557", + "name": "Paweł Krzywicki" + }, + { + "id": "e9700b00-6c05-4841-9317-0b20781cee07", + "name": "Fredrik Meyer" + }, + { + "id": "2a137841-ee81-4050-94a0-21dab6b531f3", + "name": "Håvard H. Pettersen" + }, + { + "id": "e780f76e-9b1e-48e6-933b-8dbdbf99f0d7", + "name": "Ole Andreas Rydland" + }, + { + "id": "6cc11479-8b96-442d-b03a-8fe949c72888", + "name": "Ole Alexander Pihl Konstad" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + "index": 6 + }, + { + "id": 4486, + "name": "Room 8", + "session": { + "id": "79915", + "title": "What is the point of Microsoft? 3.0", + "description": "In 2015, at DDD SouthWest, I first considered what was the point of Microsoft, after it's demise was predicted by many wise beards, and some doubted whether they would be developing with Microsoft tools for much longer.\r\n\r\nIn 2017, I revisited the topic for Get.NET in Łódź. By that time, Windows Mobile was if not dead, mortally wounded and Microsoft was busy open sourcing almost every new project.\r\n\r\nAnother two years on, when the Microsoft market capitalization exceeded that of Apple for most of December 2018 (as well as exceeding Google, Facebook and Amazon) it's time to look at what lies in the future for Microsoft*, and whether by 2020 this session will no longer have a relevance.\r\n\r\nThis will be a subjective stroll across the competitive landscape of technology, how that affects developers and whether Microsoft will remain relevant in cloud, hardware, software and development environments.\r\n\r\n*and github.com", + "startsAt": "2019-06-19T13:40:00", + "endsAt": "2019-06-19T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "1bcc3b50-a8da-47c3-850e-2fc5bde34edf", + "name": "Liam Westley" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + "index": 7 + }, + { + "id": 4487, + "name": "Room 9", + "session": { + "id": "98352", + "title": "We are the guardians of our future", + "description": "We wake up one day in the middle of a real episode of Person of Interest, Black Mirror or George Orwell's 1984. \r\nHow did this happen? Who created these AI systems? Surely they should have understood...", + "startsAt": "2019-06-19T13:40:00", + "endsAt": "2019-06-19T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "cb70e0f2-0f0b-4b8f-b3f4-a9326309a1b2", + "name": "Tess Ferrandez-Norlander" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + "index": 8 + }, + { + "id": 4488, + "name": "Room 10", + "session": { + "id": "78157", + "title": "Workshop: Apache Kafka and KSQL in Action : Let’s Build a Streaming Data Pipeline! 1/2", + "description": "Have you ever thought that you needed to be a programmer to do stream processing and build streaming data pipelines? Think again! Apache Kafka is a distributed, scalable, and fault-tolerant streaming platform, providing low-latency pub-sub messaging coupled with native storage and stream processing capabilities. Integrating Kafka with RDBMS, NoSQL, and object stores is simple with Kafka Connect, which is part of Apache Kafka. KSQL is the open-source SQL streaming engine for Apache Kafka, and makes it possible to build stream processing applications at scale, written using a familiar SQL interface.\r\n\r\nIn this workshop you will hear the architectural reasoning for Apache Kafka and the benefits of real-time integration, and then build a streaming data pipeline using nothing but your bare hands, Kafka Connect, and KSQL.\r\n\r\nGasp as we filter events in real time! Be amazed at how we can enrich streams of data with data from RDBMS! Be astonished at the power of streaming aggregates for anomaly detection!\r\n\r\nPrerequisite \r\nParticipants must have their own laptop and complete the prerequisite steps detailed here PRIOR TO THE WORKSHOP:https://github.com/confluentinc/demo-scene/blob/master/ksql-workshop/pre-requisites.adoc.\r\n\r\nComputer Setup\r\nFor reasons of compatibility, we recommend the use of Mac or Linux for the workshop. 8GB memory is required. Knowledge of SQL is assumed. Participants will benefit from existing knowledge of the concepts of Kafka (topics, streaming, etc).", + "startsAt": "2019-06-19T13:40:00", + "endsAt": "2019-06-19T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e16e10b7-f905-4c95-afb6-6d54a47f577e", + "name": "Robin Moffatt" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + "index": 9 + } + ] + }, + { + "slotStart": "15:00:00", + "rooms": [ + { + "id": 4479, + "name": "Room 1", + "session": { + "id": "99466", + "title": "Drones & AI - What's all the buzz about ?", + "description": "Drones and AI are changing our world.\r\n\r\nIn this session we will look at some of the real world solutions utilising these emerging technologies, you will get an understanding of the core use cases, learn how to get started with the tech, and find out about the pitfalls to avoid when building solutions with drones and Artificial Intelligence.", + "startsAt": "2019-06-19T15:00:00", + "endsAt": "2019-06-19T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "81ccb948-0157-4ef0-bd80-c11ad108d7cb", + "name": "Adam Stephensen" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + "index": 0 + }, + { + "id": 4480, + "name": "Room 2", + "session": { + "id": "78447", + "title": "Rust for C++ developers - What you need to know to get rolling with crates", + "description": "The session is about using the Rust language to write safe, concurrent and elegant code, contrasting with C++", + "startsAt": "2019-06-19T15:00:00", + "endsAt": "2019-06-19T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "3b2b49cf-5746-484c-a85e-be960fe76043", + "name": "Pavel Yosifovich" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + "index": 1 + }, + { + "id": 4481, + "name": "Room 3", + "session": { + "id": "97507", + "title": "CSS Grid - What is this Magic?!", + "description": "We’ve all heard a lot in the last year about a new advancement in the world of CSS, called CSS Grid. Starting off at whispers, we’re now starting to hear it as a deafening roar as more and more developers write about it, talk about it, share it and start using it. In the world of front end, I see it everywhere I turn and am excited as I start to use it in my own projects.\r\n\r\nBut what does this new CSS specification mean for software developers, and why should you care about it? In the world of tech today, we can do so many amazing things and use whatever language we choose across a wide range of devices and platforms. Whether it’s the advent of React and React Native, or frameworks like Electron, it’s easier than ever to build one app that works on multiple platforms with the language we know and work with best. The ability to do this also expands to styling apps on any platform using CSS, and therefore being able to utilise the magical thing that is\r\nCSS Grid.\r\n\r\nThe reason CSS Grid is gaining so much attention, is because it’s a game changer for front end and layouts. With a few simple lines of code, we can now create imaginative, dynamic, responsive layouts (yep, I know that’s a lot of buzz words). While a lot of people are calling this the new ‘table layout’, grid gives us so much more, with the ability to spread cells across columns and rows to whatever size you choose, dictate which direction new items flow, allow cells to move around to fit in place and even tell certain cells exactly where they need to sit.\r\n\r\nWhile there is so much to worry about when developing an app, CSS Grid means that you can worry less about building the layout on the front end, and more about making sure the back end works well. Let me show you how the magic works.", + "startsAt": "2019-06-19T15:00:00", + "endsAt": "2019-06-19T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "d387e75c-ed26-4dc6-8612-0f18abdfd9f5", + "name": "Amy Kapernick" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + "index": 2 + }, + { + "id": 4482, + "name": "Room 4", + "session": { + "id": "98629", + "title": "Getting out of quicksand, with DevOps!", + "description": "Join me in this talk about why high workload leads to increasing waiting times and is detrimental to your project’s success.\r\n\r\nTeams often find themselves in high workload situations, showing symptoms of overload and being to busy to implement the necessary changes or adopt the state-of-the-art tools to get the upper hand.\r\nThis is a story of how we applied the Three Ways of DevOps to get out of a state we referred to as quicksand (The more you fight it, the more it pulls you in).\r\n\r\nI will not only talk about queuing theory and capacity management, but also about DevOps strategies to cope with high utilization and how to start a virtuous circle.\r\n\r\nKey Takeaways are:\r\n\r\n* Crisis situations are opportunities for change\r\n* Often it takes fresh eyes or at least courage to see the problems\r\n* High workload leads to increasing waiting times\r\n* Get out of the quicksand with devops:\r\n * Quantify the work and set goals\r\n * Measure\r\n * Less is more\r\n * Automate the right things\r\n * Establish a continuous improvement process\r\n * Start a virtuous circle", + "startsAt": "2019-06-19T15:00:00", + "endsAt": "2019-06-19T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "7e1213ec-dc2b-400c-a280-fd5df894e11a", + "name": "Roman Pickl" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + "index": 3 + }, + { + "id": 4483, + "name": "Room 5", + "session": { + "id": "98397", + "title": "Adding Observability to Distributed Systems", + "description": "Tell me if this sounds familiar: you have a web service, that calls another service, that sends a Kafka message to a third service, that writes something to a database. Except sometimes it doesn’t. Where did the message go? Did the client not send it? Or did Kafka eat it? You don’t know. You look in the logs, but there are so many logs! You try to reproduce the problem, but annoyingly everything works fine. What to do?\r\n\r\nIn this talk we’ll explore mechanisms for observing and debugging distributed systems, with an eye towards taking an existing codebase that lacks observability and evolving it over time. In particular, we’ll focus on distributed tracing tools that let us track transactions which span multiple services and execution contexts. We’ll discuss how tracing differs from logging and monitoring. How to instrument applications to emit trace data, how to collect and store it, how to visualize transactions, and how this benefits developers, devops, and the business itself. We’ll look at leveraging popular open source technologies, like the CNCF OpenTracing project, Jaeger, Zipkin, and the newly released Elastic APM OpenTracing bridge. \r\n", + "startsAt": "2019-06-19T15:00:00", + "endsAt": "2019-06-19T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "1c0406d8-82a1-45b4-a818-7358e0abe7d9", + "name": "David Ostrovsky" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + "index": 4 + }, + { + "id": 4484, + "name": "Room 6", + "session": { + "id": "99524", + "title": "Writing a Neural Net from Scratch", + "description": "The best way to understand neural networks is to get your hands dirty and write one.\r\nIn this session, I'll show you how to code up a neural net for image recognition from scratch - all in C#, and without using any libraries. From the bottom up, we'll discover gradient descent, activation functions, and backpropagation.\r\n\r\nWe'll work entirely in LINQPad - with no complex maths, no Python, and no libraries. And you'll get to keep the code!", + "startsAt": "2019-06-19T15:00:00", + "endsAt": "2019-06-19T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "35dc3b12-726c-47f6-b6b4-13a8d3d0e774", + "name": "Joe Albahari" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + "index": 5 + }, + { + "id": 4485, + "name": "Room 7", + "session": { + "id": "99316", + "title": "Crash, Burn, Report", + "description": "With the launch of the Reporting API any browser that visits your site can automatically detect and alert you to a whole heap of problems with your application. DNS not resolving? Serving an invalid certificate? Got a redirect loop, using a soon to be deprecated API or any one of countless other problems, they can all be detected and reported with no user action, no agents, no code to deploy. You have one of the most extensive and powerful monitoring platforms in existence at your disposal, millions of browsers. Let's look at how to use them.\r\n\r\nIn this talk we'll look at how to configure the browser to send you reports when things go wrong. These are brand new capabilities the likes of which we've haven't seen before and they're already supported in the world's most popular browser, Google Chrome. We'll look at how to receive reports and how to make use of them after having the browser do the hard work.", + "startsAt": "2019-06-19T15:00:00", + "endsAt": "2019-06-19T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e9c64362-6194-409c-85da-45c8fd40abd6", + "name": "Scott Helme" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + "index": 6 + }, + { + "id": 4486, + "name": "Room 8", + "session": { + "id": "99532", + "title": "The Functional Toolkit", + "description": "The techniques and patterns used in functional programming are very different from object-oriented programming, and when you are just starting out it can be hard to know how they all fit together. \r\n\r\nIn this big picture talk for FP beginners, I'll present some of the common tools that can be found in a functional programmer's toolbelt; tools such as \"map\", \"apply\", \"bind\", and \"sequence\". What are they? Why are they important? How are they used in practice? And how do they relate to scary sounding concepts like functors, monads, and applicatives?", + "startsAt": "2019-06-19T15:00:00", + "endsAt": "2019-06-19T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "89335661-3092-4afa-b53f-3d203cafa2a1", + "name": "Scott Wlaschin" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + "index": 7 + }, + { + "id": 4487, + "name": "Room 9", + "session": { + "id": "97335", + "title": "Code Review Etiquettes 101", + "description": "On most software projects, developers spend a good chunk of their time doing code reviews. These are a great opportunity to provide positive and impactful feedback. More often than not it is up to the person whose code is under review to read and interpret code review comments, which makes it very important to consider the structure, tone and value of these comments. Things as simple as saying \"we could change this\" instead of \"you should change this\" and asking for feedback on a suggestion (e.g.: \"I think this could be implemented using tool X. What are your thoughts on that?\") go a long way in ensuring that the comment and the reviewer are received in a positive light. In this talk I will share code review practices that I have found helpful during my tenure as a software engineer.", + "startsAt": "2019-06-19T15:00:00", + "endsAt": "2019-06-19T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "dc7f3459-13dc-447d-a300-32e39fbe99e7", + "name": "Janani Subbiah" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + "index": 8 + }, + { + "id": 4488, + "name": "Room 10", + "session": { + "id": "128710", + "title": "Workshop: Apache Kafka and KSQL in Action : Let’s Build a Streaming Data Pipeline! Part 2/2", + "description": "Have you ever thought that you needed to be a programmer to do stream processing and build streaming data pipelines? Think again! Apache Kafka is a distributed, scalable, and fault-tolerant streaming platform, providing low-latency pub-sub messaging coupled with native storage and stream processing capabilities. Integrating Kafka with RDBMS, NoSQL, and object stores is simple with Kafka Connect, which is part of Apache Kafka. KSQL is the open-source SQL streaming engine for Apache Kafka, and makes it possible to build stream processing applications at scale, written using a familiar SQL interface.\r\n\r\nIn this workshop you will hear the architectural reasoning for Apache Kafka and the benefits of real-time integration, and then build a streaming data pipeline using nothing but your bare hands, Kafka Connect, and KSQL.\r\n\r\nGasp as we filter events in real time! Be amazed at how we can enrich streams of data with data from RDBMS! Be astonished at the power of streaming aggregates for anomaly detection!\r\n\r\nPrerequisite \r\nParticipants must have their own laptop and complete the prerequisite steps detailed here PRIOR TO THE WORKSHOP:https://github.com/confluentinc/demo-scene/blob/master/ksql-workshop/pre-requisites.adoc.\r\n\r\nComputer Setup\r\nFor reasons of compatibility, we recommend the use of Mac or Linux for the workshop. 8GB memory is required.Knowledge of SQL is assumed. Participants will benefit from existing knowledge of the concepts of Kafka (topics, streaming, etc).", + "startsAt": "2019-06-19T15:00:00", + "endsAt": "2019-06-19T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e16e10b7-f905-4c95-afb6-6d54a47f577e", + "name": "Robin Moffatt" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + "index": 9 + } + ] + }, + { + "slotStart": "16:20:00", + "rooms": [ + { + "id": 4479, + "name": "Room 1", + "session": { + "id": "98996", + "title": "Automatic text summarization", + "description": "Automatic text summarization is the process of shortening a text document by automatically creating a short, accurate, and fluent summary with the main points of the original document using software. It is a common problem in machine learning and natural language processing. \r\n\r\nSince humans have the capacity to understand the meaning of a text document and extract the most important information from the original source using their own words, we are generally quite good at making summaries of a text. However, manual creation of summaries is very time consuming, and therefore a need for automatic summary has arisen. Not only are the automatic summarization tools much faster, they are also less biased than humans. \r\n\r\nNowadays, there are several methods of text summary, but there are two basic approaches to text summary that are based on the output type: extractive and abstractive. In an extractive summary, the most important sentences are extracted and joined to get a brief summary. The abstract text summary algorithms create new sentences and sentences that provide the most useful information from the original text - just as humans do. \r\n\r\nThis lecture provides insight into most common algorithms and tools used for automatic text summarization today, together with the methods used to evaluate automated summaries. \r\n", + "startsAt": "2019-06-19T16:20:00", + "endsAt": "2019-06-19T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e47fa275-9f67-4ef4-8571-28d1b17d667a", + "name": "Masa Nekic" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + "index": 0 + }, + { + "id": 4480, + "name": "Room 2", + "session": { + "id": "98569", + "title": "Securing Web APIs from JavaScript/SPA Applications", + "description": "Modern web development means that more and more application code is running in the browser as JavaScript. This architectural shift requires us to change how we perform authentication and authorization. Fortunately, using modern protocols such as OpenID Connect you don’t need to invent your own solution for this new environment. This session will show you the modern approach for browser-based JavaScript applications to authenticate users, and perform secure web api invocations. As you might expect, security is sufficiently complex and so even modern security comes with its own set of challenges. Luckily, we will show off some libraries that help manage this complexity so your application doesn’t have to.", + "startsAt": "2019-06-19T16:20:00", + "endsAt": "2019-06-19T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "d438622e-8053-4a8f-8df0-af7e9ad32db0", + "name": "Brock Allen" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + "index": 1 + }, + { + "id": 4481, + "name": "Room 3", + "session": { + "id": "98750", + "title": "Panel discussion on the future of .NET", + "description": "Join us for a discussion with four leaders in the field on the current state of the art and the where .NET and related technologies are heading.\r\n\r\nWe will discuss cross platform development, new features, performance improvements, .NET Core and EF Core 3, what’s going to happen with full framework, Blazor, how .NET stands up against competing technologies and where it is all going.\r\n\r\nYou won't cram more info into a session than this, come spend a great hour with us.", + "startsAt": "2019-06-19T16:20:00", + "endsAt": "2019-06-19T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "de972e57-7765-4c38-9dcd-5981587c1433", + "name": "Bryan Hogan" + }, + { + "id": "c9c8096e-47a1-41e5-a00c-d49b51d01c4e", + "name": "K. Scott Allen" + }, + { + "id": "282a4701-f128-4b1d-bd67-da5d1f8b3eb0", + "name": "Julie Lerman" + }, + { + "id": "b2959d46-2ae9-494b-865c-fb850e37d24a", + "name": "David Fowler" + }, + { + "id": "a2c9a4b0-cb47-414a-a7fb-93d0928e77d2", + "name": "Damian Edwards" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + "index": 2 + }, + { + "id": 4482, + "name": "Room 4", + "session": { + "id": "98444", + "title": "Understanding Git — Behind the Command Line", + "description": "Git has become the de-facto version control system of our industry, and for good reason. What you're able to achieve with Git is unmatched by any other version control system that came before it. But for all its power and flexibility, Git has one terrible flaw: its complexity. You won't find me arguing with that. However, I don't believe that Git is hard to understand. In fact, it's quite the opposite — Git is surprisingly simple at its core. The key to unlock its power is to understand it at a fundamental level.\r\n\r\nIn this session, we'll do just that by going through how Git works from the ground up. We'll start out by understanding Git's fundamental concepts and how they're implemented in the object model. From there, we'll work our way up to the user-facing commands and learn to take advantage of Git's unique features to craft a beautiful history without having to compromise on our working style.\r\n\r\nIf you ever wished you knew how Git really works, come to this session and find out.", + "startsAt": "2019-06-19T16:20:00", + "endsAt": "2019-06-19T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "63b2c908-a6f0-41b6-ace8-46a3f5482c54", + "name": "Enrico Campidoglio" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + "index": 3 + }, + { + "id": 4483, + "name": "Room 5", + "session": { + "id": "79682", + "title": "Event Driven Collaboration", + "description": "When we move from a monolith to microservices we abandon integrating via a shared database, as each service must own its own data to allow them it to be autonomous. But now we have a new problem, our data is distributed. What happens if I need one service needs to talk to another about a shared concept such as a product, a hotel room, or an order? Does every service need to have a list of all our users? Who knows what users have permissions to the entities within the micro service? What happens if my REST endpoint needs to include data from a graph that includes other services to make it responsive? And I am not breaking the boundary of my service when all of this data leaves my service boundary in response to a request?\r\n\r\nNaive request-based solutions result in chatty calls as each service engages with multiple other services to fulfil a request, or in large message payloads as services add all the data required to process a message to each message. Neither scale well.\r\n\r\nIn 2005, Pat Helland wrote a paper ‘Data on the Inside vs. Data on the Outside’ which answers the question by distinguishing between data a service owns and reference data that it can use. Martin Fowler named the resulting architectural style; Event Driven Collaboration. This style is significant because it shifts the pattern from request to receiver-driven flow control. \r\n\r\nIn this presentation we will explain how events help us integrate our service architectures. We’ll provide examples in C#, Python and Go as well as using RMQ and Kafka.", + "startsAt": "2019-06-19T16:20:00", + "endsAt": "2019-06-19T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "84ffe422-5bc6-4075-9903-d9ad3526cf86", + "name": "Ian Cooper" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + "index": 4 + }, + { + "id": 4484, + "name": "Room 6", + "session": { + "id": "98676", + "title": "Writing Allocation Free Code in C#", + "description": "Performance is a feature. We all want our code to run faster, and there are plenty of ways to do this - caching, using a smarter algorithm or simply doing less stuff. In this session, we’re not going to look at any of that. Instead, we’re going to focus on a recent trend in the C# world - improving performance by reducing memory allocations. We’ll see how recent versions of C# allow using structs without creating lots of copies, and we’ll have a timely reminder on exactly what is the difference between a class and a struct. We’ll also spend some time with the new Span<T> runtime type and find out how that can help work with slices of existing memory, and how it’s already into the types we know and love in the framework. And of course, we’ll take a look at when you should and (more importantly) shouldn’t use these new techniques.", + "startsAt": "2019-06-19T16:20:00", + "endsAt": "2019-06-19T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "d7dedbba-5fed-47fd-be25-4fb9b1342629", + "name": "Matt Ellis" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + "index": 5 + }, + { + "id": 4485, + "name": "Room 7", + "session": { + "id": "98683", + "title": "Making IoT: An Intro for Web Devs", + "description": "For those of us used to solving problems with software, it can be difficult to branch out to solving problems with technology in the physical world. However, internet connected hardware projects can open up what we build and how people interact with technology in ways that's worth the struggle. In this session, Kristina will go from soldering an LED, connecting it to the internet, and creating a simple web app to monitor sensor data. She'll provide an overview of the different options available and give some pointers for people getting started.", + "startsAt": "2019-06-19T16:20:00", + "endsAt": "2019-06-19T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "945233b4-c513-494c-bcae-c2ccebe07dd5", + "name": "Kristina Durivage" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + "index": 6 + }, + { + "id": 4486, + "name": "Room 8", + "session": { + "id": "98899", + "title": "Terraforming Azure", + "description": "If you are working with resources in Azure and don’t know Terraform, chances are that will benefit from this session. Terraform has made a lot of progress lately in terms of Azure-support and is ready to help you improve how you manage your Azure resources. \r\n\r\nThis session will introduce Terraform and give you a primer on how to use it. Azure Resource Manager is one of the alternatives to Terraform, and you will learn about how they differ and help you choose the right tool. The session will feature a mix live-coding and slides. You will get the most out of the presentation if you know a bit about Azure or Azure Resource Manager.\r\n\r\nI will share my experience with Terraform and Azure Resource Manager, which hopefully will make it easier to understand what might be the right tool in your context. Terraform is not perfect, and you’ll learn about some of the challenges you might face.", + "startsAt": "2019-06-19T16:20:00", + "endsAt": "2019-06-19T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "c0d7c2e8-1f0b-4586-b3a0-dbd18227ca62", + "name": "Torstein Nicolaysen" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + "index": 7 + }, + { + "id": 4487, + "name": "Room 9", + "session": { + "id": "98096", + "title": "Turing's Toy - The story of a mathematical idea that changed the world", + "description": "Alan Turing's paper from 1936, where he describes what came to be known as the Turing machine, is one of the truly pivotal papers in the history of computer science. Turing's description of what he called the \"universal machine\" is frequently referred to as the starting point of the technological revolution we today call the computer. He wrote his paper during a time when the world was going through a dramatic set of upheavals both scientifically, technologically and politically, and his work is a prime example of how basic research of a seemingly esoteric problem can have far reaching consequences.\r\n\r\nAre you interested in learning more about Turing's ground breaking accomplishment? Then join me and hear the fascinating story of the Turing machine! I will describe both its historical context and its implications, but first and foremost I will explain the details of Turing's fictional machine and what he was trying to accomplish with it. This is the story of how a mathematician thought outside the box and accidentally changed the course of history! ", + "startsAt": "2019-06-19T16:20:00", + "endsAt": "2019-06-19T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "212fd3b5-294e-4624-85f0-40fb54abb1c9", + "name": "Øystein Kolsrud" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + "index": 8 + }, + { + "id": 4488, + "name": "Room 10", + "session": { + "id": "98822", + "title": "Workshop: Explore the fundamentals of Rust by creating your own Synthesizer 1/2", + "description": "Rust is a reliable systems programming language providing bare-metal performance in a modern wrapping. It guarantees memory and thread-safety without garbage collection, offers great tooling and an amazing community — in fact, Rust has been voted the most loved programming language according to the Stack Overflow Developer Survey three years in a row. The language is experiencing rapid adaptation in multiple industries ranging from game development to backend systems.\r\n\r\nIn this workshop, we will explore Rust and create a simple synthesizer that can be played with your computer keyboard. We will also implement rudimentary sound effects. The goal of this workshop is to learn some of the basics of Rust through a hands-on project, and no prior knowledge of Rust or audio processing is required.", + "startsAt": "2019-06-19T16:20:00", + "endsAt": "2019-06-19T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "eafc0cc1-0b84-439c-b09a-dc77b4b97459", + "name": "Thomas Tøkje" + }, + { + "id": "e3c7f994-2b3b-493a-b982-811a1a393bc2", + "name": "John-Olav Storvold" + }, + { + "id": "71e76d10-4a45-4a3a-b0af-2f86611bd8b7", + "name": "Sverre Bjørke" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + "index": 9 + } + ] + }, + { + "slotStart": "17:40:00", + "rooms": [ + { + "id": 4479, + "name": "Room 1", + "session": { + "id": "97550", + "title": "Entity Framework debugging using SQL Server: A Detective Story", + "description": "What happens when the code for your Entity Framework Core LINQ queries looks good, but your app is very slow? Are you looking in the right place? Don’t be afraid to start looking at your database. Knowing how to investigate and debug what your LINQ queries are doing in SQL Server is as important as the actual LINQ query in your .NET solutions. We will be looking at database server configurations, using MSSQL database profiling tools and understanding Query Execution Plans to get the most out of Entity Framework. In the end, learning to be an Entity Framework detective will make your project sound and snappy.", + "startsAt": "2019-06-19T17:40:00", + "endsAt": "2019-06-19T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "215bbd42-ce3a-4744-af1f-7e5f0f30d620", + "name": "Chris Woodruff" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + "index": 0 + }, + { + "id": 4480, + "name": "Room 2", + "session": { + "id": "98020", + "title": "Mechanical C++ Refactoring in the Present and in the Future", + "description": "In the last few years, Clang has opened up new possibilities in C++ tooling for the masses. Tools such as clang-tidy offer ready-to-use source-to-source transformations. Available transformations can be used to modernize (use newer C++ language features), improve readability (remove redundant constructs), or improve adherence to the C++ Core Guidelines.\r\n\r\nHowever, when special needs arise, maintainers of large codebases need to learn some of the Clang APIs to create their own porting aids. The Clang APIs necessarily form a more-exact picture of the structure of C++ code than most developers keep in their heads, and bridging the conceptual gap can be a daunting task.\r\n\r\nTooling supplied with clang-tidy, such as clang-query, are indispensable in the discovery of the Clang AST.\r\n\r\nThis talk will show recent and future features in Clang tooling, as well as Tips, Tricks and Traps encountered on the journey to quality refactoring tools. The audience will see how mechanical refactoring in a large codebase can become easy, given the right tools.\r\n", + "startsAt": "2019-06-19T17:40:00", + "endsAt": "2019-06-19T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "dae0a4a0-9346-4031-82b0-365633cdd776", + "name": "Stephen Kelly" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + "index": 1 + }, + { + "id": 4481, + "name": "Room 3", + "session": { + "id": "98457", + "title": "Testing GraphQL: From Zero To Hundred Percent", + "description": "Testing is important for every project, whether it's a web application or api service. But writing scripts to test your application can be a hassle, especially for specific frameworks or tools like GraphQL. Sure, you could just test using Jest, Enzyme or any other testing tool out there for JavaScript applications. But how do you specifically test your GraphQL schemas and queries?", + "startsAt": "2019-06-19T17:40:00", + "endsAt": "2019-06-19T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "4bb972aa-3d92-45ff-95b4-68ed3ca86e9e", + "name": "Roy Derks" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + "index": 2 + }, + { + "id": 4482, + "name": "Room 4", + "session": { + "id": "97531", + "title": "Azure on the cheap", + "description": "Microsoft Azure is a great platform to use when creating your next minimal viable product (MVP). \r\n\r\nBut some services are more expensive than others. And in this talk I will show that instead of going straight to the more expensive options for your MVP, there are many cheap options available on the Azure platform. Some services even have a free-tier. \r\n\r\nUsing Azure Storage Accounts for your data storage needs, Azure Functions or Azure Container Instances for your API and computing needs can make for a very cheap and low maintenance MVP. ", + "startsAt": "2019-06-19T17:40:00", + "endsAt": "2019-06-19T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "4dd872ca-5b4d-49cf-9697-cce19417e431", + "name": "Karl Syvert Løland" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + "index": 3 + }, + { + "id": 4483, + "name": "Room 5", + "session": { + "id": "84004", + "title": "Advanced Serverless Workflows with Durable Functions", + "description": "Azure Functions enable serverless code scenarios that can be triggered by a variety of events and scale automatically without having to configure individual servers or clusters. Durable functions provide state management for long running workflows. See how durable functions address scenarios from asynchronous sequential workflows to fan-out/fan-in scenarios and manual gateways. Learn how to kick-off durable worfklows, monitor progress, troubleshoot, and ultimately recognize significant cost savings by using a service that only bills when it is actively running.", + "startsAt": "2019-06-19T17:40:00", + "endsAt": "2019-06-19T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e4db7e19-394b-4cd9-bc92-9863c54c954f", + "name": "Jeremy Likness" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + "index": 4 + }, + { + "id": 4484, + "name": "Room 6", + "session": { + "id": "82977", + "title": "C# 8 and Beyond", + "description": "One of the most popular programming language on the market is getting even better. With every iteration of C# we get more and more features that are meant to make our lives as developers a lot easier. \r\n\r\nJoin me in this session to explore what's new in C# 8, as well as what we can expect in the near (and far) future of C#!\r\n\r\nWe'll talk about:\r\n- News in C# 8\r\n- Pattern Matching (incl. Record Types)\r\n- Nullable Reference Types and How to Avoid Null Reference Exceptions\r\n- How Async & Await is Improving", + "startsAt": "2019-06-19T17:40:00", + "endsAt": "2019-06-19T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "1f8704d7-04db-4f09-9c0e-d5abcbc7c9ff", + "name": "Filip Ekberg" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + "index": 5 + }, + { + "id": 4485, + "name": "Room 7", + "session": { + "id": "97648", + "title": "Indexing and searching NuGet.org with Azure Functions and Search", + "description": "Which NuGet package was that type in again? In this session, let's build a \"reverse package search\" that helps finding the correct NuGet package based on a public type.\r\n\r\nTogether, we will create a highly-scalable serverless search engine using Azure Functions and Azure Search that performs 3 tasks: listening for new packages on NuGet.org (using a custom binding), indexing packages in a distributed way, and exposing an API that accepts queries and gives our clients the best result. Expect lots of live coding!", + "startsAt": "2019-06-19T17:40:00", + "endsAt": "2019-06-19T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "b425717f-25c3-4863-b893-8f8bb943825a", + "name": "Maarten Balliauw" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + "index": 6 + }, + { + "id": 4486, + "name": "Room 8", + "session": { + "id": "98095", + "title": "Functional Patterns for the Object Oriented", + "description": "Object-oriented languages have during the last decade introduced a number of features originating from the functional programming domain. Most notable are the introduction of lambda expressions and stream processing libraries like LINQ in C# and the Stream API in Java, but other features are emerging as well. C# 7.0 introduced the concepts of tuples and pattern matching, both of which have for a long time been fundamental features of functional languages like Haskell. Why do people consider these features to be functional? And why are people with a background in functional programming thrilled to see these features introduced in the object-oriented world? This talk will focus on a set of case studies that illustrate how functional patterns are typically applied in Haskell and how solutions based on those patterns differ from the traditional OO approach. The talk does not assume a background in functional programming, but hold on to your hat and be prepared for something different!", + "startsAt": "2019-06-19T17:40:00", + "endsAt": "2019-06-19T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "212fd3b5-294e-4624-85f0-40fb54abb1c9", + "name": "Øystein Kolsrud" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + "index": 7 + }, + { + "id": 4487, + "name": "Room 9", + "session": { + "id": "97147", + "title": "Three Rewrites, One Startup - An Architect’s Journey", + "description": "Picture this: you're a senior engineer at your company who, one day, is thrust into the architect role. Suddenly, you're having to think about things that you've never thought about - what's the difference between a microservice and a service bus? How do I design a scalable system for tomorrow without overengineering today?\r\n\r\nBetter yet, if you're at a startup, do all that - and still be responsible for code reviews, development, and coaching of junior devs. How can a fledgling architect possibly \"do it all\" - and more importantly, do it well?\r\n\r\nLuckily, someone has gone down that path (and is still going)... and he's ready to share his story.\r\n\r\nAttend Spencer's talk and hear about how he, as a senior engineer, had to grow into the architect role. We'll discuss the problems faced, the critical \"decision points\" he made from an architecture standpoint, the results of those choices, and how he helped guide the business through three architectural rewrites - all in a span of four years!", + "startsAt": "2019-06-19T17:40:00", + "endsAt": "2019-06-19T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "583e8f08-8316-4ed2-afdf-4cd091e44564", + "name": "Spencer Schneidenbach" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + "index": 8 + }, + { + "id": 4488, + "name": "Room 10", + "session": { + "id": "128712", + "title": "Workshop: Explore the fundamentals of Rust by creating your own Synthesizer - Part 2/2", + "description": "Rust is a reliable systems programming language providing bare-metal performance in a modern wrapping. It guarantees memory and thread-safety without garbage collection, offers great tooling and an amazing community — in fact, Rust has been voted the most loved programming language according to the Stack Overflow Developer Survey three years in a row. The language is experiencing rapid adaptation in multiple industries ranging from game development to backend systems.\r\n\r\nIn this workshop, we will explore Rust and create a simple synthesizer that can be played with your computer keyboard. We will also implement rudimentary sound effects. The goal of this workshop is to learn some of the basics of Rust through a hands-on project, and no prior knowledge of Rust or audio processing is required.", + "startsAt": "2019-06-19T17:40:00", + "endsAt": "2019-06-19T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "71e76d10-4a45-4a3a-b0af-2f86611bd8b7", + "name": "Sverre Bjørke" + }, + { + "id": "e3c7f994-2b3b-493a-b982-811a1a393bc2", + "name": "John-Olav Storvold" + }, + { + "id": "eafc0cc1-0b84-439c-b09a-dc77b4b97459", + "name": "Thomas Tøkje" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + "index": 9 + } + ] + } + ] + }, + { + "date": "2019-06-20T00:00:00", + "rooms": [ + { + "id": 4479, + "name": "Room 1", + "sessions": [ + { + "id": "74808", + "title": "Getting Started with Cosmos DB + EF Core", + "description": "Cosmos DB is great and awesomely fast. Wouldn't be even more amazing if we could use our beloved entity framework to manage it? Let see how we can wire it up and get started", + "startsAt": "2019-06-20T09:00:00", + "endsAt": "2019-06-20T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "c739e2f1-ecf5-43e1-abcf-90cf13dd7b8f", + "name": "Thiago Passos" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + { + "id": "98994", + "title": "Deep Learning in the world of little ponies", + "description": "In this talk, we will discuss computer vision, one of the most common real-world applications of machine learning. We will deep dive into various state-of-the-art concepts around building custom image classifiers - application of deep neural networks, specifically convolutional neural networks and transfer learning. We will demonstrate how those approaches could be used to create your own image classifier to recognise the characters of \"My Little Pony\" TV Series [or Pokemon, or Superheroes, or your custom images].", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "b4c506ac-9757-4ac6-8b7c-3d6696b113e4", + "name": "Galiya Warrier" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + { + "id": "80032", + "title": "Living in eventually consistent reality", + "description": "Strongly consistent databases are dominating world of software. However, with increasing scale and global availability of our services, many developers often prefer to loose their constraints in favor of an eventual consistency. \r\n\r\nDuring this presentation we'll talk about Conflict-free Replicated Data Types (CRDT) - an eventually-consistent structures, that can be found in many modern day multi-master, geo-distributed databases such as CosmosDB, DynamoDB, Riak, Cassandra or Redis: how do they work and what makes them so interesting choice in highly available systems.", + "startsAt": "2019-06-20T11:40:00", + "endsAt": "2019-06-20T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "6373f8a6-11a6-43e9-b1ee-a898dd02d1ce", + "name": "Bartosz Sypytkowski" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + { + "id": "98933", + "title": "Is AI right for me?", + "description": "Artificial intelligence (AI) has become a form of Swiss Army knife for the enterprise world. If you have a data problem, throw some AI at it! However, this mentality can lead to wasted time and money going down the path of implementing a heavy-handed solution that doesn’t fit your business problem. Navigating the waters of AI, machine learning and data analysis can be tricky, especially when being sold by the myriad of data science and AI companies offering solutions at the enterprise level. But fear not, some simple guidelines can help. In this talk, I will present a basic rubric for evaluating AI and data analytics techniques as potential solutions for enterprise business problems.", + "startsAt": "2019-06-20T13:40:00", + "endsAt": "2019-06-20T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e1864dca-8a88-4ea7-840a-20b88702b38f", + "name": "Amber McKenzie" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + { + "id": "98310", + "title": "A Skeptics Guide to Graph Databases", + "description": "Graph databases are one of the hottest trends in tech, but is it hype or can they actually solve real problems? Well, the answer is both.\r\n\r\nIn this talk, Dave will pull back the covers and show you the good, the bad, and the ugly of solving real problems with graph databases. He will demonstrate how you can leverage the power of graph databases to solve difficult problems or existing problems differently. He will then discuss when to avoid them and just use your favorite RDBMS. We will then examine a few of his failures so that we can all learn from his mistakes. By the end of this talk, you will either be excited to use a graph database or run away screaming, either way, you will be armed with the information you need to cut through the hype and know when to use one and when to avoid them.", + "startsAt": "2019-06-20T15:00:00", + "endsAt": "2019-06-20T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "6865759f-cb01-408c-8267-1f9af62f84ee", + "name": "David Bechberger" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + { + "id": "76922", + "title": "ML and the IoT: Living on the Edge", + "description": "Machine Learning and the IoT are a match made in heaven. After all, IoT devices collect mountains of sensor data, what better way to uncover insights and actions than through sophisticated, modern computing methods like ML and AI?\r\n\r\nThe problem is, leveraging ML with IoT has historically meant backhauling all your sensor data to the Cloud. When the cloud is involved, security is a concern, and in the realm of IoT, security is often a dirty word.\r\n\r\nBut modern embedded systems, microcontrollers and single-board computers are getting more powerful, and more sophisticated, and its becoming increasingly possible to bring Machine Learning closer to sensors and IoT devices. \"Edge ML\" enables quicker insights, tighter security, and even true predictive action, and it's going to become the norm in the IoT in the near future.\r\n\r\nIn this session, we'll explore the state of the art in Edge ML and IoT, and talk about practical ways that developers can get started with both, today.", + "startsAt": "2019-06-20T16:20:00", + "endsAt": "2019-06-20T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f1547f29-3799-4bdb-bcbf-112a4e11253e", + "name": "Brandon Satrom" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + { + "id": "84573", + "title": "Tick Tock: What the heck is time-series data?", + "description": "The rise of IoT and smart infrastructure has led to the generation of massive amounts of complex data. In this session, we will talk about time-series data, the challenges of working with time series data, ingestion of this data using data from NYC cabs and running real time queries to gather insights. By the end of the session, we will have an understanding of what time-series data is, how to build streaming data pipelines for massive time series data using Flink, Kafka and CrateDB, and visualising all this data with the help of a dashboard.", + "startsAt": "2019-06-20T17:40:00", + "endsAt": "2019-06-20T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "2c535d4d-198c-4132-932c-bebe9a948306", + "name": "Tanay Pant" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4480, + "name": "Room 2", + "sessions": [ + { + "id": "86264", + "title": "Kotlin for C# Developers", + "description": "Dive into the latest craze in languages and platforms - Kotlin. This time we will be looking at it from the perspective of a .NET C# developer, draw comparisons between the languages, and bridge the gap between these 2 amazing languages.\r\n\r\nWe'll look at:\r\n- Kotlin as a language\r\n- Platforms Kotlin is great for\r\n- Object Oriented Implementations in Kotlin\r\n- Extended Features\r\n- Features Kotlin has that C# doesn't\r\n- A demo Android application in Kotlin vs a Xamarin.Android app in C#\r\n\r\nIn the end you will leave with a foundational knowledge of Kotlin and its capabilities to build awesome apps with less code. You should feel comfortable comparing C# applications to Kotlin applications and know where to find resources to learn even more!", + "startsAt": "2019-06-20T09:00:00", + "endsAt": "2019-06-20T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "42b758e4-1a7c-434d-9951-ddff53503d1f", + "name": "Alex Dunn" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + { + "id": "99197", + "title": "Kotlin coroutines: new ways to do asynchronous programming", + "description": "The async/await feature allows you to write the asynchronous code in a straightforward way, without a long list of callbacks. Used in C# for quite a while already, it has proven to be extremely useful. In Kotlin you have async and await as library functions implemented using coroutines.\r\n\r\nA coroutine is a light-weight thread that can be suspended and resumed later. Very precise definition, but might be confusing at first. What 'light-weight thread' means? How does suspension work? This talk uncovers the magic.\r\nWe'll discuss the concept of coroutines, the power of async/await, and how you can benefit from defining your asynchronous computations using suspend functions.", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "0f769b19-d5f2-49fb-aa78-a086aa046b7e", + "name": "Svetlana Isakova" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + { + "id": "78448", + "title": "Developing Kernel Drivers with Modern C++", + "description": "Kernel drivers are traditionally written in C, but today drivers can be built with the latest C++ standards. The session presents examples and best practices when developing kernel code with C++", + "startsAt": "2019-06-20T11:40:00", + "endsAt": "2019-06-20T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "3b2b49cf-5746-484c-a85e-be960fe76043", + "name": "Pavel Yosifovich" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + { + "id": "81208", + "title": "Accessibility: Coding and Beyond", + "description": "Accessibility is for everyone and is a responsibility of all team members. While a lot of web accessibility guidelines are focused on coding, there are other accessibility components that all team members need to consider in order to improve the overall product or service from the beginning of any projects. Sveta will share her personal experience as a deaf person and some examples of accessibility issues and solutions. They may be new to some and sound like common sense to others, but sadly there are many products and services that fail at accessibility. The talk will help developers and their team members better understand why accessibility is not just about coding and why it's not to be used as an afterthought.", + "startsAt": "2019-06-20T13:40:00", + "endsAt": "2019-06-20T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "ddff421a-de84-4d8f-9d2a-e799ea9c5055", + "name": "Svetlana Kouznetsova" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + { + "id": "127292", + "title": "Deliberate Architecture", + "description": "Step back from your system and take a look at its architecture. Are the major structures and technology choices the result of conscious decisions, or have they emerged as the system has evolved? Architecture is often an ad hoc, responsive process where designs get stuck in local minima while ever more features are piled into the system. Such systems often fail to live up to the origin vision and expectations of stakeholders.\r\n\r\nIn this talk we look at how to design systems which are a purely a function of the major forces acting on a solution, rather than being modishly reflective of the prevailing software zeitgeist. We’ll explore the idea that software architecture, and hence software architects, should focus deliberately on the constraints and qualities of system design, and avoid getting too distracted by features.", + "startsAt": "2019-06-20T15:00:00", + "endsAt": "2019-06-20T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "fb8c0c65-88de-4673-b049-0e8a385c89ad", + "name": "Robert Smallshire" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + { + "id": "98925", + "title": "The Curiously Recurring Pattern of Coupled Types", + "description": "Why can pointers be subtracted but not added?\r\n\r\nWhat do raw C pointers, STL iterators, std::chrono types, and 2D/3D geometric primitives have in common?\r\n\r\nIn this talk we will present some curiously coupled data types that frequently occur in your programs, together forming notions that you are already intuitively familiar with. We will shine a light on the mathematical notion of Affine Spaces, and how they guide stronger design. We will review the properties of affine spaces and show how they improve program semantics, stronger type safety and compile time enforcement of these semantics.\r\n\r\nBy showing motivational examples, we will introduce you to the mathematical notion of affine spaces. The main focus will then be on how affine space types and their well defined semantics shape expressive APIs.\r\n\r\nWe will give examples and guidelines for creating your own affine types. Although the examples in the talk will use C++, the general concepts are applicable to other strongly typed programming languages.\r\n", + "startsAt": "2019-06-20T16:20:00", + "endsAt": "2019-06-20T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f90c9365-b46d-41ef-bfe8-5a8ce7869ab5", + "name": "Adi Shavit" + }, + { + "id": "faf284c6-cee1-4e2c-bd6c-91e92ad33400", + "name": "Björn Fahller" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + { + "id": "99530", + "title": ".NET Rocks Live!", + "description": "Migrating from WCF to .NET Core with Mark Rendle\r\nAre you looking to migrate off of WCF? Microsoft has said that WCF will not move to .NET Core – so what are your options? \r\n\r\nJoin Carl and Richard from .NET Rocks as they talk to Mark Rendle about his work building a tool to help migrate WCF applications to a combination of .NET Core, ASP.NET Web API and gRPC. Bring your questions and be part of an in-person .NET Rocks recording!", + "startsAt": "2019-06-20T17:40:00", + "endsAt": "2019-06-20T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "7a34a7fc-2f1c-4751-af4f-18a21de0e6b3", + "name": "Richard Campbell" + }, + { + "id": "6d1065d2-3494-48a6-a6bb-7efde3d8de40", + "name": "Carl Franklin" + }, + { + "id": "70590ad0-b1b3-40b8-b05d-b58722ef9d9d", + "name": "Mark Rendle" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4481, + "name": "Room 3", + "sessions": [ + { + "id": "99054", + "title": "How to use ML.NET to write crushing metal riffs", + "description": "ML.NET is still fairly fresh Microsoft venture into deep learning. It's written in .NET Core and a lot of good thinking went into it. It's definitely the best hope for .NET developers to do machine learning natively and easily incorporate it into existing apps. \r\n\r\nAnd to show its power we'll harness deep learning to help a metal band to get out of their rut by writing for them some awesome new riffs. \r\n\r\nFrom this talk, you'll learn how to use ML.NET, how some deep learning techniques like Recurrent Neural Networks work and how to write metal songs!\r\n", + "startsAt": "2019-06-20T09:00:00", + "endsAt": "2019-06-20T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "1cfbd2b6-db6f-405a-a997-e0c04e5f1510", + "name": "Michał Łusiak" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + { + "id": "86691", + "title": "An Introduction to WebAssembly", + "description": "Want to write a web application? Better get familiar with JavaScript! JavaScript has long been the king of front-end. While there have been various attempts to dethrone it, they have typically involved treating JavaScript as an assembly-language analog that you transpile your code to. This has lead to complex build pipelines that result in JavaScript which the browser has to parse and *you* still have to debug. But what if there were an actual byte-code language you could compile your non-JavaScript code to instead? That is what WebAssembly is.\r\n\r\nI'm going to explain how WebAssembly works and how to use it in this talk. I'll cover what it is, how it fits into your application, and how to build and use your own WebAssembly modules. And, I'll demo how to build and use those modules with Rust, C++, and the WebAssembly Text Format. That's right, I'll be live coding in an assembly language. I'll also go over some online resources for other languages and tools that make use of WebAssembly.\r\n\r\nWhen we're done, you'll have the footing you need to start building applications featuring WebAssembly. So grab a non-JavaScript language, a modern browser, and let's and get started!", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "520bf4ca-b2d3-47c3-8475-c25bb2b257f7", + "name": "Guy Royse" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + { + "id": "99526", + "title": "Pointless or Pointfree?", + "description": "With the emergence of functional programming in mainstream JavaScript, point-free programming style (also known as tacit programming) is gaining traction. If you ever used RxJS you'll know what I'm talking about...\r\n\r\nIn this talk, we'll explore the motivation behind it and discover some interesting consequences. After imposing a strict set of rules, we'll try and solve a small practical problem and see where does that take us. This talk is a mix of presentation and live coding with examples in JavaScript.", + "startsAt": "2019-06-20T11:40:00", + "endsAt": "2019-06-20T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "c51fb01c-63d1-4b84-92d0-231f1fe3673c", + "name": "Damjan Vujnovic" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + { + "id": "99250", + "title": "The Seven Deadly Presentation Sins", + "description": "What makes a great presentation? More importantly, what are the elements that can destroy a great presentation, even if the content itself is technically sound? \r\n\r\nIn this session Samantha and Andrew Coates demonstrate seven sins that must not be committed in a presentation, why and how a presentation can suffer from committing them, and how to avoid accidently committing them. \r\n\r\nIronically, when we practice we deliberately commit presentation sins. We stop, we fix, we repeat and refine. Like elite musicians, dedicated technical presenters typically spend many solitary hours doing this, which of course is necessary to master any content. But none of these practice processes has a place on the presentation stage. In presentation we must trust, believe, create, and keep going in the face of any adversity – a completely different process which in itself must be rehearsed. \r\nIn order to give a magnificent presentation, we must PRACTICE giving a magnificent presentation. The only way to do this is by regularly and deliberately creating pressure situations in which we can practice NOT committing the presentation sins.\r\n\r\nCovering everything from wrong notes to blue screens of death, this dynamic and multi-talented pair not only break down the elements of successful and unsuccessful presentations, but also outline how one can give a truly engaging presentation every time, no matter how basic or complex the content.", + "startsAt": "2019-06-20T13:40:00", + "endsAt": "2019-06-20T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "2809c750-dc83-4e1c-8f06-38ee96b818b6", + "name": "Andrew Coates" + }, + { + "id": "0e2bfca8-149b-49f8-88d4-bd6558e8f11e", + "name": "Samantha Coates" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + { + "id": "77944", + "title": "Empathetic Design Systems", + "description": "How do you make a design system empathetic and whom should it be empathetic towards? At a recent company, we decided to replace our outdated style guide with a newfangled design system that we started from scratch. And we made a great start.\r\n\r\nBut we forgot about accessibility. Only stand alone components reflected the basics of accessibility leaving full user flows behind. We forgot about our fellow coworkers and peers. Our engineers shouldered slow development times and new technologies, designs changed often, and variants were hard to implement. And we forgot about our users. Much of the design system was geared towards engineers, neglecting designers, product managers and more.\r\n\r\nSo what did we learn in our first iteration? How did empathy help shape our ever-changing, morphing design system? Come learn how to build an empathetic design system from the ground up or start incorporating empathy today!\r\n", + "startsAt": "2019-06-20T15:00:00", + "endsAt": "2019-06-20T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "cdc97666-b7bb-4c51-aec5-c73095c08c54", + "name": "Jennifer Wong" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + { + "id": "127293", + "title": "Anchored Metadata", + "description": "When building software, we often need to associate metadata with the code we’re writing. A typical example is when we need to tell our linters to ignore a specific range of code. A common approach to adding this metadata is to embed it directly in the code using the syntax of the language, but this approach has a number of drawbacks including language specificity, potential for collision, and cluttering of the code.\r\n\r\nIn this talk we’ll look at an alternative approach that stores the metadata separate from the code using a technique called _anchoring_. The metadata is associated with an anchor, a region of code inside the source file. Critically, the anchor also includes a context, a snapshot of the code surrounding the anchored region. As the source code is changed, this context – along with some very interesting algorithms for aligning text -– is used to automatically update the anchors.\r\n\r\nTo demonstrate these concepts we’ll look at spor, a tool that implements anchoring and anchor updating. The primary implementation of spor is in Python, so it’s very approachable and, indeed, open for contribution. As a side note, we’ll also look at a partial implementation of spor written in Rust. Finally, we’ll look at how spor is being used in Cosmic Ray, a mutation testing tool for Python.", + "startsAt": "2019-06-20T16:20:00", + "endsAt": "2019-06-20T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "ad6fb1a9-9b48-4393-95f1-f352e643c541", + "name": "Austin Bingham" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + { + "id": "127294", + "title": "UX Design Fundamentals: What do your users really see", + "description": "Developers are often unaware of how their users actually see their screens. In this UX design session, we'll discuss the most important principles concerning how the human brain and visual system determine how users see application interfaces.\r\n\r\nWe'll look at Gestalt principles for grouping and highlighting, inattentional blindness and change blindness, how users scan through a view, and how to promote clarity in interfaces with levels of emphasis. Tests will help attendees see how they personally experience these principles, and better understand the challenges faced by their users when views and pages are not designed to respect design principles.", + "startsAt": "2019-06-20T17:40:00", + "endsAt": "2019-06-20T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "af1eed12-4400-4d1c-885f-7fbb41e737b6", + "name": "Billy Hollis" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4482, + "name": "Room 4", + "sessions": [ + { + "id": "98350", + "title": "Terraform best practices with examples and arguments", + "description": "It is easy to get started with Terraform to manage infrastructure as code. Just read the documentation on terraform.io, and you are done. Almost.\r\n\r\nThe harder part begins when infrastructure grows in all directions (several AWS/GCP accounts, regions, teams, projects, environments, external integrations). One of the most frequent questions is \"how to structure code\".\r\n\r\nIn this talk, I will explain many of challenges related to that, what works, what does not work, why so, and most importantly I will show all the code which works from small projects to very-large infrastructures (featuring multi-cloud and multi-region setup).\r\n\r\nThis talk is best suitable for people who have been using Terraform at least for some time and already have practical questions, but there will be some basic information for newcomers also.\r\n\r\nAll the slides, code and material will be provided to attendees. Most of the content used for the talk you can find on my site here - www.terraform-best-practices.com", + "startsAt": "2019-06-20T09:00:00", + "endsAt": "2019-06-20T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "2bc0d4de-71fd-46da-94fa-4a50e289f9ab", + "name": "Anton Babenko" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + { + "id": "97523", + "title": "How to be cool in the age of legacy", + "description": "The cloud is here. And we can safely assume it's here to stay.\r\n\r\nThe road forward is pretty clear. Containerization using something like Docker and orchestration using something like Kubernetes. And it's great! Workloads are automatically distributed, new servers can be added and removed with (or without!) the click of a button.\r\n\r\nBut then there is everything else. The 36 .NET framework applications that will take years to migrate. The third party products with support end-of-life from 2017 that are still business critical. Do you leave that stuff behind?\r\n\r\nAt RiksTV we've found a way to work on moving towards a modern cloud infrastructure without throwing out all the legacy code. Using AWS EC2, Ansible, Octopus Deploy, Consul and Traefik we've built a fully automated infrastructure that allows us to scale out applications in a matter of minutes – with (or without) the click of a button!\r\n\r\nIn this talk you'll get a under the covers look at how you can build a modern infrastructure for running old fashioned applications in the cloud. You'll get inspiration, experiences and tooling that helps you get to the cloud – even if you're living in an age of legacy.", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "7577e0ae-3f98-4649-a043-7dc915581546", + "name": "Jøran Vagnby Lillesand" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + { + "id": "97687", + "title": "Practical Chaos Engineering: breaking things on purpose to make them more resilient against failure", + "description": "With the wide adoption of micro-services and large-scale distributed systems, architectures have grow increasingly complex and hard to understand. Worse, the software systems running them have become extremely difficult to debug and test, increasing the risk of outages. With these new challenges, new tools are required and since failures have become more and more chaotic in nature, we must turn to chaos engineering in order to reveal failures before they become outages. In this talk, I will first introduce chaos engineering and show the audience how to start practicing chaos engineering on the AWS cloud. I will walk through the tools and methods they can use to inject failures in their architecture in order to make them more resilient to failure.", + "startsAt": "2019-06-20T11:40:00", + "endsAt": "2019-06-20T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e4fd745a-8a49-43d3-8763-020a4f3512ab", + "name": "Adrian Hornsby" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + { + "id": "99874", + "title": "Lightning Talks (Web)", + "description": "Lightning talks (approx 10-15 minutes each)\r\n\r\nTalk 1: Why you should think twice before choosing CosmosDB - Torstein Nicolaysen\r\n\r\nCosmos DB promises some amazing things, and in all fairness, it’s a pretty cool product. My team has been using Cosmos DB on a system that requires both high levels of performance and uptime. After hours of design sessions, experimentation, performance testing, rewriting the document structure, using new partition keys, faking consistency in the application and several other attempts to make it work for us, we felt that CosmosDB was a bad fit for our use case. The system we work on is in production, and my experience is based on real-world usage.\r\n\r\nThis lightning talk will explain some of the issues we faced, what we learned and give some advice on using Cosmos DB. It won’t be all doom and gloom, and you'll even hear some scenarios were Cosmos DB is a perfect match.\r\n-----------------------------------------------\r\n\r\nTalk 2: How we messed everything up but still got LoRa to the stratosphere - Sindre Lindstad\r\n\r\nBack in the early 2010's people were sending all sorts of tech trash into space using helium balloons and styrofoam boxes.\r\n\r\nA friend and I decided we wanted to do the same thing, but by making everything from scratch. All the way from the PCB's and antennas, down to the web API's and map applications to track it.\r\n\r\nAnd we... sort of made it.\r\n\r\nThis is a story about technology, friendship, and lots and lots of duct tape.\r\n\r\n---------------------------------------------\r\n\r\nTalk 3: Mobile AR in 10 minutes - Kristina Simakova\r\n\r\nA crash course into mobile AR. This talk will give you an overview and a current status on mobile AR technology and SDKs, its new features and shortcomings.\r\n\r\n--------------------------------------------\r\n\r\nTalk 4: I didn't know that - Stefan Judis\r\n\r\n Web Development is a constant journey of new technologies and new things to learn. A year ago I started documenting and sharing all the tiny things that I didn't know before and stopped being anxious about others thinking that I'm not smart. \r\n\r\nLet me tell you what I learned about JavaScript!\r\n\r\n---------------------------------------------\r\n\r\nTalk 5: What's cooking for JavaScript: a look at current TC39 proposals - Branislav Jenco\r\n\r\nIn this lightning talk, I go over the current proposals for new language features in JavaScript and their current status. Pipelines, decorators, null coalescing and more is coming, but when? And how will it look like?\r\n\r\n-------------------------------------------", + "startsAt": "2019-06-20T13:40:00", + "endsAt": "2019-06-20T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "c0d7c2e8-1f0b-4586-b3a0-dbd18227ca62", + "name": "Torstein Nicolaysen" + }, + { + "id": "5ec0ca76-bf24-4fce-bf3d-80656dadf1f6", + "name": "Sindre Lindstad" + }, + { + "id": "6d9319c9-0ad9-4b51-85ac-b55c227be8ec", + "name": "Kristina Simakova" + }, + { + "id": "3dd820f5-722b-496e-8430-ccc3b8ec7a75", + "name": "Stefan Judis" + }, + { + "id": "028d7685-2c9f-4322-8120-f60ac8ef7893", + "name": "Branislav Jenco" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + { + "id": "76039", + "title": "Lessons from the API Management trenches", + "description": "Azure API Management has a lot of functionality, but it's not always clear when to use what. In this session we will go into setting up an API Management architecture, inspired by real life use cases. We will see how we can expose and protect our services, which policies help make our life easier, and how to handle our application lifecycle management.", + "startsAt": "2019-06-20T15:00:00", + "endsAt": "2019-06-20T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "11a684d4-ace1-49e8-be4b-c4e5ff215a7c", + "name": "Eldert Grootenboer" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + { + "id": "78380", + "title": "Observability Driven Development", + "description": "There you are… an agile company building cloud native microservices, everything is automated and you are deploying multiple times a day. You think you ticked all the DevOps boxes but when does the money start flowing in?\r\n\r\nMaybe it's because your users don't like the way your software works, maybe you don't actually have any users. How do you know? Traditional monitoring tools are dead. They can't give you the insights you need to see if your distributed system is still working or not.\r\n\r\n\"Observability driven development\" is a way to focus on building observable systems that focus on seeing if your system is actually working and delivering value to your customers.\r\n\r\nBy being able to observe your production environment you are able to learn from it, experiment on it (in production) and in the end improve it. In this session we'll discuss what it means to create observable systems and how you can start adding observability to your own systems which help everyone from developers to product owners to make better decisions in adding value to their software.", + "startsAt": "2019-06-20T16:20:00", + "endsAt": "2019-06-20T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "a1bae1a4-f4fe-4113-8d4f-cd0f363eb48a", + "name": "Geert van der Cruijsen" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4483, + "name": "Room 5", + "sessions": [ + { + "id": "84204", + "title": "Build your Cloud Operating Model on Azure from zero to hero", + "description": "In this session we will explore how organizations can establish a working cloud operating model in Azure that will help them keep control but also enable agility for their teams, so together they can deliver value to the business. The session is targeting DevOps and PlatformOps teams. Certain level of knowledge of Azure is expected (like Resource Manager, RBAC, Policies, Azure Monitor). We will explore some new capabilities like Azure Blueprints and Resource Graph and how can you leverage them and other essential services like Security Center, Service Health, and Log Analytics to build the model, gain insights into your day-to-day operations, collect telemetry you need, automate some key processes using serverless components and integrate your favorite tools (like Slack, GitHub, etc.). By the end of this demo-packed session we should have a working model the participants can fork from GitHub, customize to fit their needs, and apply in their environment.", + "startsAt": "2019-06-20T09:00:00", + "endsAt": "2019-06-20T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "6e75977d-ea56-466a-9095-9cf793af25bd", + "name": "David Pazdera" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + { + "id": "98578", + "title": "Heterogeneous pipeline processing with Kubernetes and Google Cloud Pub/Sub", + "description": "At Spacemaker, we are building a product for real estate developers and architects leveraging AI methodologies and massive computing power to maximize the potential of any building site. At the core of our platform's AI engine, we have CPU-intensive optimization and search algorithms, memory-demanding simulations, and GPU-optimized machine learning and computer graphics techniques None of these components, however, are equal in terms of resource requirements. Depending on the input size, some components complete within a couple of milliseconds using one CPU, while other components have run time of hours even with several hundred CPUs. Finally, one of our core values at Spacemaker's is the complete autonomy of every product team. This autonomy enables the teams to make their own choices regarding programming languages and libraries but also on their general approach to the problems on hand.\r\n\r\nThe challenges outlined above requires a really flexible pipeline. We have, therefore, replaced our old batch-oriented pipeline with an asynchronous, message-based pipelined built on Kubernetes and Google Pub/Sub. At the core of this pipeline, we find a central message broker that dispatches units of work onto a set of queues, where the broker takes care of task dependencies and ensures the pipeline executions run to their completion. The dispatched tasks are processed by a set of workers deployed to a shared, auto-scaled Kubernetes cluster. This offers elasticity and scalability for the workers and their respective resource requirements. By structuring the pipeline in this way the teams are free to develop individual components using whichever programming languages and tools they see fit, allowing for each component to have different resource requirements.\r\n\r\nIn this presentation I will start off with presenting our old, batch oriented pipeline, discussing why it needed replacement and the research leading up to the design of our new pipeline. I will then elaborate further on the details of our auto-scaling including how we handle the burst workloads by adding new resources to our Kubernetes cluster based on the queue lengths for the workers. Then, I will dig into the details of our message broker, the API and the code used in our pipeline workers. Finally I will wrap-up my presentation highlighting som key performance results and my thoughts on the potential surrounding modularizing a pipeline to enable more general use cases.", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "4e459fd7-73f8-41fc-8c59-e80154a0878e", + "name": "Håkon Åmdal" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + { + "id": "98923", + "title": "Life Beyond Distributed Transactions: An Apostate's Implementation", + "description": "Over a decade ago, Pat Helland authored his paper, \"Life Beyond Distributed Transactions: An Apostate's Opinion\" describing a means to coordinate activities between entities in databases when a transaction encompassing those entities wasn't feasible or possible. While the paper and subsequent talks provided great insight in the challenges of coordinating activities across entities in a single database, implementations were left as an exercise to the reader!\r\n\r\nFast forward to today, and now we have NoSQL databases, microservices, message queues and brokers, HTTP web services and more that don't (and shouldn't) support any kind of distributed transaction.\r\n\r\nIn this session, we'll look at how to implement coordination between non-transactional resources using Pat's paper as a guide, with examples in Azure Cosmos DB, Azure Service Bus, and Azure SQL Server. We'll look at a real-world example where a codebase assumed everything would be transactional and always succeed, but production proved us wrong! Finally, we'll look at advanced coordination workflows such as Sagas to achieve robust, scalable coordination across the enterprise.", + "startsAt": "2019-06-20T11:40:00", + "endsAt": "2019-06-20T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f109dd0b-9441-4cbf-8664-19c021a6de4a", + "name": "Jimmy Bogard" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + { + "id": "127290", + "title": "Monolith Decomposition Patterns", + "description": "Patterns to help you incrementally migrate from a monolith to microservices.\r\n\r\nBig Bang rebuilds of systems is so 20th century. With our users expecting new functionality to be shipped ever more frequently than before, we no longer have the luxury of a complete system rebuild. In fact, a Big Bang migration of a Monolithic architecture into a microservice architecture can be especially problematic, as we’ll explore in this talk.\r\nWe want to ship features, but we also want to change our architecture - and many of us want to be able to break down existing systems into microservice architectures. But how do you do this while still shipping features?\r\n\r\nIn this talk, I’ll share with you some key principles and a number of patterns which you can use to incrementally decompose an existing system into microservices. I’ll even cover off patterns that can work to migrate functionality out of systems you can’t change, making them useful when working with very old systems or vendor products. We'll look at the use of stranger patterns, change data capture, database decomposition and more.", + "startsAt": "2019-06-20T13:40:00", + "endsAt": "2019-06-20T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "006d28cc-1e6f-48af-81d7-58314daa92ce", + "name": "Sam Newman" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + { + "id": "78473", + "title": "Code the future, now", + "description": "We know how to write code to do something now. What about code to do something tomorrow, or next year? Sometimes we use batch jobs. But as business grows, our \"overnight\" batch job starts finishing around lunch time. As we expand to new regions, we realise there is no \"night\". And it's only a matter of time before we make a change and break a batch job we forgot existed. What if tomorrow's code could live in the same place as today's code? What if it all looked the same? What if we could scale it all the same way?\r\n\r\nJoin Adam and discover how to embrace the future in the code we write now. Learn how to capture requirements as first class business logic, and avoid relegating them as second class citizens of the batch job world. Take a deep dive into techniques which combine off the shelf products with fundamental computer science.\r\n\r\nWhere we're going... we don't need batch jobs.", + "startsAt": "2019-06-20T15:00:00", + "endsAt": "2019-06-20T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e3d11172-923c-4256-932a-630aeb5a680e", + "name": "Adam Ralph" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + { + "id": "97321", + "title": "Real-Time, Distributed Applications w/ Akka.NET, Kubernetes, .NET Core, and Azure Kubernetes Service", + "description": "In this session you will learn about how companies ranging from the Fortune 500 to brand new startups are changing the way the build .NET applications to leverage the very latest offerings from Microsoft and the .NET open source community.\r\n\r\nYou'll learn how and why companies are moving their applications onto .NET Core; rearchitecting them to use Akka.NET for fault tolerance, scalability, and the ability to respond to customers in real-time; containerizing them with Docker; putting everything together using Kubernetes for orchestration on-premise or on the cloud with Azure Container Services.\r\n\r\nThis session will provide an overview of how all of these technologies fit together and why companies are adopting them.", + "startsAt": "2019-06-20T16:20:00", + "endsAt": "2019-06-20T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "5a279f06-e4d2-449c-879d-eedec29cd401", + "name": "Aaron Stannard" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + { + "id": "97346", + "title": "Empower Your Microservices with Istio Service Mesh", + "description": "Microservices popularity has grown as a lot of organizations are moving their applications to microservices which enables their teams to autonomously own and operate their own microservices. The microservices have to communicate with each other so how do you efficiently connect, secure, and monitor those services? \r\n\r\nIstio is an open platform for providing a uniform way to integrate microservices, manage traffic flow across microservices, enforce policies and aggregate telemetry data.\r\n\r\nIn this session, we will cover what is service mesh and why it is important for you, what are the core components of Istio, how to empower your microservices to leverage the features that Istio provides on top of Kubernetes such as service discovery, load balancing, resiliency, observability, and security.", + "startsAt": "2019-06-20T17:40:00", + "endsAt": "2019-06-20T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "80f14329-6da2-4fb3-915d-7a2b1f49619f", + "name": "Hossam Barakat" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4484, + "name": "Room 6", + "sessions": [ + { + "id": "75536", + "title": "Pragmatic Performance: When to care about perf, and what to do about it.", + "description": "As a developer you often here both that performance is important, but also that you shouldn't worry about performance up front, so when is the right time to think about it? And if the time is right, what are you actually supposed to do?\r\n\r\nIf you're interested to hear about a pragmatic approach to performance, this talk will explain when is the right time to think about benchmarking, but more importantly will run through how to correctly benchmark .NET code so any decisions made will be based on information about your code that is trustworthy.\r\n\r\nAdditionally you'll also find out about some of the common, and some of the unknown, performance pitfalls of the .NET Framework and we'll discuss the true meaning behind the phrase \"premature optimization is the root of all evil\".", + "startsAt": "2019-06-20T09:00:00", + "endsAt": "2019-06-20T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "604507ba-fd96-4c48-a29a-67a95760d888", + "name": "David Wengier" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + { + "id": "100426", + "title": "Bulletproof Transient Error Handling with Polly", + "description": "Connected applications only work when connected. What happens if the network breaks temporarily? Will your system recover smoothly or pitch a fit? Using an OSS project called Polly (available on GitHub) you can handle this and many other transient situations with elegance and fluency. Polly let’s you define retry policies using standard patterns such as retry, retry forever, wait and retry, and circuit breaker. Learn how to make your system bulletproof with Polly and a little know-how.", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "6d1065d2-3494-48a6-a6bb-7efde3d8de40", + "name": "Carl Franklin" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + { + "id": "98473", + "title": "Building a parser in C#, from first principles", + "description": "A simple query language is often more usable than a gigantic search form. A small domain-specific language can sometimes be much more succinct and expressive than a method-driven API. Parsing and language implementation belong in the toolbox of every working programmer.\r\n\r\nUnfortunately, the first time most of us encounter parser construction, it's in an academic setting that surveys the entire sophisticated and rather daunting field. This makes it easy to mistake language implementation for a specialist area, when in fact, parsers for even very complex languages can be built in plain C# using just a few simple patterns.\r\n\r\nCome along to this session to level-up your language implementation skills. We'll distill the nature of the task, the essential techniques on hand, and build a parser using tools you can introduce into your real-world applications and libraries.", + "startsAt": "2019-06-20T11:40:00", + "endsAt": "2019-06-20T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "57f3370f-81bd-43a3-b0ed-acb40cc70035", + "name": "Nicholas Blumhardt" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + { + "id": "99517", + "title": "Blazor, a new framework for browser-based .NET apps", + "description": "Today, nearly all browser-based apps are written in JavaScript (or similar languages that transpile to it). That’s fine, but there’s no good reason to limit our industry to basically one language when so many powerful and mature alternate languages and programming platforms exist. Starting now, WebAssembly opens the floodgates to new choices, and one of the first realistic options may be .NET.\r\n\r\nBlazor is a new experimental web UI framework from the ASP.NET team that aims to brings .NET applications into all browsers (including mobile) via WebAssembly. It allows you to build true full-stack .NET applications, sharing code across server and client, with no need for transpilation or plugins.\r\n\r\nIn this talk I’ll demonstrate what you can do with Blazor today and how it works on the underlying WebAssembly runtime behind the scenes. You’ll see its modern, component-based architecture (inspired by modern SPA frameworks) at work as we use it to build a responsive client-side UI. I’ll cover both basic and advanced scenarios using Blazor’s components, router, DI system, JavaScript interop, and more.", + "startsAt": "2019-06-20T13:40:00", + "endsAt": "2019-06-20T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "0c555530-fbd8-49f4-831a-6b30d15c2966", + "name": "Steve Sanderson" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + { + "id": "84340", + "title": "Logging, Metrics and Events in ASP.NET Core", + "description": "Providing decent monitoring of your applications has always been considered the boring part of development, with tons of boilerplate code, and making upfront decisions around how it will be done, or retrofit afterwards. However, with dotnet core, things have changed, it's never been easier to implement effective visibility into how your application is performing in production.\r\n\r\nIn this session I will cover the fundamental differences between Metrics and Logs, and Events and look at where one is useful over the other.\r\n\r\nWe’ll look at some of the things Microsoft has done in dotnet core to make logging easier, and some of the third-party libraries and tools that aim to make it easier to navigate.\r\n\r\nWe’ll cover tools like Serilog and Log4Net, along with AppMetrics for capturing application information. We’ll then take a quick look at Grafana, and see how we can make some sense of that information. Finally, we'll look at Honeycomb.io and how they're providing actionable insights for distributed systems using events, enabling testing in production.", + "startsAt": "2019-06-20T15:00:00", + "endsAt": "2019-06-20T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "9b006212-1589-4af6-8d18-10d2792fd9ce", + "name": "Martin Thwaites" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + { + "id": "82548", + "title": "Correcting Common Async/Await Mistakes in .NET", + "description": "Did you know that the .NET compiler turns our async methods into classes? And that .NET adds a try/catch block to each of these classes, potentially hiding thrown exceptions? It's true!\r\n\r\nIn this session, we will learn how to best use async/await in C# by analyzing how .NET compiles our async code.\r\n\r\nJoin me as we take an existing app and optimize its async code together, showing off performance gains, better exception handling, improved run-time speed, and smaller app size!", + "startsAt": "2019-06-20T16:20:00", + "endsAt": "2019-06-20T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "276db8d7-4b9d-4e5e-a656-b88335a0ba00", + "name": "Brandon Minnick" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + { + "id": "76044", + "title": "Advanced .NET debugging techniques from real world investigations", + "description": "You know how it feels. After releasing a new version, a service starts behaving in an unexpected way, and it's up to you to save the day. But where to start?\r\n\r\nCriteo processes 150 billion requests per day, across more than 4000 front-end servers. As part of the Criteo Performance team, our job is to investigate critical issues in this kind of environment.\r\n\r\nIn this talk, you will follow our insights, mistakes and false leads during a real world case.\r\n\r\nWe will cover all the phases of the investigation, from the early detection to the actual fix, and we will detail our tricks and tools along the way. Including but not limited to:\r\n\r\n - Using metrics to detect and assess the issue;\r\n - What you can get... or not from a profiler to make a good assumption;\r\n - Digging into the CLR data structures with a decompiler, WinDBG and SOS to assert your assumption;\r\n - Automating memory dump analysis with ClrMD to build your own tools when WinDBG falls short.", + "startsAt": "2019-06-20T17:40:00", + "endsAt": "2019-06-20T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "a147c43c-8537-4cc7-92f5-41ee2c1d67ab", + "name": "Kevin Gosse" + }, + { + "id": "62706aaf-aadc-4538-9f39-70f5afb4cf0b", + "name": "Christophe Nasarre" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4485, + "name": "Room 7", + "sessions": [ + { + "id": "99154", + "title": "Hack to the Future", + "description": "Infosec is a continual game of one-upmanship; we build a defence and someone breaks it so we build another one then they break that and the cycle continues. Because of this, the security controls we have at our disposal are rapidly changing and the ones we used yesterday are very often useless today.\r\n\r\nThis talk focuses on what the threats look like *today*. What are we getting wrong, how do we fix it and how do we stay on top in an environment which will be different again tomorrow to what it is today. It's a real-world look at modern defences that everyone building online applications will want to see.", + "startsAt": "2019-06-20T09:00:00", + "endsAt": "2019-06-20T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "735a4b60-42e8-4452-9480-68197372c206", + "name": "Troy Hunt" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + { + "id": "78506", + "title": "A practical look at security and identity in ASP.NET Core and Entity Framework Core", + "description": "This is a talk about what happened when a client asked me to build a big, multi-tenant web application, and they said “we have quite a complex set of rules on what our user can do”. That turned into quite a journey.\r\n\r\nIn this session I will take you through the design we used to get ASP.NET Core and Entity Framework Core to provide both feature-level authorisation (e.g. controlling what Web APIs/pages the user can access) and data-level authorisation (i.e. controlling what data they can see).", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e193d34d-e2ed-4042-960c-c5357c33cd39", + "name": "Jon P Smith" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + { + "id": "97725", + "title": "Security Static Analysis - Avoiding an Angry Mob of Engineers", + "description": "The idea of Security Static Analysis is promising - point a tool at source code and magically find all of the security mistakes, hurray! Clearly several organizations think so, as many compliance regimes require its usage, and most secure development guidance recommend it. In reality adopting static analysis into a development process is incredibly challenging, and can easily both fail to meet security objections and enrage the software engineers. This talk draws on many painful lessons learned deploying static analysis in several engineering organizations, with the goal of helping the audience better evaluate tools in the space, and have higher success deploying them.", + "startsAt": "2019-06-20T11:40:00", + "endsAt": "2019-06-20T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "2d2346a9-ce85-4160-aa7d-3aaab29ad067", + "name": "Josh Brown-White" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + { + "id": "82788", + "title": "Privacy and GDPR: What all developers should know", + "description": "On May 25th the European Union enacted new privacy laws that apply uniformly to all member nations. These rules will pretty much apply to anyone who builds or owns IT systems and the implications may surprise you.\r\n\r\nIn this practical and entertaining talk, Johannes explores how a simple example of an everyday application gets entangled with privacy issues and how to untangle yourself.\r\n\r\nAs a side effect of the going to the talk, you will be able to impress your friends with statements like \"according GDPR article 7, subsection 4, this is not a legally obtained consent\" - a phrase that works surprisingly well at parties.", + "startsAt": "2019-06-20T13:40:00", + "endsAt": "2019-06-20T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "a1b51ef9-8e88-4154-9d4f-0d982498ea43", + "name": "Johannes Brodwall" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + { + "id": "98435", + "title": "Best practices for securing CI/CD pipeline", + "description": "DevOps practices are in a place; containers are everywhere, pipelines are flying. We do Agile. We do DevOps. Now we try to follow security practices for protecting the deployed resources, too. This is a reason why DevSecOps is not hype anymore and is gaining more prominence. There is a lot of information about DevSecOps, but how to do it properly? Where to start? What are the best practices?\r\nIn this session, we will walk through an end-to-end scenario where we will deploy infrastructure components securely to Azure using Azure DevOps, Azure Container Registry and security tools. We will build a pipeline with security in mind to protect and detect potential security flows during the build.\r\nYou will learn:\r\n- How to build end-to-end CI/CD pipeline that builds the application and deploys infrastructure on Azure with security checks for the application, containers and infrastructure;\r\n- What are the security tools available for CI/CD pipeline and how to implement them in the best way into different Git workflows;\r\n- Best practices and patterns of building security pipelines.\r\n\r\n\r\n\r\n", + "startsAt": "2019-06-20T15:00:00", + "endsAt": "2019-06-20T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "4c3efe89-ab58-4b28-a9c3-78251f25ee06", + "name": "Victoria Almazova" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + { + "id": "98763", + "title": "Securing the web with AI", + "description": "In today’s web not a week goes by without a large data breach or a website being hacked. Unlawful access to our online information can be prevented by encryption, 2FA and IP detection, but often this isn’t enough. Additionally tools like 2FA can be difficult to configure or understand for the initiated, leaving many at a disadvantage - security should be a right, not a privilege.\r\n\r\nThis session explores some interesting and experimental ways that AI could be used to improve security and protect users on the web.\r\n\r\nUsing existing AI tools like Azure Cognitive Services we’ll look at ways facial or voice recognition could be used as part of 2FA to make security more accessible to end users, including code examples in .NET and JavaScript. Then we’ll investigate some simple methods to find patterns in user behaviour, such as login times and mouse behaviour, to detect anomalies and take action.\r\n\r\nFinally, we’ll see how machine learning can be used to identify fraudulent text or photoshopped images within webpages and warn users of scams before it becomes an issue.", + "startsAt": "2019-06-20T16:20:00", + "endsAt": "2019-06-20T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "3f01a9fa-4c71-4efe-871f-8e0ced1471d0", + "name": "Callum Whyte" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + { + "id": "98882", + "title": "What vulnerabilities? Live hacking of containers and orchestrators", + "description": "We often see alerts about vulnerabilities being found in frameworks that we use today, but should we really care about them? What's the worst that can happen? Can someone own a container? Could they run a bitcoin miner on my servers? Are they able to own the cluster?\r\n\r\nIn this talk, we look at one of the worst-case scenarios from a real-world perspective. We have a red team member attempting to hack a cluster we own with a live hack on stage whilst the blue team member tries to stop it from happening.\r\n\r\nWe'll discuss developing best practices, implement security policies and how best to monitor your services to put preventative measures in place.\r\n\r\n", + "startsAt": "2019-06-20T17:40:00", + "endsAt": "2019-06-20T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "964af3ac-fd5e-46f6-b582-6c0d2da30db4", + "name": "Lewis Denham-Parry" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4486, + "name": "Room 8", + "sessions": [ + { + "id": "86523", + "title": "A practical guide to deep learning", + "description": "Machine Learning is one of the fastest growing areas of computer science, and Deep Learning (neural networks) is growing even faster, with lots of data and computing power at our fingertips. \r\nThis talk is a practical (very little math) guide to computer vision and deep learning.\r\n\r\nWe will look at a deep learning project from start to finish, look at how to program and train a neural network and gradually refine it using some tips and tricks that you can steal for your future deep learning projects.", + "startsAt": "2019-06-20T09:00:00", + "endsAt": "2019-06-20T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "cb70e0f2-0f0b-4b8f-b3f4-a9326309a1b2", + "name": "Tess Ferrandez-Norlander" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + { + "id": "77149", + "title": "Write your own domain specific language with F#", + "description": "F# is a powerful and expressive multi-paradigm language with high performance and focus on functional programming. This language allows you to write code, which a non technical person would be able to read and understand. In this talk I will show you how to write your own strongly and statically typed DSL. With it you will be able to focus on business logic and not get distracted with \"keyword\" noise.", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "2720a9e3-3c9e-4b2b-9472-e7b7b0de19d5", + "name": "Mikhail Smal" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + { + "id": "85869", + "title": "Functional Web Programming in .Net with the SAFE Stack", + "description": "The SAFE stack is an open source stack of libraries and tools which simplify the process of building type safe web applications which run on the cloud almost entirely in F#. \r\n\r\nIn this talk we'll explore the components of the SAFE stack and how they can be used to write web services and web sites in idiomatic F#. We'll see how we can manage this without needing to compromise and use object oriented frameworks whilst also still integrating with the existing ASP.Net, JavaScript and React ecosystems. We'll consider how we can write backend applications using Saturn on top of ASP.Net, we'll look at how to run F# in the web browser with Fable and we'll cover how we can develop interactive web applications leveraging the benefits of functional programming. This talk is aimed at developers who are looking to understand how they can use F# to effectively build full stack web applications.", + "startsAt": "2019-06-20T11:40:00", + "endsAt": "2019-06-20T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "71cb7875-d2d8-45d1-ae12-7687bae03200", + "name": "Anthony Brown" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + { + "id": "98635", + "title": "Real world hypermedia at NRK TV", + "description": "At NRK TV we are gradually introducing hypermedia in the API that serves the clients our viewers use to stream our TV content. Why? Not out of idealism, but because it provides concrete benefits for our service. We use hyperlinks to provide affordances for clients: instead of just exposing individual endpoints that serve data, we offer navigation options that form user stories that adapt dynamically based on different scenarios and application states. Hyperlinks also allow us to tie together bounded domain contexts that we keep separate to contain complexity. Clients can seamlessly navigate between e.g. editorial content, catalog, playback and personalized recommendations, without noticing or caring that different contexts could be supported by separate applications with varying degrees of criticality and separate failure modes. That sounds all sweet and dandy, but I'll back these pretty words up with practical examples taken from our API, and share some experiences and lessons learned.", + "startsAt": "2019-06-20T13:40:00", + "endsAt": "2019-06-20T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "bfe8fb18-a060-40c1-9882-e082073a5e77", + "name": "Einar Høst" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + { + "id": "99067", + "title": "Building a bank from scratch in the Cloud", + "description": "We are building the next generation mobile bank in the cloud from scratch! This is how we build Bulder Bank from the ground up.\r\n\r\nEarly on it was decided that we had to be open for radical new ideas if we was to succeed. Important kriterias was speed, modern and automated processes and future-proofing. In addition we wanted to make something that was cool and motivated everyone on the team to work on.\r\n\r\nThe choice landed on Google Kubernetes Engine and Google Firebase and the possibilities this gives us are literally endless! And it gives us the opportunity to move fast while having a more or less fully managed environment that is always up and running!\r\n\r\nWe have decided to model payments entirely event based and asynchronously where multiple microservices written in Go each do their part before handing over the transaction to the next service over a message queue.", + "startsAt": "2019-06-20T15:00:00", + "endsAt": "2019-06-20T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "3de2ca4c-383f-436e-8351-9ca8bf4771cd", + "name": "Hans Kristian Flaatten" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + { + "id": "98660", + "title": "Moving the enterprise to Kubernetes", + "description": "With around 720.000 customers, Hafslund Nett is Norway’s largest power grid company and the fifth-largest in the Nordic region. The IT department have been migrating all of their services onto kubernetes. This introduces a set of challenges to keep control without sacrificing agility or speed.\r\n\r\nThis talk will show how Hafslund Nett decided to use a Cloud Managed Kubernetes with RBAC and AD groups to get fine grained control, secure development projects, use namespaces to control worker nodes usage and how we ended on separated Kubernetes clusters for each cluster environment. Additionally OpenIDConnect is used to provide the customers facing applications with B2C capabilities.\r\n\r\nWe will show how the centralizing of logs enable us to do monitoring, display trends, optimizing resource usage, improve Kubernetes scheduling and feed the CI/CD pipelines to further improve the container services.", + "startsAt": "2019-06-20T16:20:00", + "endsAt": "2019-06-20T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "dff50ecf-976f-48fa-a630-64511bbf3b88", + "name": "Fredrik Klingenberg" + }, + { + "id": "b195b7d1-3a85-4ca0-a5e6-7cfbdd3a8c48", + "name": "Gustav Kaleta" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + { + "id": "74878", + "title": "Powering 100+ million daily users", + "description": "In this talk I will walk through how we build a simple architecture for a complex system with strict performance (250 ms) and scale (100+ million connected daily users) requirements in order to power people experiences in Outlook, Owa, OneDrive, etc. Also share our thinking of how to slowly and gradually shift the engineering mindset to embrace microservices without scratching everything and starting from scratch.", + "startsAt": "2019-06-20T17:40:00", + "endsAt": "2019-06-20T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "8d5c7076-3579-40c3-9fbf-a02749078257", + "name": "Rezaul Hoque" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4487, + "name": "Room 9", + "sessions": [ + { + "id": "86058", + "title": "The New Frontier: A Gentle Introduction to Rust", + "description": "The Rust programming language is systems oriented language that has captured attention and love of software developers and proved to have a great adoption, having being voted the most loved programming language for the last three years in the StackOverflow Developer survey.\r\n\r\nMy session will be an introduction to Rust programming language for developers interested in the language, it's characteristics, strengths and real world usage.\r\n\r\nThe outline of my session will be :\r\n- Why Rust: \r\n * the problems it aims to solve.\r\n- Rust's Defining Features: \r\n * what makes rust Rust.\r\n- Rust's Ecosystem, maturity and production readiness.\r\n * areas where Rust application suits and the state of maturity, libraries and support.\r\n- Real world Rust usage:\r\n * show how Rust has been leverage in real world usage\r\n- Where do I start: how to adopt Rust with your organisation\r\n * next steps if you think Rust is a good fit for you.\r\n\r\nRust is a language that empowers everyone to write efficient and reliable software. It encourages fearless hacking and this talk is really meant to exemplify this! My aim to encourage fellow engineers to embrace it and reap from the benefits it brings.\r\n\r\n\r\nThanks\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n", + "startsAt": "2019-06-20T09:00:00", + "endsAt": "2019-06-20T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "16088c49-02b3-47f5-b383-f021aef73075", + "name": "Matthew Gathu" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + { + "id": "98949", + "title": "Mirror mirror on the wall, what is the vainest metric of them all?", + "description": "You may have heard development teams talking about the number of deploys they make a day or the number of PRs merged a day. You may have heard marketing teams talk about the number of page views a day. What do these metrics even mean? Are they actually useful to the business as a whole?\r\n\r\nIn this talk, Paul will debunk the idea of “vanity” metrics and why using these as a guide to success has only one outcome. This is a talk intended for all parts of an organisation to really help understand what metrics can do for us and why a metric may not mean what you believe it does\r\n\r\nBehind every vanity metric is a real metric that can help us understand the health of our company - whether it be the ability to understand our users or the ability to understand the value of a feature\r\n\r\nWe just need to step back and think about what it actually is...", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "18f368cc-86e7-4921-9f9a-587e7ef037ea", + "name": "Paul Stack" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + { + "id": "99529", + "title": "The Moon: Gateway to the Solar System", + "description": "In 1972, the last human to walk on the Moon headed back to Earth. Is it time to go back? Join Richard Campbell as he explores the potential of a return of humans to the Moon. \r\n\r\nMuch has been learned about the Moon since the Apollo missions, and interest in the Moon as a place of science, exploration and learning is growing. Even today there are new spacecraft and new science being done on and around the Moon. The Moon can be a catalyst to humankind traveling the solar system - it's time to go back!", + "startsAt": "2019-06-20T11:40:00", + "endsAt": "2019-06-20T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "7a34a7fc-2f1c-4751-af4f-18a21de0e6b3", + "name": "Richard Campbell" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + { + "id": "98869", + "title": "Universal Design of Software Solutions: Necessary for some, good for everyone", + "description": "The Norwegian government has made “necessary for some, good for everyone” a mantra of a new movement that aims to ensure that everyone can participate in society. One of the ways the government has tried to achieve this aim is through universal design. Universal design is the idea that the buildings as well as digital solutions can be made accessible to all people, regardless of age, disability, or other factors. In Norway, universal design is a legal obligation for all public service providers. It’s also good for business as including new untapped forms or revenue and market segments can help broaden a product or services appeal. However, according to the Norwegian government, public and private service providers have not yet fully adopted universal design as in the design and development of software systems.\r\n\r\nThe government agency, Difi, recently reported that one website stood out as an useful example of how universal design could be implemented in practice. The official website of the Norwegian police, politet.no, one of Bouvet’s clients gave us permission to present how this project took the grand challenge of universal design and made it part of the DNA of their website. The project team integrated a universal design approach in the development process from beginning to end. \r\nThis process provides an good practice approach for using universal design not only set an example for other businesses and government agencies, but to reach all of their citizens equally no matter their age or disability. \r\n\r\nOne of the great myths of universal design is that it is difficult to prioritize with all the other high demands that organizations face and that it will be expensive. However by integrating a universal design approach in technology development, software engineers and programmers have the opportunity to create low cost and easily deployable solutions for achieving universal design. As a result, their products and services enjoy greater usability, a better user experience and a truly equal approach to creating new technology.\r\n", + "startsAt": "2019-06-20T13:40:00", + "endsAt": "2019-06-20T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f281d82e-3bfe-44c1-9f2a-7dca7353123c", + "name": "George Anthony Giannoumis" + }, + { + "id": "471b4692-faac-4cfc-b1de-b1adba2211bc", + "name": "Maren Gulnes" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + { + "id": "86712", + "title": "Why our products and communities need our empathy", + "description": "Empathy is a fundamental part of human interaction. When we communicate by email or at conferences, or indirectly, when we create products, events, or do a talk. However, our understanding of other people is full of error, and worse, bias. This can lead us to make communities and products that work poorly for people that are different from ourselves, introduce confusion and misunderstanding, exclude people unintentionally, and sometimes even cause harm.\r\n\r\nHowever, our communities are an opportunity to learn as well. To embrace our diversity, and expand our understanding of other people's worlds. To gain understanding of other people’s situations, experiences and emotions, which can be dramatically different to ours. And how we can use this to create both products and communities which work great not only for ourselves, but also those that we more easily forget about. As creators in tech we have such tremendous power to create change, but merely our best intentions will not be enough for that.\r\n\r\nThis talk will explore how and why we sometimes have such difficulty to understand others, and how others can have difficulty to understand us. We'll talk about why other people's experiences, emotion and perceptions can be so different. Both for the world as a whole, but also with the speaker's personal experiences. Finally, we'll cover specific ways for us to understand others better, and associated pitfalls, to make our communities and products happy, inviting and supportive places.\r\n\r\nPrevious attendees of this talk said:\r\n\r\n- \"I think this touched the very core of the complexity of empathy and vulnerability\"\r\n- \"I feel safe in this community, and talks like this are one of the main reasons.\"\r\n- \"Having a talk about such a difficult topic makes you a great role model in general to me!\"\r\n- \"Your talk made me feel so much more welcome and safe at this event.\"\r\n- \"As usual, she's delivering an amazing talk.\"\r\n- \"Great speech, really important and meaningful.\"\r\n- \"Awesome, awesome talk.\"", + "startsAt": "2019-06-20T15:00:00", + "endsAt": "2019-06-20T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "2f0477e0-2bc8-491b-881c-a319783bad12", + "name": "Sasha Romijn" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + { + "id": "99225", + "title": "Shaving my head made me a better programmer", + "description": "How do perceptions and stereotypes affect those in software and on engineering teams? This talk tells the true story of how I hacked my appearance, by shaving my head, to change the way I was perceived as a programmer.\r\n\r\nThis talk also serves as a primer on unconscious bias and stereotype threat, and their effects on individuals and teams. I will provide actionable advice on how to make engineering teams more inclusive, more diverse, and thusly more productive, successful, and attractive to potential hires.", + "startsAt": "2019-06-20T16:20:00", + "endsAt": "2019-06-20T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "c7c00ce0-a071-4a0a-976d-b6903d39209d", + "name": "Alex Qin" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + { + "id": "98723", + "title": "5 Tips for Cultivating EQ in the Workplace", + "description": "Learning to manage our state of mind in the workplace is an acquired skill. While stress in the workplace in unavoidable, it is possible to cultivate Emotional Intelligence (EQ) to manage our state of mind. Practicing EQ helps us identify and eliminate stressors in our lives. Awareness of self and awareness of others strengthens personal and professional relationships. When we understand the motivations of ourselves and the perspectives of others we form deeper connections. In this presentation, learn five tips for cultivating Emotional Intelligence in the workplace.\r\n\r\n", + "startsAt": "2019-06-20T17:40:00", + "endsAt": "2019-06-20T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e296f852-2d30-4f51-8cf6-ac3c87b1427e", + "name": "Christina Aldan" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4488, + "name": "Room 10", + "sessions": [ + { + "id": "85978", + "title": "Workshop: Pragmatic unit testing now - Part 1/2", + "description": "At the age of cloud and serverless, unit testing remains very relevant if not more so. Yet we keep seeing resistance and frustration around unit testing.\r\n\r\nPrerequisite\r\nBring a laptop with .NET Core, Git + an I.D.E. installed (e.g. Visual Studio Code).\r\nWe will be coding in C# but the ideas are not tied to it. Plus the code project should be straight-forward enough.\r\nPaper programmers welcome too!\r\nSlightly more reading for overachievers https://github.com/hackle/putn\r\n\r\nFor this workshop we:\r\n\r\n- explore why that is,\r\n- expose disadvantages of questionable yet popular practices in the industry,\r\n- gradually address blockers to efficient unit testing\r\n- and advance a pragmatic & practical approach to application architecture and unit testing, which can help teams adopt quickly and benefit immediately.\r\n\r\nA way of unit testing - and application architecture in turn - heavily influenced by functional style programming, but rarely promoted in the Object Oriented community.\r\n\r\n- Pursuit of purity in code: what, why and how\r\n- Deliberate and planned segregation of complexity\r\n- Separation of IO for cleaner architecture\r\n\r\nSome of the techniques introduced in this session may appear unconventional at first look, but would prove productive and reasonable (even obvious) as we dig deeper.\r\n", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "a7c88a64-b900-4c3c-a5c7-a2552528f533", + "name": "Hackle Wayne" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + { + "id": "128714", + "title": "Workshop: Pragmatic unit testing now - Part 2/2", + "description": "At the age of cloud and serverless, unit testing remains very relevant if not more so. Yet we keep seeing resistance and frustration around unit testing.\r\n\r\nPrerequisite\r\nBring a laptop with .NET Core, Git + an I.D.E. installed (e.g. Visual Studio Code).\r\nWe will be coding in C# but the ideas are not tied to it. Plus the code project should be straight-forward enough.\r\nPaper programmers welcome too!\r\nSlightly more reading for overachievers https://github.com/hackle/putn\r\n\r\nFor this workshop we:\r\n\r\n- explore why that is,\r\n- expose disadvantages of questionable yet popular practices in the industry,\r\n- gradually address blockers to efficient unit testing\r\n- and advance a pragmatic & practical approach to application architecture and unit testing, which can help teams adopt quickly and benefit immediately.\r\n\r\nA way of unit testing - and application architecture in turn - heavily influenced by functional style programming, but rarely promoted in the Object Oriented community.\r\n\r\n- Pursuit of purity in code: what, why and how\r\n- Deliberate and planned segregation of complexity\r\n- Separation of IO for cleaner architecture\r\n\r\nSome of the techniques introduced in this session may appear unconventional at first look, but would prove productive and reasonable (even obvious) as we dig deeper.\r\n", + "startsAt": "2019-06-20T11:40:00", + "endsAt": "2019-06-20T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "a7c88a64-b900-4c3c-a5c7-a2552528f533", + "name": "Hackle Wayne" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + { + "id": "98988", + "title": "Workshop: Save the plants with technology! 1/2", + "description": "Just got a new plant? Hard to keep it alive? Let´s use technology to give the plant a long and happy life! \r\nAt this work shop you will learn how to solder your own gadget with a specific micro control unit. ESP8266. This unit became very popular when it offered WIFI, analog GPIO, and several digital GPIO gates at the cost of a few dollars. We will use this to solder terminals and connect with a moisture sensor. The programming is not very advanced, however it will teach you how to read data and share online for the data to be used for latter visualization. All participants will get a goodiebag to be soldered, programmed and brought back home. The goodiebag contains a ESP8266 micro controller, moisture sensor and a personally designed circuit board. Bring your own laptop, and to save time please download and install Arduino IDE to be found at Arduino´s home page. \r\n", + "startsAt": "2019-06-20T13:40:00", + "endsAt": "2019-06-20T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "848e41e0-8f50-48eb-887b-6a2ef9f1f707", + "name": "Anja Bergby" + }, + { + "id": "076a93ed-fdd8-49db-b709-90b996807f6f", + "name": "Kristin Annabel Folland" + }, + { + "id": "3357f0ef-ace2-44c5-aff7-8a4b4e75de20", + "name": "Ragnhild Kosmo Holm" + }, + { + "id": "7070251f-eb37-4415-a24d-de1cd461fb4d", + "name": "Elise Garborg Undheim" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + { + "id": "128715", + "title": "Workshop: Save the plants with technology! Part 2/2", + "description": "Just got a new plant? Hard to keep it alive? Let´s use technology to give the plant a long and happy life!\r\n\r\nAt this work shop you will learn how to solder your own gadget with a specific micro control unit. ESP8266. This unit became very popular when it offered WIFI, analog GPIO, and several digital GPIO gates at the cost of a few dollars. We will use this to solder terminals and connect with a moisture sensor. The programming is not very advanced, however it will teach you how to read data and share online for the data to be used for latter visualization. All participants will get a goodiebag to be soldered, programmed and brought back home. The goodiebag contains a ESP8266 micro controller, moisture sensor and a personally designed circuit board. Bring your own laptop, and to save time please download and install Arduino IDE to be found at Arduino´s home page.", + "startsAt": "2019-06-20T15:00:00", + "endsAt": "2019-06-20T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "7070251f-eb37-4415-a24d-de1cd461fb4d", + "name": "Elise Garborg Undheim" + }, + { + "id": "076a93ed-fdd8-49db-b709-90b996807f6f", + "name": "Kristin Annabel Folland" + }, + { + "id": "848e41e0-8f50-48eb-887b-6a2ef9f1f707", + "name": "Anja Bergby" + }, + { + "id": "3357f0ef-ace2-44c5-aff7-8a4b4e75de20", + "name": "Ragnhild Kosmo Holm" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + { + "id": "98813", + "title": "Workshop: DIY – build your own React 1/2", + "description": "Are you using React, but don’t really know how it works? The framework is quite simple and do not require understanding the underlying mechanisms for most day to day tasks. This workshop will take your skills up a level, giving you a thorough understanding of React.\r\n\r\nYou will create a working version of React in less than 200 lines of code. It won’t be as efficient as React is. Nonetheless, you will gain valuable insight into how React work under the hood. We will demystify a lot of the concepts that are taken for granted when using React: representing the DOM-tree, rendering components, setting state and props, and re-rendering.", + "startsAt": "2019-06-20T16:20:00", + "endsAt": "2019-06-20T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "a9b0694d-8478-4b05-b368-e89d138323f8", + "name": "Svein Petter Gjøby" + }, + { + "id": "79cb3124-4d83-4b49-adcd-9035a0c45135", + "name": "Eirik Vigeland" + }, + { + "id": "e91a37c2-fe9c-46f2-bef4-2e67e2e114a9", + "name": "Henrik Hermansen" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + { + "id": "128716", + "title": "Workshop: DIY – build your own React - Part 2/2", + "description": "Are you using React, but don’t really know how it works? The framework is quite simple and do not require understanding the underlying mechanisms for most day to day tasks. This workshop will take your skills up a level, giving you a thorough understanding of React.\r\n\r\nYou will create a working version of React in less than 200 lines of code. It won’t be as efficient as React is. Nonetheless, you will gain valuable insight into how React work under the hood. We will demystify a lot of the concepts that are taken for granted when using React: representing the DOM-tree, rendering components, setting state and props, and re-rendering.", + "startsAt": "2019-06-20T17:40:00", + "endsAt": "2019-06-20T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e91a37c2-fe9c-46f2-bef4-2e67e2e114a9", + "name": "Henrik Hermansen" + }, + { + "id": "a9b0694d-8478-4b05-b368-e89d138323f8", + "name": "Svein Petter Gjøby" + }, + { + "id": "79cb3124-4d83-4b49-adcd-9035a0c45135", + "name": "Eirik Vigeland" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4504, + "name": "Room 11", + "sessions": [ + { + "id": "99515", + "title": "Workshop: Featureban (Experience before explanation!) Part 1/2", + "description": "During this Kanban workshop we are going to play the Featureban simulation game invented by Mike Burrows.\r\n\r\nFeatureBan is a simple and quick simulation that introduces several of the key concepts of Kanban, including visualization, feedback loops and limiting work in progress and lets participants learn by doing.\r\n\r\nKanban is a Lean change method that promotes continuous improvement through incremental change.\r\n\r\nOutline/Structure of the Workshop\r\n\r\nIntroduction and Simulation Instructions\r\n(Time to setup the boards and ask questions)\r\nIteration 1: we start with visual management\r\nIteration 2: we introduce things like WIP limits\r\nIteration 3: metrics\r\nWrap-up: Q&A, comments\r\nLearning Outcome\r\n\r\nParticipants will see how limiting WIP as part of a Kanban system produces flow. They can immediately use these concepts at their own workplace.\r\n\r\nTarget Audience\r\n\r\nFacilitators, Coaches, Anyone wanting more focus and results.\r\n\r\nStop Starting, Start Finishing!", + "startsAt": "2019-06-20T09:00:00", + "endsAt": "2019-06-20T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "3fe984d3-d973-46b0-b817-74d96fe6d939", + "name": "Maarten Hoppen" + } + ], + "categories": [], + "roomId": 4504, + "room": "Room 11" + }, + { + "id": "128713", + "title": "Workshop: Featureban (Experience before explanation!) Part 2/2", + "description": "During this Kanban workshop we are going to play the Featureban simulation game invented by Mike Burrows.\r\n\r\nFeatureBan is a simple and quick simulation that introduces several of the key concepts of Kanban, including visualization, feedback loops and limiting work in progress and lets participants learn by doing.\r\n\r\nKanban is a Lean change method that promotes continuous improvement through incremental change.\r\n\r\nOutline/Structure of the Workshop\r\n\r\nIntroduction and Simulation Instructions\r\n(Time to setup the boards and ask questions)\r\nIteration 1: we start with visual management\r\nIteration 2: we introduce things like WIP limits\r\nIteration 3: metrics\r\nWrap-up: Q&A, comments\r\nLearning Outcome\r\n\r\nParticipants will see how limiting WIP as part of a Kanban system produces flow. They can immediately use these concepts at their own workplace.\r\n\r\nTarget Audience\r\n\r\nFacilitators, Coaches, Anyone wanting more focus and results.\r\n\r\nStop Starting, Start Finishing!", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "3fe984d3-d973-46b0-b817-74d96fe6d939", + "name": "Maarten Hoppen" + } + ], + "categories": [], + "roomId": 4504, + "room": "Room 11" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4489, + "name": "Expo", + "sessions": [ + { + "id": "128960", + "title": "Party", + "description": "Kick back, get to know your fellow attendees and enjoy live music from the main stage. The party is complimentary for all NDC delegates. (18:40- 23:00)\r\n\r\nSchedule:\r\n\r\n- Conference Reception in the Expo\r\n- Fun talks with host Lars Klint\r\n- Dylan Beattie and the Linebreakers\r\n- LoveShack", + "startsAt": "2019-06-20T18:40:00", + "endsAt": "2019-06-20T23:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f99fa878-6176-4ff4-b151-c717fa5daf0c", + "name": "Lars Klint" + }, + { + "id": "1d7dcbfc-1de6-4228-8bd6-04f4ba1c4267", + "name": "Dylan Beattie" + } + ], + "categories": [], + "roomId": 4489, + "room": "Expo" + } + ], + "hasOnlyPlenumSessions": false + } + ], + "timeSlots": [ + { + "slotStart": "09:00:00", + "rooms": [ + { + "id": 4479, + "name": "Room 1", + "session": { + "id": "74808", + "title": "Getting Started with Cosmos DB + EF Core", + "description": "Cosmos DB is great and awesomely fast. Wouldn't be even more amazing if we could use our beloved entity framework to manage it? Let see how we can wire it up and get started", + "startsAt": "2019-06-20T09:00:00", + "endsAt": "2019-06-20T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "c739e2f1-ecf5-43e1-abcf-90cf13dd7b8f", + "name": "Thiago Passos" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + "index": 0 + }, + { + "id": 4480, + "name": "Room 2", + "session": { + "id": "86264", + "title": "Kotlin for C# Developers", + "description": "Dive into the latest craze in languages and platforms - Kotlin. This time we will be looking at it from the perspective of a .NET C# developer, draw comparisons between the languages, and bridge the gap between these 2 amazing languages.\r\n\r\nWe'll look at:\r\n- Kotlin as a language\r\n- Platforms Kotlin is great for\r\n- Object Oriented Implementations in Kotlin\r\n- Extended Features\r\n- Features Kotlin has that C# doesn't\r\n- A demo Android application in Kotlin vs a Xamarin.Android app in C#\r\n\r\nIn the end you will leave with a foundational knowledge of Kotlin and its capabilities to build awesome apps with less code. You should feel comfortable comparing C# applications to Kotlin applications and know where to find resources to learn even more!", + "startsAt": "2019-06-20T09:00:00", + "endsAt": "2019-06-20T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "42b758e4-1a7c-434d-9951-ddff53503d1f", + "name": "Alex Dunn" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + "index": 1 + }, + { + "id": 4481, + "name": "Room 3", + "session": { + "id": "99054", + "title": "How to use ML.NET to write crushing metal riffs", + "description": "ML.NET is still fairly fresh Microsoft venture into deep learning. It's written in .NET Core and a lot of good thinking went into it. It's definitely the best hope for .NET developers to do machine learning natively and easily incorporate it into existing apps. \r\n\r\nAnd to show its power we'll harness deep learning to help a metal band to get out of their rut by writing for them some awesome new riffs. \r\n\r\nFrom this talk, you'll learn how to use ML.NET, how some deep learning techniques like Recurrent Neural Networks work and how to write metal songs!\r\n", + "startsAt": "2019-06-20T09:00:00", + "endsAt": "2019-06-20T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "1cfbd2b6-db6f-405a-a997-e0c04e5f1510", + "name": "Michał Łusiak" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + "index": 2 + }, + { + "id": 4482, + "name": "Room 4", + "session": { + "id": "98350", + "title": "Terraform best practices with examples and arguments", + "description": "It is easy to get started with Terraform to manage infrastructure as code. Just read the documentation on terraform.io, and you are done. Almost.\r\n\r\nThe harder part begins when infrastructure grows in all directions (several AWS/GCP accounts, regions, teams, projects, environments, external integrations). One of the most frequent questions is \"how to structure code\".\r\n\r\nIn this talk, I will explain many of challenges related to that, what works, what does not work, why so, and most importantly I will show all the code which works from small projects to very-large infrastructures (featuring multi-cloud and multi-region setup).\r\n\r\nThis talk is best suitable for people who have been using Terraform at least for some time and already have practical questions, but there will be some basic information for newcomers also.\r\n\r\nAll the slides, code and material will be provided to attendees. Most of the content used for the talk you can find on my site here - www.terraform-best-practices.com", + "startsAt": "2019-06-20T09:00:00", + "endsAt": "2019-06-20T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "2bc0d4de-71fd-46da-94fa-4a50e289f9ab", + "name": "Anton Babenko" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + "index": 3 + }, + { + "id": 4483, + "name": "Room 5", + "session": { + "id": "84204", + "title": "Build your Cloud Operating Model on Azure from zero to hero", + "description": "In this session we will explore how organizations can establish a working cloud operating model in Azure that will help them keep control but also enable agility for their teams, so together they can deliver value to the business. The session is targeting DevOps and PlatformOps teams. Certain level of knowledge of Azure is expected (like Resource Manager, RBAC, Policies, Azure Monitor). We will explore some new capabilities like Azure Blueprints and Resource Graph and how can you leverage them and other essential services like Security Center, Service Health, and Log Analytics to build the model, gain insights into your day-to-day operations, collect telemetry you need, automate some key processes using serverless components and integrate your favorite tools (like Slack, GitHub, etc.). By the end of this demo-packed session we should have a working model the participants can fork from GitHub, customize to fit their needs, and apply in their environment.", + "startsAt": "2019-06-20T09:00:00", + "endsAt": "2019-06-20T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "6e75977d-ea56-466a-9095-9cf793af25bd", + "name": "David Pazdera" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + "index": 4 + }, + { + "id": 4484, + "name": "Room 6", + "session": { + "id": "75536", + "title": "Pragmatic Performance: When to care about perf, and what to do about it.", + "description": "As a developer you often here both that performance is important, but also that you shouldn't worry about performance up front, so when is the right time to think about it? And if the time is right, what are you actually supposed to do?\r\n\r\nIf you're interested to hear about a pragmatic approach to performance, this talk will explain when is the right time to think about benchmarking, but more importantly will run through how to correctly benchmark .NET code so any decisions made will be based on information about your code that is trustworthy.\r\n\r\nAdditionally you'll also find out about some of the common, and some of the unknown, performance pitfalls of the .NET Framework and we'll discuss the true meaning behind the phrase \"premature optimization is the root of all evil\".", + "startsAt": "2019-06-20T09:00:00", + "endsAt": "2019-06-20T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "604507ba-fd96-4c48-a29a-67a95760d888", + "name": "David Wengier" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + "index": 5 + }, + { + "id": 4485, + "name": "Room 7", + "session": { + "id": "99154", + "title": "Hack to the Future", + "description": "Infosec is a continual game of one-upmanship; we build a defence and someone breaks it so we build another one then they break that and the cycle continues. Because of this, the security controls we have at our disposal are rapidly changing and the ones we used yesterday are very often useless today.\r\n\r\nThis talk focuses on what the threats look like *today*. What are we getting wrong, how do we fix it and how do we stay on top in an environment which will be different again tomorrow to what it is today. It's a real-world look at modern defences that everyone building online applications will want to see.", + "startsAt": "2019-06-20T09:00:00", + "endsAt": "2019-06-20T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "735a4b60-42e8-4452-9480-68197372c206", + "name": "Troy Hunt" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + "index": 6 + }, + { + "id": 4486, + "name": "Room 8", + "session": { + "id": "86523", + "title": "A practical guide to deep learning", + "description": "Machine Learning is one of the fastest growing areas of computer science, and Deep Learning (neural networks) is growing even faster, with lots of data and computing power at our fingertips. \r\nThis talk is a practical (very little math) guide to computer vision and deep learning.\r\n\r\nWe will look at a deep learning project from start to finish, look at how to program and train a neural network and gradually refine it using some tips and tricks that you can steal for your future deep learning projects.", + "startsAt": "2019-06-20T09:00:00", + "endsAt": "2019-06-20T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "cb70e0f2-0f0b-4b8f-b3f4-a9326309a1b2", + "name": "Tess Ferrandez-Norlander" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + "index": 7 + }, + { + "id": 4487, + "name": "Room 9", + "session": { + "id": "86058", + "title": "The New Frontier: A Gentle Introduction to Rust", + "description": "The Rust programming language is systems oriented language that has captured attention and love of software developers and proved to have a great adoption, having being voted the most loved programming language for the last three years in the StackOverflow Developer survey.\r\n\r\nMy session will be an introduction to Rust programming language for developers interested in the language, it's characteristics, strengths and real world usage.\r\n\r\nThe outline of my session will be :\r\n- Why Rust: \r\n * the problems it aims to solve.\r\n- Rust's Defining Features: \r\n * what makes rust Rust.\r\n- Rust's Ecosystem, maturity and production readiness.\r\n * areas where Rust application suits and the state of maturity, libraries and support.\r\n- Real world Rust usage:\r\n * show how Rust has been leverage in real world usage\r\n- Where do I start: how to adopt Rust with your organisation\r\n * next steps if you think Rust is a good fit for you.\r\n\r\nRust is a language that empowers everyone to write efficient and reliable software. It encourages fearless hacking and this talk is really meant to exemplify this! My aim to encourage fellow engineers to embrace it and reap from the benefits it brings.\r\n\r\n\r\nThanks\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n", + "startsAt": "2019-06-20T09:00:00", + "endsAt": "2019-06-20T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "16088c49-02b3-47f5-b383-f021aef73075", + "name": "Matthew Gathu" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + "index": 8 + }, + { + "id": 4504, + "name": "Room 11", + "session": { + "id": "99515", + "title": "Workshop: Featureban (Experience before explanation!) Part 1/2", + "description": "During this Kanban workshop we are going to play the Featureban simulation game invented by Mike Burrows.\r\n\r\nFeatureBan is a simple and quick simulation that introduces several of the key concepts of Kanban, including visualization, feedback loops and limiting work in progress and lets participants learn by doing.\r\n\r\nKanban is a Lean change method that promotes continuous improvement through incremental change.\r\n\r\nOutline/Structure of the Workshop\r\n\r\nIntroduction and Simulation Instructions\r\n(Time to setup the boards and ask questions)\r\nIteration 1: we start with visual management\r\nIteration 2: we introduce things like WIP limits\r\nIteration 3: metrics\r\nWrap-up: Q&A, comments\r\nLearning Outcome\r\n\r\nParticipants will see how limiting WIP as part of a Kanban system produces flow. They can immediately use these concepts at their own workplace.\r\n\r\nTarget Audience\r\n\r\nFacilitators, Coaches, Anyone wanting more focus and results.\r\n\r\nStop Starting, Start Finishing!", + "startsAt": "2019-06-20T09:00:00", + "endsAt": "2019-06-20T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "3fe984d3-d973-46b0-b817-74d96fe6d939", + "name": "Maarten Hoppen" + } + ], + "categories": [], + "roomId": 4504, + "room": "Room 11" + }, + "index": 10 + } + ] + }, + { + "slotStart": "10:20:00", + "rooms": [ + { + "id": 4479, + "name": "Room 1", + "session": { + "id": "98994", + "title": "Deep Learning in the world of little ponies", + "description": "In this talk, we will discuss computer vision, one of the most common real-world applications of machine learning. We will deep dive into various state-of-the-art concepts around building custom image classifiers - application of deep neural networks, specifically convolutional neural networks and transfer learning. We will demonstrate how those approaches could be used to create your own image classifier to recognise the characters of \"My Little Pony\" TV Series [or Pokemon, or Superheroes, or your custom images].", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "b4c506ac-9757-4ac6-8b7c-3d6696b113e4", + "name": "Galiya Warrier" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + "index": 0 + }, + { + "id": 4480, + "name": "Room 2", + "session": { + "id": "99197", + "title": "Kotlin coroutines: new ways to do asynchronous programming", + "description": "The async/await feature allows you to write the asynchronous code in a straightforward way, without a long list of callbacks. Used in C# for quite a while already, it has proven to be extremely useful. In Kotlin you have async and await as library functions implemented using coroutines.\r\n\r\nA coroutine is a light-weight thread that can be suspended and resumed later. Very precise definition, but might be confusing at first. What 'light-weight thread' means? How does suspension work? This talk uncovers the magic.\r\nWe'll discuss the concept of coroutines, the power of async/await, and how you can benefit from defining your asynchronous computations using suspend functions.", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "0f769b19-d5f2-49fb-aa78-a086aa046b7e", + "name": "Svetlana Isakova" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + "index": 1 + }, + { + "id": 4481, + "name": "Room 3", + "session": { + "id": "86691", + "title": "An Introduction to WebAssembly", + "description": "Want to write a web application? Better get familiar with JavaScript! JavaScript has long been the king of front-end. While there have been various attempts to dethrone it, they have typically involved treating JavaScript as an assembly-language analog that you transpile your code to. This has lead to complex build pipelines that result in JavaScript which the browser has to parse and *you* still have to debug. But what if there were an actual byte-code language you could compile your non-JavaScript code to instead? That is what WebAssembly is.\r\n\r\nI'm going to explain how WebAssembly works and how to use it in this talk. I'll cover what it is, how it fits into your application, and how to build and use your own WebAssembly modules. And, I'll demo how to build and use those modules with Rust, C++, and the WebAssembly Text Format. That's right, I'll be live coding in an assembly language. I'll also go over some online resources for other languages and tools that make use of WebAssembly.\r\n\r\nWhen we're done, you'll have the footing you need to start building applications featuring WebAssembly. So grab a non-JavaScript language, a modern browser, and let's and get started!", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "520bf4ca-b2d3-47c3-8475-c25bb2b257f7", + "name": "Guy Royse" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + "index": 2 + }, + { + "id": 4482, + "name": "Room 4", + "session": { + "id": "97523", + "title": "How to be cool in the age of legacy", + "description": "The cloud is here. And we can safely assume it's here to stay.\r\n\r\nThe road forward is pretty clear. Containerization using something like Docker and orchestration using something like Kubernetes. And it's great! Workloads are automatically distributed, new servers can be added and removed with (or without!) the click of a button.\r\n\r\nBut then there is everything else. The 36 .NET framework applications that will take years to migrate. The third party products with support end-of-life from 2017 that are still business critical. Do you leave that stuff behind?\r\n\r\nAt RiksTV we've found a way to work on moving towards a modern cloud infrastructure without throwing out all the legacy code. Using AWS EC2, Ansible, Octopus Deploy, Consul and Traefik we've built a fully automated infrastructure that allows us to scale out applications in a matter of minutes – with (or without) the click of a button!\r\n\r\nIn this talk you'll get a under the covers look at how you can build a modern infrastructure for running old fashioned applications in the cloud. You'll get inspiration, experiences and tooling that helps you get to the cloud – even if you're living in an age of legacy.", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "7577e0ae-3f98-4649-a043-7dc915581546", + "name": "Jøran Vagnby Lillesand" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + "index": 3 + }, + { + "id": 4483, + "name": "Room 5", + "session": { + "id": "98578", + "title": "Heterogeneous pipeline processing with Kubernetes and Google Cloud Pub/Sub", + "description": "At Spacemaker, we are building a product for real estate developers and architects leveraging AI methodologies and massive computing power to maximize the potential of any building site. At the core of our platform's AI engine, we have CPU-intensive optimization and search algorithms, memory-demanding simulations, and GPU-optimized machine learning and computer graphics techniques None of these components, however, are equal in terms of resource requirements. Depending on the input size, some components complete within a couple of milliseconds using one CPU, while other components have run time of hours even with several hundred CPUs. Finally, one of our core values at Spacemaker's is the complete autonomy of every product team. This autonomy enables the teams to make their own choices regarding programming languages and libraries but also on their general approach to the problems on hand.\r\n\r\nThe challenges outlined above requires a really flexible pipeline. We have, therefore, replaced our old batch-oriented pipeline with an asynchronous, message-based pipelined built on Kubernetes and Google Pub/Sub. At the core of this pipeline, we find a central message broker that dispatches units of work onto a set of queues, where the broker takes care of task dependencies and ensures the pipeline executions run to their completion. The dispatched tasks are processed by a set of workers deployed to a shared, auto-scaled Kubernetes cluster. This offers elasticity and scalability for the workers and their respective resource requirements. By structuring the pipeline in this way the teams are free to develop individual components using whichever programming languages and tools they see fit, allowing for each component to have different resource requirements.\r\n\r\nIn this presentation I will start off with presenting our old, batch oriented pipeline, discussing why it needed replacement and the research leading up to the design of our new pipeline. I will then elaborate further on the details of our auto-scaling including how we handle the burst workloads by adding new resources to our Kubernetes cluster based on the queue lengths for the workers. Then, I will dig into the details of our message broker, the API and the code used in our pipeline workers. Finally I will wrap-up my presentation highlighting som key performance results and my thoughts on the potential surrounding modularizing a pipeline to enable more general use cases.", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "4e459fd7-73f8-41fc-8c59-e80154a0878e", + "name": "Håkon Åmdal" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + "index": 4 + }, + { + "id": 4484, + "name": "Room 6", + "session": { + "id": "100426", + "title": "Bulletproof Transient Error Handling with Polly", + "description": "Connected applications only work when connected. What happens if the network breaks temporarily? Will your system recover smoothly or pitch a fit? Using an OSS project called Polly (available on GitHub) you can handle this and many other transient situations with elegance and fluency. Polly let’s you define retry policies using standard patterns such as retry, retry forever, wait and retry, and circuit breaker. Learn how to make your system bulletproof with Polly and a little know-how.", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "6d1065d2-3494-48a6-a6bb-7efde3d8de40", + "name": "Carl Franklin" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + "index": 5 + }, + { + "id": 4485, + "name": "Room 7", + "session": { + "id": "78506", + "title": "A practical look at security and identity in ASP.NET Core and Entity Framework Core", + "description": "This is a talk about what happened when a client asked me to build a big, multi-tenant web application, and they said “we have quite a complex set of rules on what our user can do”. That turned into quite a journey.\r\n\r\nIn this session I will take you through the design we used to get ASP.NET Core and Entity Framework Core to provide both feature-level authorisation (e.g. controlling what Web APIs/pages the user can access) and data-level authorisation (i.e. controlling what data they can see).", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e193d34d-e2ed-4042-960c-c5357c33cd39", + "name": "Jon P Smith" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + "index": 6 + }, + { + "id": 4486, + "name": "Room 8", + "session": { + "id": "77149", + "title": "Write your own domain specific language with F#", + "description": "F# is a powerful and expressive multi-paradigm language with high performance and focus on functional programming. This language allows you to write code, which a non technical person would be able to read and understand. In this talk I will show you how to write your own strongly and statically typed DSL. With it you will be able to focus on business logic and not get distracted with \"keyword\" noise.", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "2720a9e3-3c9e-4b2b-9472-e7b7b0de19d5", + "name": "Mikhail Smal" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + "index": 7 + }, + { + "id": 4487, + "name": "Room 9", + "session": { + "id": "98949", + "title": "Mirror mirror on the wall, what is the vainest metric of them all?", + "description": "You may have heard development teams talking about the number of deploys they make a day or the number of PRs merged a day. You may have heard marketing teams talk about the number of page views a day. What do these metrics even mean? Are they actually useful to the business as a whole?\r\n\r\nIn this talk, Paul will debunk the idea of “vanity” metrics and why using these as a guide to success has only one outcome. This is a talk intended for all parts of an organisation to really help understand what metrics can do for us and why a metric may not mean what you believe it does\r\n\r\nBehind every vanity metric is a real metric that can help us understand the health of our company - whether it be the ability to understand our users or the ability to understand the value of a feature\r\n\r\nWe just need to step back and think about what it actually is...", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "18f368cc-86e7-4921-9f9a-587e7ef037ea", + "name": "Paul Stack" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + "index": 8 + }, + { + "id": 4488, + "name": "Room 10", + "session": { + "id": "85978", + "title": "Workshop: Pragmatic unit testing now - Part 1/2", + "description": "At the age of cloud and serverless, unit testing remains very relevant if not more so. Yet we keep seeing resistance and frustration around unit testing.\r\n\r\nPrerequisite\r\nBring a laptop with .NET Core, Git + an I.D.E. installed (e.g. Visual Studio Code).\r\nWe will be coding in C# but the ideas are not tied to it. Plus the code project should be straight-forward enough.\r\nPaper programmers welcome too!\r\nSlightly more reading for overachievers https://github.com/hackle/putn\r\n\r\nFor this workshop we:\r\n\r\n- explore why that is,\r\n- expose disadvantages of questionable yet popular practices in the industry,\r\n- gradually address blockers to efficient unit testing\r\n- and advance a pragmatic & practical approach to application architecture and unit testing, which can help teams adopt quickly and benefit immediately.\r\n\r\nA way of unit testing - and application architecture in turn - heavily influenced by functional style programming, but rarely promoted in the Object Oriented community.\r\n\r\n- Pursuit of purity in code: what, why and how\r\n- Deliberate and planned segregation of complexity\r\n- Separation of IO for cleaner architecture\r\n\r\nSome of the techniques introduced in this session may appear unconventional at first look, but would prove productive and reasonable (even obvious) as we dig deeper.\r\n", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "a7c88a64-b900-4c3c-a5c7-a2552528f533", + "name": "Hackle Wayne" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + "index": 9 + }, + { + "id": 4504, + "name": "Room 11", + "session": { + "id": "128713", + "title": "Workshop: Featureban (Experience before explanation!) Part 2/2", + "description": "During this Kanban workshop we are going to play the Featureban simulation game invented by Mike Burrows.\r\n\r\nFeatureBan is a simple and quick simulation that introduces several of the key concepts of Kanban, including visualization, feedback loops and limiting work in progress and lets participants learn by doing.\r\n\r\nKanban is a Lean change method that promotes continuous improvement through incremental change.\r\n\r\nOutline/Structure of the Workshop\r\n\r\nIntroduction and Simulation Instructions\r\n(Time to setup the boards and ask questions)\r\nIteration 1: we start with visual management\r\nIteration 2: we introduce things like WIP limits\r\nIteration 3: metrics\r\nWrap-up: Q&A, comments\r\nLearning Outcome\r\n\r\nParticipants will see how limiting WIP as part of a Kanban system produces flow. They can immediately use these concepts at their own workplace.\r\n\r\nTarget Audience\r\n\r\nFacilitators, Coaches, Anyone wanting more focus and results.\r\n\r\nStop Starting, Start Finishing!", + "startsAt": "2019-06-20T10:20:00", + "endsAt": "2019-06-20T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "3fe984d3-d973-46b0-b817-74d96fe6d939", + "name": "Maarten Hoppen" + } + ], + "categories": [], + "roomId": 4504, + "room": "Room 11" + }, + "index": 10 + } + ] + }, + { + "slotStart": "11:40:00", + "rooms": [ + { + "id": 4479, + "name": "Room 1", + "session": { + "id": "80032", + "title": "Living in eventually consistent reality", + "description": "Strongly consistent databases are dominating world of software. However, with increasing scale and global availability of our services, many developers often prefer to loose their constraints in favor of an eventual consistency. \r\n\r\nDuring this presentation we'll talk about Conflict-free Replicated Data Types (CRDT) - an eventually-consistent structures, that can be found in many modern day multi-master, geo-distributed databases such as CosmosDB, DynamoDB, Riak, Cassandra or Redis: how do they work and what makes them so interesting choice in highly available systems.", + "startsAt": "2019-06-20T11:40:00", + "endsAt": "2019-06-20T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "6373f8a6-11a6-43e9-b1ee-a898dd02d1ce", + "name": "Bartosz Sypytkowski" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + "index": 0 + }, + { + "id": 4480, + "name": "Room 2", + "session": { + "id": "78448", + "title": "Developing Kernel Drivers with Modern C++", + "description": "Kernel drivers are traditionally written in C, but today drivers can be built with the latest C++ standards. The session presents examples and best practices when developing kernel code with C++", + "startsAt": "2019-06-20T11:40:00", + "endsAt": "2019-06-20T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "3b2b49cf-5746-484c-a85e-be960fe76043", + "name": "Pavel Yosifovich" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + "index": 1 + }, + { + "id": 4481, + "name": "Room 3", + "session": { + "id": "99526", + "title": "Pointless or Pointfree?", + "description": "With the emergence of functional programming in mainstream JavaScript, point-free programming style (also known as tacit programming) is gaining traction. If you ever used RxJS you'll know what I'm talking about...\r\n\r\nIn this talk, we'll explore the motivation behind it and discover some interesting consequences. After imposing a strict set of rules, we'll try and solve a small practical problem and see where does that take us. This talk is a mix of presentation and live coding with examples in JavaScript.", + "startsAt": "2019-06-20T11:40:00", + "endsAt": "2019-06-20T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "c51fb01c-63d1-4b84-92d0-231f1fe3673c", + "name": "Damjan Vujnovic" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + "index": 2 + }, + { + "id": 4482, + "name": "Room 4", + "session": { + "id": "97687", + "title": "Practical Chaos Engineering: breaking things on purpose to make them more resilient against failure", + "description": "With the wide adoption of micro-services and large-scale distributed systems, architectures have grow increasingly complex and hard to understand. Worse, the software systems running them have become extremely difficult to debug and test, increasing the risk of outages. With these new challenges, new tools are required and since failures have become more and more chaotic in nature, we must turn to chaos engineering in order to reveal failures before they become outages. In this talk, I will first introduce chaos engineering and show the audience how to start practicing chaos engineering on the AWS cloud. I will walk through the tools and methods they can use to inject failures in their architecture in order to make them more resilient to failure.", + "startsAt": "2019-06-20T11:40:00", + "endsAt": "2019-06-20T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e4fd745a-8a49-43d3-8763-020a4f3512ab", + "name": "Adrian Hornsby" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + "index": 3 + }, + { + "id": 4483, + "name": "Room 5", + "session": { + "id": "98923", + "title": "Life Beyond Distributed Transactions: An Apostate's Implementation", + "description": "Over a decade ago, Pat Helland authored his paper, \"Life Beyond Distributed Transactions: An Apostate's Opinion\" describing a means to coordinate activities between entities in databases when a transaction encompassing those entities wasn't feasible or possible. While the paper and subsequent talks provided great insight in the challenges of coordinating activities across entities in a single database, implementations were left as an exercise to the reader!\r\n\r\nFast forward to today, and now we have NoSQL databases, microservices, message queues and brokers, HTTP web services and more that don't (and shouldn't) support any kind of distributed transaction.\r\n\r\nIn this session, we'll look at how to implement coordination between non-transactional resources using Pat's paper as a guide, with examples in Azure Cosmos DB, Azure Service Bus, and Azure SQL Server. We'll look at a real-world example where a codebase assumed everything would be transactional and always succeed, but production proved us wrong! Finally, we'll look at advanced coordination workflows such as Sagas to achieve robust, scalable coordination across the enterprise.", + "startsAt": "2019-06-20T11:40:00", + "endsAt": "2019-06-20T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f109dd0b-9441-4cbf-8664-19c021a6de4a", + "name": "Jimmy Bogard" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + "index": 4 + }, + { + "id": 4484, + "name": "Room 6", + "session": { + "id": "98473", + "title": "Building a parser in C#, from first principles", + "description": "A simple query language is often more usable than a gigantic search form. A small domain-specific language can sometimes be much more succinct and expressive than a method-driven API. Parsing and language implementation belong in the toolbox of every working programmer.\r\n\r\nUnfortunately, the first time most of us encounter parser construction, it's in an academic setting that surveys the entire sophisticated and rather daunting field. This makes it easy to mistake language implementation for a specialist area, when in fact, parsers for even very complex languages can be built in plain C# using just a few simple patterns.\r\n\r\nCome along to this session to level-up your language implementation skills. We'll distill the nature of the task, the essential techniques on hand, and build a parser using tools you can introduce into your real-world applications and libraries.", + "startsAt": "2019-06-20T11:40:00", + "endsAt": "2019-06-20T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "57f3370f-81bd-43a3-b0ed-acb40cc70035", + "name": "Nicholas Blumhardt" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + "index": 5 + }, + { + "id": 4485, + "name": "Room 7", + "session": { + "id": "97725", + "title": "Security Static Analysis - Avoiding an Angry Mob of Engineers", + "description": "The idea of Security Static Analysis is promising - point a tool at source code and magically find all of the security mistakes, hurray! Clearly several organizations think so, as many compliance regimes require its usage, and most secure development guidance recommend it. In reality adopting static analysis into a development process is incredibly challenging, and can easily both fail to meet security objections and enrage the software engineers. This talk draws on many painful lessons learned deploying static analysis in several engineering organizations, with the goal of helping the audience better evaluate tools in the space, and have higher success deploying them.", + "startsAt": "2019-06-20T11:40:00", + "endsAt": "2019-06-20T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "2d2346a9-ce85-4160-aa7d-3aaab29ad067", + "name": "Josh Brown-White" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + "index": 6 + }, + { + "id": 4486, + "name": "Room 8", + "session": { + "id": "85869", + "title": "Functional Web Programming in .Net with the SAFE Stack", + "description": "The SAFE stack is an open source stack of libraries and tools which simplify the process of building type safe web applications which run on the cloud almost entirely in F#. \r\n\r\nIn this talk we'll explore the components of the SAFE stack and how they can be used to write web services and web sites in idiomatic F#. We'll see how we can manage this without needing to compromise and use object oriented frameworks whilst also still integrating with the existing ASP.Net, JavaScript and React ecosystems. We'll consider how we can write backend applications using Saturn on top of ASP.Net, we'll look at how to run F# in the web browser with Fable and we'll cover how we can develop interactive web applications leveraging the benefits of functional programming. This talk is aimed at developers who are looking to understand how they can use F# to effectively build full stack web applications.", + "startsAt": "2019-06-20T11:40:00", + "endsAt": "2019-06-20T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "71cb7875-d2d8-45d1-ae12-7687bae03200", + "name": "Anthony Brown" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + "index": 7 + }, + { + "id": 4487, + "name": "Room 9", + "session": { + "id": "99529", + "title": "The Moon: Gateway to the Solar System", + "description": "In 1972, the last human to walk on the Moon headed back to Earth. Is it time to go back? Join Richard Campbell as he explores the potential of a return of humans to the Moon. \r\n\r\nMuch has been learned about the Moon since the Apollo missions, and interest in the Moon as a place of science, exploration and learning is growing. Even today there are new spacecraft and new science being done on and around the Moon. The Moon can be a catalyst to humankind traveling the solar system - it's time to go back!", + "startsAt": "2019-06-20T11:40:00", + "endsAt": "2019-06-20T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "7a34a7fc-2f1c-4751-af4f-18a21de0e6b3", + "name": "Richard Campbell" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + "index": 8 + }, + { + "id": 4488, + "name": "Room 10", + "session": { + "id": "128714", + "title": "Workshop: Pragmatic unit testing now - Part 2/2", + "description": "At the age of cloud and serverless, unit testing remains very relevant if not more so. Yet we keep seeing resistance and frustration around unit testing.\r\n\r\nPrerequisite\r\nBring a laptop with .NET Core, Git + an I.D.E. installed (e.g. Visual Studio Code).\r\nWe will be coding in C# but the ideas are not tied to it. Plus the code project should be straight-forward enough.\r\nPaper programmers welcome too!\r\nSlightly more reading for overachievers https://github.com/hackle/putn\r\n\r\nFor this workshop we:\r\n\r\n- explore why that is,\r\n- expose disadvantages of questionable yet popular practices in the industry,\r\n- gradually address blockers to efficient unit testing\r\n- and advance a pragmatic & practical approach to application architecture and unit testing, which can help teams adopt quickly and benefit immediately.\r\n\r\nA way of unit testing - and application architecture in turn - heavily influenced by functional style programming, but rarely promoted in the Object Oriented community.\r\n\r\n- Pursuit of purity in code: what, why and how\r\n- Deliberate and planned segregation of complexity\r\n- Separation of IO for cleaner architecture\r\n\r\nSome of the techniques introduced in this session may appear unconventional at first look, but would prove productive and reasonable (even obvious) as we dig deeper.\r\n", + "startsAt": "2019-06-20T11:40:00", + "endsAt": "2019-06-20T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "a7c88a64-b900-4c3c-a5c7-a2552528f533", + "name": "Hackle Wayne" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + "index": 9 + } + ] + }, + { + "slotStart": "13:40:00", + "rooms": [ + { + "id": 4479, + "name": "Room 1", + "session": { + "id": "98933", + "title": "Is AI right for me?", + "description": "Artificial intelligence (AI) has become a form of Swiss Army knife for the enterprise world. If you have a data problem, throw some AI at it! However, this mentality can lead to wasted time and money going down the path of implementing a heavy-handed solution that doesn’t fit your business problem. Navigating the waters of AI, machine learning and data analysis can be tricky, especially when being sold by the myriad of data science and AI companies offering solutions at the enterprise level. But fear not, some simple guidelines can help. In this talk, I will present a basic rubric for evaluating AI and data analytics techniques as potential solutions for enterprise business problems.", + "startsAt": "2019-06-20T13:40:00", + "endsAt": "2019-06-20T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e1864dca-8a88-4ea7-840a-20b88702b38f", + "name": "Amber McKenzie" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + "index": 0 + }, + { + "id": 4480, + "name": "Room 2", + "session": { + "id": "81208", + "title": "Accessibility: Coding and Beyond", + "description": "Accessibility is for everyone and is a responsibility of all team members. While a lot of web accessibility guidelines are focused on coding, there are other accessibility components that all team members need to consider in order to improve the overall product or service from the beginning of any projects. Sveta will share her personal experience as a deaf person and some examples of accessibility issues and solutions. They may be new to some and sound like common sense to others, but sadly there are many products and services that fail at accessibility. The talk will help developers and their team members better understand why accessibility is not just about coding and why it's not to be used as an afterthought.", + "startsAt": "2019-06-20T13:40:00", + "endsAt": "2019-06-20T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "ddff421a-de84-4d8f-9d2a-e799ea9c5055", + "name": "Svetlana Kouznetsova" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + "index": 1 + }, + { + "id": 4481, + "name": "Room 3", + "session": { + "id": "99250", + "title": "The Seven Deadly Presentation Sins", + "description": "What makes a great presentation? More importantly, what are the elements that can destroy a great presentation, even if the content itself is technically sound? \r\n\r\nIn this session Samantha and Andrew Coates demonstrate seven sins that must not be committed in a presentation, why and how a presentation can suffer from committing them, and how to avoid accidently committing them. \r\n\r\nIronically, when we practice we deliberately commit presentation sins. We stop, we fix, we repeat and refine. Like elite musicians, dedicated technical presenters typically spend many solitary hours doing this, which of course is necessary to master any content. But none of these practice processes has a place on the presentation stage. In presentation we must trust, believe, create, and keep going in the face of any adversity – a completely different process which in itself must be rehearsed. \r\nIn order to give a magnificent presentation, we must PRACTICE giving a magnificent presentation. The only way to do this is by regularly and deliberately creating pressure situations in which we can practice NOT committing the presentation sins.\r\n\r\nCovering everything from wrong notes to blue screens of death, this dynamic and multi-talented pair not only break down the elements of successful and unsuccessful presentations, but also outline how one can give a truly engaging presentation every time, no matter how basic or complex the content.", + "startsAt": "2019-06-20T13:40:00", + "endsAt": "2019-06-20T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "2809c750-dc83-4e1c-8f06-38ee96b818b6", + "name": "Andrew Coates" + }, + { + "id": "0e2bfca8-149b-49f8-88d4-bd6558e8f11e", + "name": "Samantha Coates" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + "index": 2 + }, + { + "id": 4482, + "name": "Room 4", + "session": { + "id": "99874", + "title": "Lightning Talks (Web)", + "description": "Lightning talks (approx 10-15 minutes each)\r\n\r\nTalk 1: Why you should think twice before choosing CosmosDB - Torstein Nicolaysen\r\n\r\nCosmos DB promises some amazing things, and in all fairness, it’s a pretty cool product. My team has been using Cosmos DB on a system that requires both high levels of performance and uptime. After hours of design sessions, experimentation, performance testing, rewriting the document structure, using new partition keys, faking consistency in the application and several other attempts to make it work for us, we felt that CosmosDB was a bad fit for our use case. The system we work on is in production, and my experience is based on real-world usage.\r\n\r\nThis lightning talk will explain some of the issues we faced, what we learned and give some advice on using Cosmos DB. It won’t be all doom and gloom, and you'll even hear some scenarios were Cosmos DB is a perfect match.\r\n-----------------------------------------------\r\n\r\nTalk 2: How we messed everything up but still got LoRa to the stratosphere - Sindre Lindstad\r\n\r\nBack in the early 2010's people were sending all sorts of tech trash into space using helium balloons and styrofoam boxes.\r\n\r\nA friend and I decided we wanted to do the same thing, but by making everything from scratch. All the way from the PCB's and antennas, down to the web API's and map applications to track it.\r\n\r\nAnd we... sort of made it.\r\n\r\nThis is a story about technology, friendship, and lots and lots of duct tape.\r\n\r\n---------------------------------------------\r\n\r\nTalk 3: Mobile AR in 10 minutes - Kristina Simakova\r\n\r\nA crash course into mobile AR. This talk will give you an overview and a current status on mobile AR technology and SDKs, its new features and shortcomings.\r\n\r\n--------------------------------------------\r\n\r\nTalk 4: I didn't know that - Stefan Judis\r\n\r\n Web Development is a constant journey of new technologies and new things to learn. A year ago I started documenting and sharing all the tiny things that I didn't know before and stopped being anxious about others thinking that I'm not smart. \r\n\r\nLet me tell you what I learned about JavaScript!\r\n\r\n---------------------------------------------\r\n\r\nTalk 5: What's cooking for JavaScript: a look at current TC39 proposals - Branislav Jenco\r\n\r\nIn this lightning talk, I go over the current proposals for new language features in JavaScript and their current status. Pipelines, decorators, null coalescing and more is coming, but when? And how will it look like?\r\n\r\n-------------------------------------------", + "startsAt": "2019-06-20T13:40:00", + "endsAt": "2019-06-20T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "c0d7c2e8-1f0b-4586-b3a0-dbd18227ca62", + "name": "Torstein Nicolaysen" + }, + { + "id": "5ec0ca76-bf24-4fce-bf3d-80656dadf1f6", + "name": "Sindre Lindstad" + }, + { + "id": "6d9319c9-0ad9-4b51-85ac-b55c227be8ec", + "name": "Kristina Simakova" + }, + { + "id": "3dd820f5-722b-496e-8430-ccc3b8ec7a75", + "name": "Stefan Judis" + }, + { + "id": "028d7685-2c9f-4322-8120-f60ac8ef7893", + "name": "Branislav Jenco" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + "index": 3 + }, + { + "id": 4483, + "name": "Room 5", + "session": { + "id": "127290", + "title": "Monolith Decomposition Patterns", + "description": "Patterns to help you incrementally migrate from a monolith to microservices.\r\n\r\nBig Bang rebuilds of systems is so 20th century. With our users expecting new functionality to be shipped ever more frequently than before, we no longer have the luxury of a complete system rebuild. In fact, a Big Bang migration of a Monolithic architecture into a microservice architecture can be especially problematic, as we’ll explore in this talk.\r\nWe want to ship features, but we also want to change our architecture - and many of us want to be able to break down existing systems into microservice architectures. But how do you do this while still shipping features?\r\n\r\nIn this talk, I’ll share with you some key principles and a number of patterns which you can use to incrementally decompose an existing system into microservices. I’ll even cover off patterns that can work to migrate functionality out of systems you can’t change, making them useful when working with very old systems or vendor products. We'll look at the use of stranger patterns, change data capture, database decomposition and more.", + "startsAt": "2019-06-20T13:40:00", + "endsAt": "2019-06-20T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "006d28cc-1e6f-48af-81d7-58314daa92ce", + "name": "Sam Newman" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + "index": 4 + }, + { + "id": 4484, + "name": "Room 6", + "session": { + "id": "99517", + "title": "Blazor, a new framework for browser-based .NET apps", + "description": "Today, nearly all browser-based apps are written in JavaScript (or similar languages that transpile to it). That’s fine, but there’s no good reason to limit our industry to basically one language when so many powerful and mature alternate languages and programming platforms exist. Starting now, WebAssembly opens the floodgates to new choices, and one of the first realistic options may be .NET.\r\n\r\nBlazor is a new experimental web UI framework from the ASP.NET team that aims to brings .NET applications into all browsers (including mobile) via WebAssembly. It allows you to build true full-stack .NET applications, sharing code across server and client, with no need for transpilation or plugins.\r\n\r\nIn this talk I’ll demonstrate what you can do with Blazor today and how it works on the underlying WebAssembly runtime behind the scenes. You’ll see its modern, component-based architecture (inspired by modern SPA frameworks) at work as we use it to build a responsive client-side UI. I’ll cover both basic and advanced scenarios using Blazor’s components, router, DI system, JavaScript interop, and more.", + "startsAt": "2019-06-20T13:40:00", + "endsAt": "2019-06-20T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "0c555530-fbd8-49f4-831a-6b30d15c2966", + "name": "Steve Sanderson" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + "index": 5 + }, + { + "id": 4485, + "name": "Room 7", + "session": { + "id": "82788", + "title": "Privacy and GDPR: What all developers should know", + "description": "On May 25th the European Union enacted new privacy laws that apply uniformly to all member nations. These rules will pretty much apply to anyone who builds or owns IT systems and the implications may surprise you.\r\n\r\nIn this practical and entertaining talk, Johannes explores how a simple example of an everyday application gets entangled with privacy issues and how to untangle yourself.\r\n\r\nAs a side effect of the going to the talk, you will be able to impress your friends with statements like \"according GDPR article 7, subsection 4, this is not a legally obtained consent\" - a phrase that works surprisingly well at parties.", + "startsAt": "2019-06-20T13:40:00", + "endsAt": "2019-06-20T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "a1b51ef9-8e88-4154-9d4f-0d982498ea43", + "name": "Johannes Brodwall" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + "index": 6 + }, + { + "id": 4486, + "name": "Room 8", + "session": { + "id": "98635", + "title": "Real world hypermedia at NRK TV", + "description": "At NRK TV we are gradually introducing hypermedia in the API that serves the clients our viewers use to stream our TV content. Why? Not out of idealism, but because it provides concrete benefits for our service. We use hyperlinks to provide affordances for clients: instead of just exposing individual endpoints that serve data, we offer navigation options that form user stories that adapt dynamically based on different scenarios and application states. Hyperlinks also allow us to tie together bounded domain contexts that we keep separate to contain complexity. Clients can seamlessly navigate between e.g. editorial content, catalog, playback and personalized recommendations, without noticing or caring that different contexts could be supported by separate applications with varying degrees of criticality and separate failure modes. That sounds all sweet and dandy, but I'll back these pretty words up with practical examples taken from our API, and share some experiences and lessons learned.", + "startsAt": "2019-06-20T13:40:00", + "endsAt": "2019-06-20T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "bfe8fb18-a060-40c1-9882-e082073a5e77", + "name": "Einar Høst" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + "index": 7 + }, + { + "id": 4487, + "name": "Room 9", + "session": { + "id": "98869", + "title": "Universal Design of Software Solutions: Necessary for some, good for everyone", + "description": "The Norwegian government has made “necessary for some, good for everyone” a mantra of a new movement that aims to ensure that everyone can participate in society. One of the ways the government has tried to achieve this aim is through universal design. Universal design is the idea that the buildings as well as digital solutions can be made accessible to all people, regardless of age, disability, or other factors. In Norway, universal design is a legal obligation for all public service providers. It’s also good for business as including new untapped forms or revenue and market segments can help broaden a product or services appeal. However, according to the Norwegian government, public and private service providers have not yet fully adopted universal design as in the design and development of software systems.\r\n\r\nThe government agency, Difi, recently reported that one website stood out as an useful example of how universal design could be implemented in practice. The official website of the Norwegian police, politet.no, one of Bouvet’s clients gave us permission to present how this project took the grand challenge of universal design and made it part of the DNA of their website. The project team integrated a universal design approach in the development process from beginning to end. \r\nThis process provides an good practice approach for using universal design not only set an example for other businesses and government agencies, but to reach all of their citizens equally no matter their age or disability. \r\n\r\nOne of the great myths of universal design is that it is difficult to prioritize with all the other high demands that organizations face and that it will be expensive. However by integrating a universal design approach in technology development, software engineers and programmers have the opportunity to create low cost and easily deployable solutions for achieving universal design. As a result, their products and services enjoy greater usability, a better user experience and a truly equal approach to creating new technology.\r\n", + "startsAt": "2019-06-20T13:40:00", + "endsAt": "2019-06-20T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f281d82e-3bfe-44c1-9f2a-7dca7353123c", + "name": "George Anthony Giannoumis" + }, + { + "id": "471b4692-faac-4cfc-b1de-b1adba2211bc", + "name": "Maren Gulnes" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + "index": 8 + }, + { + "id": 4488, + "name": "Room 10", + "session": { + "id": "98988", + "title": "Workshop: Save the plants with technology! 1/2", + "description": "Just got a new plant? Hard to keep it alive? Let´s use technology to give the plant a long and happy life! \r\nAt this work shop you will learn how to solder your own gadget with a specific micro control unit. ESP8266. This unit became very popular when it offered WIFI, analog GPIO, and several digital GPIO gates at the cost of a few dollars. We will use this to solder terminals and connect with a moisture sensor. The programming is not very advanced, however it will teach you how to read data and share online for the data to be used for latter visualization. All participants will get a goodiebag to be soldered, programmed and brought back home. The goodiebag contains a ESP8266 micro controller, moisture sensor and a personally designed circuit board. Bring your own laptop, and to save time please download and install Arduino IDE to be found at Arduino´s home page. \r\n", + "startsAt": "2019-06-20T13:40:00", + "endsAt": "2019-06-20T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "848e41e0-8f50-48eb-887b-6a2ef9f1f707", + "name": "Anja Bergby" + }, + { + "id": "076a93ed-fdd8-49db-b709-90b996807f6f", + "name": "Kristin Annabel Folland" + }, + { + "id": "3357f0ef-ace2-44c5-aff7-8a4b4e75de20", + "name": "Ragnhild Kosmo Holm" + }, + { + "id": "7070251f-eb37-4415-a24d-de1cd461fb4d", + "name": "Elise Garborg Undheim" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + "index": 9 + } + ] + }, + { + "slotStart": "15:00:00", + "rooms": [ + { + "id": 4479, + "name": "Room 1", + "session": { + "id": "98310", + "title": "A Skeptics Guide to Graph Databases", + "description": "Graph databases are one of the hottest trends in tech, but is it hype or can they actually solve real problems? Well, the answer is both.\r\n\r\nIn this talk, Dave will pull back the covers and show you the good, the bad, and the ugly of solving real problems with graph databases. He will demonstrate how you can leverage the power of graph databases to solve difficult problems or existing problems differently. He will then discuss when to avoid them and just use your favorite RDBMS. We will then examine a few of his failures so that we can all learn from his mistakes. By the end of this talk, you will either be excited to use a graph database or run away screaming, either way, you will be armed with the information you need to cut through the hype and know when to use one and when to avoid them.", + "startsAt": "2019-06-20T15:00:00", + "endsAt": "2019-06-20T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "6865759f-cb01-408c-8267-1f9af62f84ee", + "name": "David Bechberger" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + "index": 0 + }, + { + "id": 4480, + "name": "Room 2", + "session": { + "id": "127292", + "title": "Deliberate Architecture", + "description": "Step back from your system and take a look at its architecture. Are the major structures and technology choices the result of conscious decisions, or have they emerged as the system has evolved? Architecture is often an ad hoc, responsive process where designs get stuck in local minima while ever more features are piled into the system. Such systems often fail to live up to the origin vision and expectations of stakeholders.\r\n\r\nIn this talk we look at how to design systems which are a purely a function of the major forces acting on a solution, rather than being modishly reflective of the prevailing software zeitgeist. We’ll explore the idea that software architecture, and hence software architects, should focus deliberately on the constraints and qualities of system design, and avoid getting too distracted by features.", + "startsAt": "2019-06-20T15:00:00", + "endsAt": "2019-06-20T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "fb8c0c65-88de-4673-b049-0e8a385c89ad", + "name": "Robert Smallshire" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + "index": 1 + }, + { + "id": 4481, + "name": "Room 3", + "session": { + "id": "77944", + "title": "Empathetic Design Systems", + "description": "How do you make a design system empathetic and whom should it be empathetic towards? At a recent company, we decided to replace our outdated style guide with a newfangled design system that we started from scratch. And we made a great start.\r\n\r\nBut we forgot about accessibility. Only stand alone components reflected the basics of accessibility leaving full user flows behind. We forgot about our fellow coworkers and peers. Our engineers shouldered slow development times and new technologies, designs changed often, and variants were hard to implement. And we forgot about our users. Much of the design system was geared towards engineers, neglecting designers, product managers and more.\r\n\r\nSo what did we learn in our first iteration? How did empathy help shape our ever-changing, morphing design system? Come learn how to build an empathetic design system from the ground up or start incorporating empathy today!\r\n", + "startsAt": "2019-06-20T15:00:00", + "endsAt": "2019-06-20T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "cdc97666-b7bb-4c51-aec5-c73095c08c54", + "name": "Jennifer Wong" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + "index": 2 + }, + { + "id": 4482, + "name": "Room 4", + "session": { + "id": "76039", + "title": "Lessons from the API Management trenches", + "description": "Azure API Management has a lot of functionality, but it's not always clear when to use what. In this session we will go into setting up an API Management architecture, inspired by real life use cases. We will see how we can expose and protect our services, which policies help make our life easier, and how to handle our application lifecycle management.", + "startsAt": "2019-06-20T15:00:00", + "endsAt": "2019-06-20T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "11a684d4-ace1-49e8-be4b-c4e5ff215a7c", + "name": "Eldert Grootenboer" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + "index": 3 + }, + { + "id": 4483, + "name": "Room 5", + "session": { + "id": "78473", + "title": "Code the future, now", + "description": "We know how to write code to do something now. What about code to do something tomorrow, or next year? Sometimes we use batch jobs. But as business grows, our \"overnight\" batch job starts finishing around lunch time. As we expand to new regions, we realise there is no \"night\". And it's only a matter of time before we make a change and break a batch job we forgot existed. What if tomorrow's code could live in the same place as today's code? What if it all looked the same? What if we could scale it all the same way?\r\n\r\nJoin Adam and discover how to embrace the future in the code we write now. Learn how to capture requirements as first class business logic, and avoid relegating them as second class citizens of the batch job world. Take a deep dive into techniques which combine off the shelf products with fundamental computer science.\r\n\r\nWhere we're going... we don't need batch jobs.", + "startsAt": "2019-06-20T15:00:00", + "endsAt": "2019-06-20T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e3d11172-923c-4256-932a-630aeb5a680e", + "name": "Adam Ralph" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + "index": 4 + }, + { + "id": 4484, + "name": "Room 6", + "session": { + "id": "84340", + "title": "Logging, Metrics and Events in ASP.NET Core", + "description": "Providing decent monitoring of your applications has always been considered the boring part of development, with tons of boilerplate code, and making upfront decisions around how it will be done, or retrofit afterwards. However, with dotnet core, things have changed, it's never been easier to implement effective visibility into how your application is performing in production.\r\n\r\nIn this session I will cover the fundamental differences between Metrics and Logs, and Events and look at where one is useful over the other.\r\n\r\nWe’ll look at some of the things Microsoft has done in dotnet core to make logging easier, and some of the third-party libraries and tools that aim to make it easier to navigate.\r\n\r\nWe’ll cover tools like Serilog and Log4Net, along with AppMetrics for capturing application information. We’ll then take a quick look at Grafana, and see how we can make some sense of that information. Finally, we'll look at Honeycomb.io and how they're providing actionable insights for distributed systems using events, enabling testing in production.", + "startsAt": "2019-06-20T15:00:00", + "endsAt": "2019-06-20T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "9b006212-1589-4af6-8d18-10d2792fd9ce", + "name": "Martin Thwaites" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + "index": 5 + }, + { + "id": 4485, + "name": "Room 7", + "session": { + "id": "98435", + "title": "Best practices for securing CI/CD pipeline", + "description": "DevOps practices are in a place; containers are everywhere, pipelines are flying. We do Agile. We do DevOps. Now we try to follow security practices for protecting the deployed resources, too. This is a reason why DevSecOps is not hype anymore and is gaining more prominence. There is a lot of information about DevSecOps, but how to do it properly? Where to start? What are the best practices?\r\nIn this session, we will walk through an end-to-end scenario where we will deploy infrastructure components securely to Azure using Azure DevOps, Azure Container Registry and security tools. We will build a pipeline with security in mind to protect and detect potential security flows during the build.\r\nYou will learn:\r\n- How to build end-to-end CI/CD pipeline that builds the application and deploys infrastructure on Azure with security checks for the application, containers and infrastructure;\r\n- What are the security tools available for CI/CD pipeline and how to implement them in the best way into different Git workflows;\r\n- Best practices and patterns of building security pipelines.\r\n\r\n\r\n\r\n", + "startsAt": "2019-06-20T15:00:00", + "endsAt": "2019-06-20T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "4c3efe89-ab58-4b28-a9c3-78251f25ee06", + "name": "Victoria Almazova" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + "index": 6 + }, + { + "id": 4486, + "name": "Room 8", + "session": { + "id": "99067", + "title": "Building a bank from scratch in the Cloud", + "description": "We are building the next generation mobile bank in the cloud from scratch! This is how we build Bulder Bank from the ground up.\r\n\r\nEarly on it was decided that we had to be open for radical new ideas if we was to succeed. Important kriterias was speed, modern and automated processes and future-proofing. In addition we wanted to make something that was cool and motivated everyone on the team to work on.\r\n\r\nThe choice landed on Google Kubernetes Engine and Google Firebase and the possibilities this gives us are literally endless! And it gives us the opportunity to move fast while having a more or less fully managed environment that is always up and running!\r\n\r\nWe have decided to model payments entirely event based and asynchronously where multiple microservices written in Go each do their part before handing over the transaction to the next service over a message queue.", + "startsAt": "2019-06-20T15:00:00", + "endsAt": "2019-06-20T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "3de2ca4c-383f-436e-8351-9ca8bf4771cd", + "name": "Hans Kristian Flaatten" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + "index": 7 + }, + { + "id": 4487, + "name": "Room 9", + "session": { + "id": "86712", + "title": "Why our products and communities need our empathy", + "description": "Empathy is a fundamental part of human interaction. When we communicate by email or at conferences, or indirectly, when we create products, events, or do a talk. However, our understanding of other people is full of error, and worse, bias. This can lead us to make communities and products that work poorly for people that are different from ourselves, introduce confusion and misunderstanding, exclude people unintentionally, and sometimes even cause harm.\r\n\r\nHowever, our communities are an opportunity to learn as well. To embrace our diversity, and expand our understanding of other people's worlds. To gain understanding of other people’s situations, experiences and emotions, which can be dramatically different to ours. And how we can use this to create both products and communities which work great not only for ourselves, but also those that we more easily forget about. As creators in tech we have such tremendous power to create change, but merely our best intentions will not be enough for that.\r\n\r\nThis talk will explore how and why we sometimes have such difficulty to understand others, and how others can have difficulty to understand us. We'll talk about why other people's experiences, emotion and perceptions can be so different. Both for the world as a whole, but also with the speaker's personal experiences. Finally, we'll cover specific ways for us to understand others better, and associated pitfalls, to make our communities and products happy, inviting and supportive places.\r\n\r\nPrevious attendees of this talk said:\r\n\r\n- \"I think this touched the very core of the complexity of empathy and vulnerability\"\r\n- \"I feel safe in this community, and talks like this are one of the main reasons.\"\r\n- \"Having a talk about such a difficult topic makes you a great role model in general to me!\"\r\n- \"Your talk made me feel so much more welcome and safe at this event.\"\r\n- \"As usual, she's delivering an amazing talk.\"\r\n- \"Great speech, really important and meaningful.\"\r\n- \"Awesome, awesome talk.\"", + "startsAt": "2019-06-20T15:00:00", + "endsAt": "2019-06-20T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "2f0477e0-2bc8-491b-881c-a319783bad12", + "name": "Sasha Romijn" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + "index": 8 + }, + { + "id": 4488, + "name": "Room 10", + "session": { + "id": "128715", + "title": "Workshop: Save the plants with technology! Part 2/2", + "description": "Just got a new plant? Hard to keep it alive? Let´s use technology to give the plant a long and happy life!\r\n\r\nAt this work shop you will learn how to solder your own gadget with a specific micro control unit. ESP8266. This unit became very popular when it offered WIFI, analog GPIO, and several digital GPIO gates at the cost of a few dollars. We will use this to solder terminals and connect with a moisture sensor. The programming is not very advanced, however it will teach you how to read data and share online for the data to be used for latter visualization. All participants will get a goodiebag to be soldered, programmed and brought back home. The goodiebag contains a ESP8266 micro controller, moisture sensor and a personally designed circuit board. Bring your own laptop, and to save time please download and install Arduino IDE to be found at Arduino´s home page.", + "startsAt": "2019-06-20T15:00:00", + "endsAt": "2019-06-20T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "7070251f-eb37-4415-a24d-de1cd461fb4d", + "name": "Elise Garborg Undheim" + }, + { + "id": "076a93ed-fdd8-49db-b709-90b996807f6f", + "name": "Kristin Annabel Folland" + }, + { + "id": "848e41e0-8f50-48eb-887b-6a2ef9f1f707", + "name": "Anja Bergby" + }, + { + "id": "3357f0ef-ace2-44c5-aff7-8a4b4e75de20", + "name": "Ragnhild Kosmo Holm" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + "index": 9 + } + ] + }, + { + "slotStart": "16:20:00", + "rooms": [ + { + "id": 4479, + "name": "Room 1", + "session": { + "id": "76922", + "title": "ML and the IoT: Living on the Edge", + "description": "Machine Learning and the IoT are a match made in heaven. After all, IoT devices collect mountains of sensor data, what better way to uncover insights and actions than through sophisticated, modern computing methods like ML and AI?\r\n\r\nThe problem is, leveraging ML with IoT has historically meant backhauling all your sensor data to the Cloud. When the cloud is involved, security is a concern, and in the realm of IoT, security is often a dirty word.\r\n\r\nBut modern embedded systems, microcontrollers and single-board computers are getting more powerful, and more sophisticated, and its becoming increasingly possible to bring Machine Learning closer to sensors and IoT devices. \"Edge ML\" enables quicker insights, tighter security, and even true predictive action, and it's going to become the norm in the IoT in the near future.\r\n\r\nIn this session, we'll explore the state of the art in Edge ML and IoT, and talk about practical ways that developers can get started with both, today.", + "startsAt": "2019-06-20T16:20:00", + "endsAt": "2019-06-20T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f1547f29-3799-4bdb-bcbf-112a4e11253e", + "name": "Brandon Satrom" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + "index": 0 + }, + { + "id": 4480, + "name": "Room 2", + "session": { + "id": "98925", + "title": "The Curiously Recurring Pattern of Coupled Types", + "description": "Why can pointers be subtracted but not added?\r\n\r\nWhat do raw C pointers, STL iterators, std::chrono types, and 2D/3D geometric primitives have in common?\r\n\r\nIn this talk we will present some curiously coupled data types that frequently occur in your programs, together forming notions that you are already intuitively familiar with. We will shine a light on the mathematical notion of Affine Spaces, and how they guide stronger design. We will review the properties of affine spaces and show how they improve program semantics, stronger type safety and compile time enforcement of these semantics.\r\n\r\nBy showing motivational examples, we will introduce you to the mathematical notion of affine spaces. The main focus will then be on how affine space types and their well defined semantics shape expressive APIs.\r\n\r\nWe will give examples and guidelines for creating your own affine types. Although the examples in the talk will use C++, the general concepts are applicable to other strongly typed programming languages.\r\n", + "startsAt": "2019-06-20T16:20:00", + "endsAt": "2019-06-20T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f90c9365-b46d-41ef-bfe8-5a8ce7869ab5", + "name": "Adi Shavit" + }, + { + "id": "faf284c6-cee1-4e2c-bd6c-91e92ad33400", + "name": "Björn Fahller" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + "index": 1 + }, + { + "id": 4481, + "name": "Room 3", + "session": { + "id": "127293", + "title": "Anchored Metadata", + "description": "When building software, we often need to associate metadata with the code we’re writing. A typical example is when we need to tell our linters to ignore a specific range of code. A common approach to adding this metadata is to embed it directly in the code using the syntax of the language, but this approach has a number of drawbacks including language specificity, potential for collision, and cluttering of the code.\r\n\r\nIn this talk we’ll look at an alternative approach that stores the metadata separate from the code using a technique called _anchoring_. The metadata is associated with an anchor, a region of code inside the source file. Critically, the anchor also includes a context, a snapshot of the code surrounding the anchored region. As the source code is changed, this context – along with some very interesting algorithms for aligning text -– is used to automatically update the anchors.\r\n\r\nTo demonstrate these concepts we’ll look at spor, a tool that implements anchoring and anchor updating. The primary implementation of spor is in Python, so it’s very approachable and, indeed, open for contribution. As a side note, we’ll also look at a partial implementation of spor written in Rust. Finally, we’ll look at how spor is being used in Cosmic Ray, a mutation testing tool for Python.", + "startsAt": "2019-06-20T16:20:00", + "endsAt": "2019-06-20T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "ad6fb1a9-9b48-4393-95f1-f352e643c541", + "name": "Austin Bingham" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + "index": 2 + }, + { + "id": 4482, + "name": "Room 4", + "session": { + "id": "78380", + "title": "Observability Driven Development", + "description": "There you are… an agile company building cloud native microservices, everything is automated and you are deploying multiple times a day. You think you ticked all the DevOps boxes but when does the money start flowing in?\r\n\r\nMaybe it's because your users don't like the way your software works, maybe you don't actually have any users. How do you know? Traditional monitoring tools are dead. They can't give you the insights you need to see if your distributed system is still working or not.\r\n\r\n\"Observability driven development\" is a way to focus on building observable systems that focus on seeing if your system is actually working and delivering value to your customers.\r\n\r\nBy being able to observe your production environment you are able to learn from it, experiment on it (in production) and in the end improve it. In this session we'll discuss what it means to create observable systems and how you can start adding observability to your own systems which help everyone from developers to product owners to make better decisions in adding value to their software.", + "startsAt": "2019-06-20T16:20:00", + "endsAt": "2019-06-20T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "a1bae1a4-f4fe-4113-8d4f-cd0f363eb48a", + "name": "Geert van der Cruijsen" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + "index": 3 + }, + { + "id": 4483, + "name": "Room 5", + "session": { + "id": "97321", + "title": "Real-Time, Distributed Applications w/ Akka.NET, Kubernetes, .NET Core, and Azure Kubernetes Service", + "description": "In this session you will learn about how companies ranging from the Fortune 500 to brand new startups are changing the way the build .NET applications to leverage the very latest offerings from Microsoft and the .NET open source community.\r\n\r\nYou'll learn how and why companies are moving their applications onto .NET Core; rearchitecting them to use Akka.NET for fault tolerance, scalability, and the ability to respond to customers in real-time; containerizing them with Docker; putting everything together using Kubernetes for orchestration on-premise or on the cloud with Azure Container Services.\r\n\r\nThis session will provide an overview of how all of these technologies fit together and why companies are adopting them.", + "startsAt": "2019-06-20T16:20:00", + "endsAt": "2019-06-20T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "5a279f06-e4d2-449c-879d-eedec29cd401", + "name": "Aaron Stannard" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + "index": 4 + }, + { + "id": 4484, + "name": "Room 6", + "session": { + "id": "82548", + "title": "Correcting Common Async/Await Mistakes in .NET", + "description": "Did you know that the .NET compiler turns our async methods into classes? And that .NET adds a try/catch block to each of these classes, potentially hiding thrown exceptions? It's true!\r\n\r\nIn this session, we will learn how to best use async/await in C# by analyzing how .NET compiles our async code.\r\n\r\nJoin me as we take an existing app and optimize its async code together, showing off performance gains, better exception handling, improved run-time speed, and smaller app size!", + "startsAt": "2019-06-20T16:20:00", + "endsAt": "2019-06-20T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "276db8d7-4b9d-4e5e-a656-b88335a0ba00", + "name": "Brandon Minnick" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + "index": 5 + }, + { + "id": 4485, + "name": "Room 7", + "session": { + "id": "98763", + "title": "Securing the web with AI", + "description": "In today’s web not a week goes by without a large data breach or a website being hacked. Unlawful access to our online information can be prevented by encryption, 2FA and IP detection, but often this isn’t enough. Additionally tools like 2FA can be difficult to configure or understand for the initiated, leaving many at a disadvantage - security should be a right, not a privilege.\r\n\r\nThis session explores some interesting and experimental ways that AI could be used to improve security and protect users on the web.\r\n\r\nUsing existing AI tools like Azure Cognitive Services we’ll look at ways facial or voice recognition could be used as part of 2FA to make security more accessible to end users, including code examples in .NET and JavaScript. Then we’ll investigate some simple methods to find patterns in user behaviour, such as login times and mouse behaviour, to detect anomalies and take action.\r\n\r\nFinally, we’ll see how machine learning can be used to identify fraudulent text or photoshopped images within webpages and warn users of scams before it becomes an issue.", + "startsAt": "2019-06-20T16:20:00", + "endsAt": "2019-06-20T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "3f01a9fa-4c71-4efe-871f-8e0ced1471d0", + "name": "Callum Whyte" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + "index": 6 + }, + { + "id": 4486, + "name": "Room 8", + "session": { + "id": "98660", + "title": "Moving the enterprise to Kubernetes", + "description": "With around 720.000 customers, Hafslund Nett is Norway’s largest power grid company and the fifth-largest in the Nordic region. The IT department have been migrating all of their services onto kubernetes. This introduces a set of challenges to keep control without sacrificing agility or speed.\r\n\r\nThis talk will show how Hafslund Nett decided to use a Cloud Managed Kubernetes with RBAC and AD groups to get fine grained control, secure development projects, use namespaces to control worker nodes usage and how we ended on separated Kubernetes clusters for each cluster environment. Additionally OpenIDConnect is used to provide the customers facing applications with B2C capabilities.\r\n\r\nWe will show how the centralizing of logs enable us to do monitoring, display trends, optimizing resource usage, improve Kubernetes scheduling and feed the CI/CD pipelines to further improve the container services.", + "startsAt": "2019-06-20T16:20:00", + "endsAt": "2019-06-20T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "dff50ecf-976f-48fa-a630-64511bbf3b88", + "name": "Fredrik Klingenberg" + }, + { + "id": "b195b7d1-3a85-4ca0-a5e6-7cfbdd3a8c48", + "name": "Gustav Kaleta" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + "index": 7 + }, + { + "id": 4487, + "name": "Room 9", + "session": { + "id": "99225", + "title": "Shaving my head made me a better programmer", + "description": "How do perceptions and stereotypes affect those in software and on engineering teams? This talk tells the true story of how I hacked my appearance, by shaving my head, to change the way I was perceived as a programmer.\r\n\r\nThis talk also serves as a primer on unconscious bias and stereotype threat, and their effects on individuals and teams. I will provide actionable advice on how to make engineering teams more inclusive, more diverse, and thusly more productive, successful, and attractive to potential hires.", + "startsAt": "2019-06-20T16:20:00", + "endsAt": "2019-06-20T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "c7c00ce0-a071-4a0a-976d-b6903d39209d", + "name": "Alex Qin" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + "index": 8 + }, + { + "id": 4488, + "name": "Room 10", + "session": { + "id": "98813", + "title": "Workshop: DIY – build your own React 1/2", + "description": "Are you using React, but don’t really know how it works? The framework is quite simple and do not require understanding the underlying mechanisms for most day to day tasks. This workshop will take your skills up a level, giving you a thorough understanding of React.\r\n\r\nYou will create a working version of React in less than 200 lines of code. It won’t be as efficient as React is. Nonetheless, you will gain valuable insight into how React work under the hood. We will demystify a lot of the concepts that are taken for granted when using React: representing the DOM-tree, rendering components, setting state and props, and re-rendering.", + "startsAt": "2019-06-20T16:20:00", + "endsAt": "2019-06-20T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "a9b0694d-8478-4b05-b368-e89d138323f8", + "name": "Svein Petter Gjøby" + }, + { + "id": "79cb3124-4d83-4b49-adcd-9035a0c45135", + "name": "Eirik Vigeland" + }, + { + "id": "e91a37c2-fe9c-46f2-bef4-2e67e2e114a9", + "name": "Henrik Hermansen" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + "index": 9 + } + ] + }, + { + "slotStart": "17:40:00", + "rooms": [ + { + "id": 4479, + "name": "Room 1", + "session": { + "id": "84573", + "title": "Tick Tock: What the heck is time-series data?", + "description": "The rise of IoT and smart infrastructure has led to the generation of massive amounts of complex data. In this session, we will talk about time-series data, the challenges of working with time series data, ingestion of this data using data from NYC cabs and running real time queries to gather insights. By the end of the session, we will have an understanding of what time-series data is, how to build streaming data pipelines for massive time series data using Flink, Kafka and CrateDB, and visualising all this data with the help of a dashboard.", + "startsAt": "2019-06-20T17:40:00", + "endsAt": "2019-06-20T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "2c535d4d-198c-4132-932c-bebe9a948306", + "name": "Tanay Pant" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + "index": 0 + }, + { + "id": 4480, + "name": "Room 2", + "session": { + "id": "99530", + "title": ".NET Rocks Live!", + "description": "Migrating from WCF to .NET Core with Mark Rendle\r\nAre you looking to migrate off of WCF? Microsoft has said that WCF will not move to .NET Core – so what are your options? \r\n\r\nJoin Carl and Richard from .NET Rocks as they talk to Mark Rendle about his work building a tool to help migrate WCF applications to a combination of .NET Core, ASP.NET Web API and gRPC. Bring your questions and be part of an in-person .NET Rocks recording!", + "startsAt": "2019-06-20T17:40:00", + "endsAt": "2019-06-20T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "7a34a7fc-2f1c-4751-af4f-18a21de0e6b3", + "name": "Richard Campbell" + }, + { + "id": "6d1065d2-3494-48a6-a6bb-7efde3d8de40", + "name": "Carl Franklin" + }, + { + "id": "70590ad0-b1b3-40b8-b05d-b58722ef9d9d", + "name": "Mark Rendle" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + "index": 1 + }, + { + "id": 4481, + "name": "Room 3", + "session": { + "id": "127294", + "title": "UX Design Fundamentals: What do your users really see", + "description": "Developers are often unaware of how their users actually see their screens. In this UX design session, we'll discuss the most important principles concerning how the human brain and visual system determine how users see application interfaces.\r\n\r\nWe'll look at Gestalt principles for grouping and highlighting, inattentional blindness and change blindness, how users scan through a view, and how to promote clarity in interfaces with levels of emphasis. Tests will help attendees see how they personally experience these principles, and better understand the challenges faced by their users when views and pages are not designed to respect design principles.", + "startsAt": "2019-06-20T17:40:00", + "endsAt": "2019-06-20T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "af1eed12-4400-4d1c-885f-7fbb41e737b6", + "name": "Billy Hollis" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + "index": 2 + }, + { + "id": 4483, + "name": "Room 5", + "session": { + "id": "97346", + "title": "Empower Your Microservices with Istio Service Mesh", + "description": "Microservices popularity has grown as a lot of organizations are moving their applications to microservices which enables their teams to autonomously own and operate their own microservices. The microservices have to communicate with each other so how do you efficiently connect, secure, and monitor those services? \r\n\r\nIstio is an open platform for providing a uniform way to integrate microservices, manage traffic flow across microservices, enforce policies and aggregate telemetry data.\r\n\r\nIn this session, we will cover what is service mesh and why it is important for you, what are the core components of Istio, how to empower your microservices to leverage the features that Istio provides on top of Kubernetes such as service discovery, load balancing, resiliency, observability, and security.", + "startsAt": "2019-06-20T17:40:00", + "endsAt": "2019-06-20T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "80f14329-6da2-4fb3-915d-7a2b1f49619f", + "name": "Hossam Barakat" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + "index": 4 + }, + { + "id": 4484, + "name": "Room 6", + "session": { + "id": "76044", + "title": "Advanced .NET debugging techniques from real world investigations", + "description": "You know how it feels. After releasing a new version, a service starts behaving in an unexpected way, and it's up to you to save the day. But where to start?\r\n\r\nCriteo processes 150 billion requests per day, across more than 4000 front-end servers. As part of the Criteo Performance team, our job is to investigate critical issues in this kind of environment.\r\n\r\nIn this talk, you will follow our insights, mistakes and false leads during a real world case.\r\n\r\nWe will cover all the phases of the investigation, from the early detection to the actual fix, and we will detail our tricks and tools along the way. Including but not limited to:\r\n\r\n - Using metrics to detect and assess the issue;\r\n - What you can get... or not from a profiler to make a good assumption;\r\n - Digging into the CLR data structures with a decompiler, WinDBG and SOS to assert your assumption;\r\n - Automating memory dump analysis with ClrMD to build your own tools when WinDBG falls short.", + "startsAt": "2019-06-20T17:40:00", + "endsAt": "2019-06-20T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "a147c43c-8537-4cc7-92f5-41ee2c1d67ab", + "name": "Kevin Gosse" + }, + { + "id": "62706aaf-aadc-4538-9f39-70f5afb4cf0b", + "name": "Christophe Nasarre" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + "index": 5 + }, + { + "id": 4485, + "name": "Room 7", + "session": { + "id": "98882", + "title": "What vulnerabilities? Live hacking of containers and orchestrators", + "description": "We often see alerts about vulnerabilities being found in frameworks that we use today, but should we really care about them? What's the worst that can happen? Can someone own a container? Could they run a bitcoin miner on my servers? Are they able to own the cluster?\r\n\r\nIn this talk, we look at one of the worst-case scenarios from a real-world perspective. We have a red team member attempting to hack a cluster we own with a live hack on stage whilst the blue team member tries to stop it from happening.\r\n\r\nWe'll discuss developing best practices, implement security policies and how best to monitor your services to put preventative measures in place.\r\n\r\n", + "startsAt": "2019-06-20T17:40:00", + "endsAt": "2019-06-20T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "964af3ac-fd5e-46f6-b582-6c0d2da30db4", + "name": "Lewis Denham-Parry" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + "index": 6 + }, + { + "id": 4486, + "name": "Room 8", + "session": { + "id": "74878", + "title": "Powering 100+ million daily users", + "description": "In this talk I will walk through how we build a simple architecture for a complex system with strict performance (250 ms) and scale (100+ million connected daily users) requirements in order to power people experiences in Outlook, Owa, OneDrive, etc. Also share our thinking of how to slowly and gradually shift the engineering mindset to embrace microservices without scratching everything and starting from scratch.", + "startsAt": "2019-06-20T17:40:00", + "endsAt": "2019-06-20T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "8d5c7076-3579-40c3-9fbf-a02749078257", + "name": "Rezaul Hoque" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + "index": 7 + }, + { + "id": 4487, + "name": "Room 9", + "session": { + "id": "98723", + "title": "5 Tips for Cultivating EQ in the Workplace", + "description": "Learning to manage our state of mind in the workplace is an acquired skill. While stress in the workplace in unavoidable, it is possible to cultivate Emotional Intelligence (EQ) to manage our state of mind. Practicing EQ helps us identify and eliminate stressors in our lives. Awareness of self and awareness of others strengthens personal and professional relationships. When we understand the motivations of ourselves and the perspectives of others we form deeper connections. In this presentation, learn five tips for cultivating Emotional Intelligence in the workplace.\r\n\r\n", + "startsAt": "2019-06-20T17:40:00", + "endsAt": "2019-06-20T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e296f852-2d30-4f51-8cf6-ac3c87b1427e", + "name": "Christina Aldan" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + "index": 8 + }, + { + "id": 4488, + "name": "Room 10", + "session": { + "id": "128716", + "title": "Workshop: DIY – build your own React - Part 2/2", + "description": "Are you using React, but don’t really know how it works? The framework is quite simple and do not require understanding the underlying mechanisms for most day to day tasks. This workshop will take your skills up a level, giving you a thorough understanding of React.\r\n\r\nYou will create a working version of React in less than 200 lines of code. It won’t be as efficient as React is. Nonetheless, you will gain valuable insight into how React work under the hood. We will demystify a lot of the concepts that are taken for granted when using React: representing the DOM-tree, rendering components, setting state and props, and re-rendering.", + "startsAt": "2019-06-20T17:40:00", + "endsAt": "2019-06-20T18:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e91a37c2-fe9c-46f2-bef4-2e67e2e114a9", + "name": "Henrik Hermansen" + }, + { + "id": "a9b0694d-8478-4b05-b368-e89d138323f8", + "name": "Svein Petter Gjøby" + }, + { + "id": "79cb3124-4d83-4b49-adcd-9035a0c45135", + "name": "Eirik Vigeland" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + "index": 9 + } + ] + }, + { + "slotStart": "18:40:00", + "rooms": [ + { + "id": 4489, + "name": "Expo", + "session": { + "id": "128960", + "title": "Party", + "description": "Kick back, get to know your fellow attendees and enjoy live music from the main stage. The party is complimentary for all NDC delegates. (18:40- 23:00)\r\n\r\nSchedule:\r\n\r\n- Conference Reception in the Expo\r\n- Fun talks with host Lars Klint\r\n- Dylan Beattie and the Linebreakers\r\n- LoveShack", + "startsAt": "2019-06-20T18:40:00", + "endsAt": "2019-06-20T23:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f99fa878-6176-4ff4-b151-c717fa5daf0c", + "name": "Lars Klint" + }, + { + "id": "1d7dcbfc-1de6-4228-8bd6-04f4ba1c4267", + "name": "Dylan Beattie" + } + ], + "categories": [], + "roomId": 4489, + "room": "Expo" + }, + "index": 11 + } + ] + } + ] + }, + { + "date": "2019-06-21T00:00:00", + "rooms": [ + { + "id": 4479, + "name": "Room 1", + "sessions": [ + { + "id": "81395", + "title": "Machine Learning: The Bare Math Behind Libraries", + "description": "Machine learning is one of the hottest buzzwords in technology today as well as one of the most innovative fields in computer science – yet people use libraries as black boxes without basic knowledge of the field. In this session, we will strip them to bare math, so next time you use a machine learning library, you'll have a deeper understanding of what lies underneath.\r\n\r\nDuring this session, we will first provide a short history of machine learning and an overview of two basic teaching techniques: supervised and unsupervised learning.\r\n\r\nWe will start by defining what machine learning is and equip you with an intuition of how it works. We will then explain gradient descent algorithm with the use of simple linear regression to give you an even deeper understanding of this learning method. Then we will project it to supervised neural networks training.\r\n\r\nWithin unsupervised learning, you will become familiar with Hebb’s learning and learning with concurrency (winner takes all and winner takes most algorithms). We will use Octave for examples in this session; however, you can use your favorite technology to implement presented ideas.\r\n\r\nOur aim is to show the mathematical basics of neural networks for those who want to start using machine learning in their day-to-day work or use it already but find it difficult to understand the underlying processes. After viewing our presentation, you should find it easier to select parameters for your networks and feel more confident in your selection of network type, as well as be encouraged to dive into more complex and powerful deep learning methods.\r\n\r\nLevel: beginner\r\n", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f5715729-0aeb-4945-a65e-9dd0d6ddf424", + "name": "Łukasz Gebel" + }, + { + "id": "826496af-d697-40eb-a5d8-2c16bda34181", + "name": "Piotr Czajka" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + { + "id": "84059", + "title": "Protecting sensitive data in huge datasets: Cloud tools you can use", + "description": "Before releasing a public dataset, practitioners need to thread the needle between utility and protection of individuals. Felipe Hoffa explores how to handle massive public datasets, taking you from theory to real life as they showcase newly available tools that help with PII detection and brings concepts like k-anonymity and l-diversity to the practical realm. You’ll also cover options such as removing, masking, and coarsening.\r\n\r\nWhat you'll learn:\r\n\r\n- Learn how to identify PII in massive datasets\r\n- Explore k-anonymity, l-diversity, and related research and options such as removing, masking, and coarsening\r\n- Gain experience with practical demos over massive datasets", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "28dd5c97-7753-4acf-b956-25e7467c31ab", + "name": "Felipe Hoffa" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + { + "id": "84838", + "title": "ML BuzzWords demystified", + "description": "Machine Learning is a fast evolving discipline and one of the hottest areas both in industry and academia, and it only keeps getting more traction. With such a quickly advancing field, it becomes increasingly hard to keep up with the new concepts. \r\nIf you find yourself lost in a forest of ML buzzwords and want to catch up, welcome to our session!\r\nWe will give you the gist of the latest trends in Machine Learning - from Reinforcement Learning and AutoML to ML bias - with zero formulas and maximum sense.\r\n\r\nBy the end of the session, you will be up-to-date with what is happening in the field.", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "61a48ebe-ebe0-427f-a1a1-eef2f7e92ed9", + "name": "Oleksandra Sopova" + }, + { + "id": "5937af3f-6906-46e8-86a9-0e9cefd5a080", + "name": "Natalia An" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + { + "id": "98658", + "title": "The Hitchhiker's Guide to the Cloud (AWS vs GCP vs Azure) and their AI/ML API’s capabilities", + "description": "To companies leveraging the capabilities of public cloud (often Amazon Web Services, Google Cloud or Microsoft Azure) the felling of immersion into a single provider platform is constant in their day to day. With a rapid evolution of services becoming available in each cloud provider, companies tend to focus and keep updated with only one of them while other providers capabilities are simply unknown, ignored or forgotten. \r\nOn the other hand, there are many companies that are not yet using public cloud and are now facing the dilemma of which Public Cloud provider to choose.\r\n\r\nAI and Machine Learning are key areas of investment, growth and differentiation for many companies and that is no exception for the three biggest public cloud players (AWS, GCP and Azure). In this context, pre-trained AI/ML API’s in combination with other Serverless services is one area that has been on the rise and with fast adoption. \r\n\r\nIn this talk we will learn about the three major public cloud providers (AWS, GCP and Azure) by having an overview and gain insights about each other pros and cons. In addition, we are going to explore their AI/ML Cloud API’s that allow us to leverage ready-made capabilities such as: Text to Speech, Image & Video Classification, Translation, Speech Recognition, Sentiment Analysis, etc.\r\n\r\n", + "startsAt": "2019-06-21T15:00:00", + "endsAt": "2019-06-21T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "a2e6985d-7ead-4b43-bdde-bfdea9923300", + "name": "Bruno Amaro Almeida" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + { + "id": "99155", + "title": "Everything is Cyber-broken 2", + "description": "TBA - submitting this now so you have it in the agenda, it'll be an all new talk in the theme of the first cyber-broken talk", + "startsAt": "2019-06-21T16:20:00", + "endsAt": "2019-06-21T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "735a4b60-42e8-4452-9480-68197372c206", + "name": "Troy Hunt" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4480, + "name": "Room 2", + "sessions": [ + { + "id": "98412", + "title": "Hacking with Go", + "description": "Learning Go programming is easy. Go is popular and becomes even more also in security experts world. Wanted to feel a bit as a hacker? Learn a new language? Or do both at the same time? This session is about it. \r\nSo let's jump into hands-on session and explore how security tools can be written in Go. How to enumerate network resources, extract an information, sniff packets and do port scanning, brute force and more all with Go. \r\nBy the end, you will have more ideas what else can be written or re-written in Go. ", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "4c3efe89-ab58-4b28-a9c3-78251f25ee06", + "name": "Victoria Almazova" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + { + "id": "98825", + "title": "Source Instrumentation for Monitoring C++ in Production", + "description": "It is essential to discuss how modern C++ code can be effectively instrumented, in order to effectively monitor it after deployment. This talk will focus on portable source instrumentation techniques such as logging, tracing and metrics. Straightforward, but well designed code additions can drastically ease the troubleshooting of functional issues, and identification of performance bottlenecks, in production.\r\n\r\nOf course when dealing with C++ performance is often critical, and so minimizing the cost of any instrumentation is also critical. Key to this is understanding the trade-off between the detail of information collected, and the overheads of exposing that information. It is also important to understand how best to benefit from advances in contemporary monitoring infrastructure, popularised by cloud environments.\r\n\r\nThis talk will open with some brief motivation towards monitoring and instrumentation. It will then walk through some practical code examples using some generic instrumentation primitives, based on proven principles employed in demanding production software. ", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "8ccea10a-7d68-4c6a-9d59-88f9355ccfff", + "name": "Steven Simpson" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + { + "id": "99876", + "title": "Lightning Talks (Diverse)", + "description": "Lightning talks (approx 10-15 minutes each)\r\n\r\nTalk 1: 5 Lessons Learned from Implementing 40+ Machine Learning Projects - Xiaopeng Li\r\n\r\nMachine learning has reached the peak of Gartner's hype curve in 2018. Many companies are talking about it, while very few are actually doing it. At Inmeta, we have together with partners and clients implemented 40+ machine learning projects in the past few years. In this talk, I will share the top 5 lessons we learned from doing machine learning for real.\r\n\r\n-----------------------------------------------------------------------\r\n\r\nTalk 2: test && commit || revert. What?! - Kari Eline Strandjord\r\n\r\n`test && commit || revert` is a workflow developed during a week of code camp at Iterate with Kent Beck. The main idea is that your code should always be in a valid state. If the test passes, the code is committed. If it fails, you lose all your changes, and the code is forced back to the last valid state. At first, the idea seemed both unrealistic and a bit harsh. But after trying it out during a longer period writing an application in Elm, it did change my way of coding. \r\n\r\nThe talk will give a brief explanation of the workflow. I will also share my experiences from using it in a real project.\r\n\r\n-----------------------------------------------------------------------\r\n\r\nTalk 3: Five Ways to Break a Git Repository - Edward Thomson\r\n\r\nCan you break your Git repository? I hope not! That's where you keep all your stuff! Edward Thomson shows you five common mistakes that break Git repositories and how to fix them.\r\n\r\n-----------------------------------------------------------------------\r\n\r\nTalk 4: Unlocking the doors of parliament - Sindre Lindstad\r\n\r\nWhen Norway's Minister of Children and Families was instated, he enthusiastically showed the world the key to his new office through press photos.\r\n\r\nThe only problem was that it was a plastic punch-hole keycard, which meant anyone could make a copy.\r\n\r\nSo I made one with 3D printing (and lasers!). But does it work?\r\n\r\n----------------------------------------------------------------------- ", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "99aa52b8-e0ab-4bd8-be19-437cc4b93740", + "name": "Xiaopeng Li" + }, + { + "id": "a5357148-b11b-4ab0-822c-b650881773ef", + "name": "Kari Eline Strandjord" + }, + { + "id": "fee375b8-047c-4ea2-ab43-9837f2420b19", + "name": "Edward Thomson" + }, + { + "id": "5ec0ca76-bf24-4fce-bf3d-80656dadf1f6", + "name": "Sindre Lindstad" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + { + "id": "99320", + "title": "Trying to learn C#", + "description": "Learning a new language is often colored by the language you come from. As a programmer coming from C++ and Java, with some functional programming background, how did I navigate trying to get a grasp of C#? Should be fun for C# developers, but also educational: How do we teach a new language to folks that already know how to program?", + "startsAt": "2019-06-21T15:00:00", + "endsAt": "2019-06-21T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "0eaa4bb2-cb2a-4b76-800d-de8b1dfdb50c", + "name": "Patricia Aas" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + { + "id": "86521", + "title": "Rediscovering fire - on designing portable, multi-language libraries", + "description": "The session will cover the design choices and lessons learned developing the multi-language free library segyio, or more conceptually, designing libraries for libraries.\r\n\r\nBriefly, it will discuss:\r\n- Stable API, ABI, and how to design them for the future\r\n- How to design C-interface libraries that allows for good foreign-language libraries (in our case python)\r\n- Library design philosophy and the beauty of primitive functions\r\n- How to design for composition and caller flexibility\r\n- Plumbing and porcelain\r\n\r\nThe session should appeal both to library developers for embedded systems, and consumers of higher-level libraries in desktop and scientific applications, as the topic covered is the bridge between primitive and sophisticated systems, and making it beautiful.", + "startsAt": "2019-06-21T16:20:00", + "endsAt": "2019-06-21T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "142b682d-b548-423c-8e51-e36ee08db70f", + "name": "Jørgen Kvalsvik" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4481, + "name": "Room 3", + "sessions": [ + { + "id": "98167", + "title": "Evolving compositional user interfaces", + "description": "Ever since we started breaking applications into services, be it in the era of SOA or more recently with microservices, we’ve struggled to incorporate user interfaces into our decoupled, distributed architectures. We’ve seen frontends versioned separately with tight coupling to our services, breaking cohesion. We’ve seen the rise of Backend-For-Frontend and the emerge of micro frontends. We talk about composition, yet so many projects fail to implement actual composition. Instead we end up with some kind of compromise, with repeated business logic in the front-end, back-end and API, making it hard to scale – especially when multiple teams are involved – causing lock-step deployment, latency, bottlenecks and coordination issues.\r\n\r\nWhat if we could find a viable solution that allowed us to scale development, keep distribution and cohesion and also provide composition of user interfaces?\r\n\r\nIn this talk you are introduced to the evolution of compositional user interfaces and existing patterns while we discover their pros and cons, before diving into the architecture and development of compositional interfaces using hypermedia and micro-frontends. We go beyond the simple “Hello World” example that always seems to work, and you’ll learn patterns in modelling and design that will get you up and running with decoupled, composed user interfaces in your day job.\r\n", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "a6b5a582-ff8e-4874-84c7-35e095954666", + "name": "Thomas Presthus" + }, + { + "id": "1e4b0b48-cc95-4059-bff4-32103fb3a496", + "name": "Asbjørn Ulsberg" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + { + "id": "128875", + "title": "Fabulous – F# for cross-platform mobile apps", + "description": "In this informal talk, I will describe Fabulous, a community-developed framework using F# to build cross-platform mobile and desktop Xamarin apps.\r\n\r\nCome and learn how this radical new approach to app programming makes your code simpler, more testable and helps avoid repetition. By embracing the React-like MVU architecture, you can do away with your Xaml, your behaviours, your converters, your templating, your MVVM and embrace the simplicity of functional model descriptions and view re-evalaution. I will talk about the concepts involved and how this differs from Model-View-ViewModel (MVVM), the tooling available and how yuo can get involved.\r\n\r\nThis is mostly a conceptual talk and won’t be full of sparkling demos: demo apps are available from the Fabulous community.\r\n\r\nNote, Fabulous is a community project and is at version 0.34 as of May 2019. It is not a supported product or framework from Microsoft.\r\n\r\nhttps://fsprojects.github.io/Fabulous/", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "68b8aef8-e1b3-4a1f-9b73-2562ec1af738", + "name": "Don Syme" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + { + "id": "98611", + "title": "An in-flight port from Angular to React, a tale of performance and happiness", + "description": "A real-world story of how we used some clever trickery to completely rewrite an app, bit by bit from Angular to React, resulting in better performance, a smaller footprint, a shorter feedback loop, less coupling, fewer bugs, increased development velocity and happier developers.\r\nWe did the re-write, while deploying to production frequently. New features were added to the product throughout the whole rewrite process, and stability was maintained throughout the entire process.\r\n\r\nThe application is an e-commerce payment solution (Nets Easy), used by numerous merchants in their web shops to get paid.", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "912bbb93-e7bd-4448-8854-19ef39fa5843", + "name": "Henning Christiansen" + }, + { + "id": "1e49e725-0923-4dae-b00d-f443c518b010", + "name": "Francis Paulin" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + { + "id": "99143", + "title": "It's about time", + "description": "Time Zones, Daylight savings, Leap years, Leap seconds... Storing it all, testing it, getting it right for every point in time in every country... \r\nWriting correct timing code can be a nightmare! \r\nWe'll be ranting our way through some common pitfalls, tips and tricks to enable you to reason more effectively about time in your applications.", + "startsAt": "2019-06-21T15:00:00", + "endsAt": "2019-06-21T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "d28ae055-13a5-4d0a-8668-24fd93198cef", + "name": "Christin Gorman" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + { + "id": "99253", + "title": "Who's Who? Federating Identity with Azure B2C", + "description": "Often, users of your system will already know who they are, or at least think they do. Making sure you know who they are and what they can do is pretty important too.\r\n\r\nIn this session Microsoft Engineer Andrew Coates will present techniques for allowing users to log into your system with credentials from another system. Using Azure B2C allows you to offload authentication to other identity providers while keeping authorization tasks local to your system.\r\n\r\nOffload the hassles of lost passwords, expiring accounts and more, leaving you time to build and maintain the things that are important to your system.\r\n\r\nAndrew will demonstrate the setup and configuration of this powerful identity federation system allowing integration of any combination of social identities such as Facebook or twitter, as well as organisational accounts like Active Directory and others. He'll also discuss the extension points allowing complete control of the identity system including rules-based identity flows and calling out to custom REST services as part of the claims processing flow,\r\n\r\nIf your system needs to include users from outside your organisation, this is a must-see session.\r\n", + "startsAt": "2019-06-21T16:20:00", + "endsAt": "2019-06-21T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "2809c750-dc83-4e1c-8f06-38ee96b818b6", + "name": "Andrew Coates" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4482, + "name": "Room 4", + "sessions": [ + { + "id": "97917", + "title": "Modern Continuous Integration with Azure Pipelines", + "description": "CI builds shouldn't be relegated to an old desktop underneath a developers desk: modern software demands a modern build and release system. Edward Thomson introduces a cloud-first way of thinking about your builds, taking advantage of containers for simpler, reproducible configuration of build environments, building and testing across more platforms with Docker and QEMU, leveraging GitHub Actions for automation and other strategies to keep your software project's quality high while keeping your costs and overhead low.", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "fee375b8-047c-4ea2-ab43-9837f2420b19", + "name": "Edward Thomson" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + { + "id": "99261", + "title": "Dev and Test Agility for your Database with Docker", + "description": "Agile practices teach us how to deal with evolving applications but so often the data store is overlooked as a component of your application lifecycle. Database servers are monolothic, resource intensive and mostly viewed as set in stone. Encapsulating your database server in a container and your database in a storage container can dramatically lighten the load and make your database as agile as your model and other processes. And you can even use a serious enterprise class database like SQL Server this way. This session will show how to benefit from using a containerized version of SQL Server for Linux during development and testing. We'll also address concerns about data that needs to be persisted. You'll also get a peek at the DevOps side of this, including using images in your CI/CD process.", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "282a4701-f128-4b1d-bd67-da5d1f8b3eb0", + "name": "Julie Lerman" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + { + "id": "119374", + "title": "Building great teams ", + "description": "How do you build your dream team and ensure it continues to thrive? In this talk I will share interviewing tips, strategies to create a great culture and practical ways to manage those \"difficult\" conversations.\r\n", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "aff02f28-da1d-4681-817c-6cc42bf9484e", + "name": "Donna Edwards" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + { + "id": "98866", + "title": "The Neverending Story: Agile Transformation for DevOps", + "description": "The Digital Media division of National Public Radio (NPR) recently went through a period of growth that required scaling up its small sysadmin team to an Agile DevOps team, but the need for change didn’t stop there. \r\n\r\nAs a scrum master, I had to help the team let go of their old, ad hoc way of working and adjust to the Agile mindset of continually inspecting and adapting their processes. In this talk, I’ll take the audience through all aspects of our Agile transformation: overcoming resistance to change within the team and the department, why we struggled with our initial choice of the Scrum framework, why we wanted to try Kanban, how we moved to Scrumban and most importantly, what we’re going to do next since true Agile transformations never really end.\r\n\r\nYou’ll walk away with some ideas to overcome change fatigue and resistance that can work for both small teams and large organizations, an understanding of how Scrum and Kanban both helped us become a better DevOps team, and why the move to Scrumban was the right choice for our team at that time and might be right for you. You’ll also get an idea of where our DevOps model might go next!", + "startsAt": "2019-06-21T15:00:00", + "endsAt": "2019-06-21T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "2775faa3-3ee4-4c76-ac3e-4ee04c51c1b8", + "name": "Sarah Ziegenfuss" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + { + "id": "127295", + "title": "Avoiding the Agile Alignment Trap with DevOps", + "description": "MIT Sloan Management Review published an article in 2007 titled Avoiding the Alignment Trap in IT. What the researchers discovered is that organizations don’t become high performing by starting initiatives focused on aligning business and technology. Rather, only by improving delivery performance first was it possible to achieve IT Enabled Growth.\r\n\r\nThis presentation shows why Agile transformations won't save your software delivery challenges, what supporting evidence has accumulated in the last decade, and how to avoid the common traps that occur in digital transformations.", + "startsAt": "2019-06-21T16:20:00", + "endsAt": "2019-06-21T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "8cc2a599-d122-4ef2-8433-1132aa0c4a93", + "name": "Mike Long" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4483, + "name": "Room 5", + "sessions": [ + { + "id": "86189", + "title": "Serverless with Knative", + "description": "When you build a serverless app, you either tie yourself to a cloud provider, or you end up building your own serverless stack. Knative provides a better choice. Knative extends Kubernetes to provide a set of middleware components (build, serving, events) for modern, source-centric, and container-based apps that can run anywhere. In this talk, we’ll see how we can use Knative primitives to build a serverless app that utilizes the Machine Learning magic of the cloud. ", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f79e1173-a28c-4ad1-8885-7c52ba397fe3", + "name": "Mete Atamel" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + { + "id": "99318", + "title": "Architecture: The Stuff That's Hard to Change", + "description": "We’ve all heard of the idea of ‘software architecture’. We’ve read books about domain-driven design and event sourcing, we’ve been to conferences and learned about micro services and REST APIs. Some of us remember working with n-tiers and stored procedures… some of us are still using them. But the role of a systems architect is still one of the most misunderstood things about the software development process. What does the architect actually do? If you’re working with a systems architect, what can you expect from them? And if you are a systems architect, what are your team expecting from you?\r\n\r\nIn this talk, Dylan will share his own insights into the idea of architecture as part of a software development process. We’ll explore some popular architectural patterns and processes - and a couple of obscure ones as well - and look at how, and when, you can incorporate those patterns into your own projects. We’ll talk about how the idea of software architecture has changed over time, and share some tips and advice for developers who find themselves working with architecture as part of their role.", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "1d7dcbfc-1de6-4228-8bd6-04f4ba1c4267", + "name": "Dylan Beattie" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + { + "id": "83143", + "title": "Microservices without DDD is risky business!", + "description": "Just about everyone is doing microservices these days, at least that's what they're claiming. Microservices is the new black! But, how well are they really doing? When breaking things up there is a risk of ending up in the same rut as SOA did a decade ago, in effect creating distributed monoliths. So, is it at all possible for anyone to reach the promised land consisting of autonomous, cohesive, and loosely coupled services? \r\n\r\nMy claim is that it is doable, but not without some up-front modelling under the guidance of Domain-driven Design concepts like \"bounded context\", \"core domain\", \"ubiquitous language\" and “aggregates”. Distilling the domain, drilling deep into the core business concepts, and breaking it up into isolated and protected contexts will take you a long way. Add some business capability modelling and service-orientation into the mix, and you are halfway there. Use it as a map to guide you on the journey towards an orderly and robust distributed system, built by adding one MVP at the time in a low-risk agile manner. \r\n\r\nThis talk requires no previous experience with DDD, but it is advantageous if you are familiar with the challenges it attempts to solve, such as modularisation of unruly monoliths or managing a flock of microservices that make herding cats seem simple.", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "40a5fba3-0c7b-487c-9dc9-9d836a8ca999", + "name": "Trond Hjorteland" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + { + "id": "99471", + "title": "CompSci and My Day Job", + "description": "4 years ago I had a vague idea about Big-O notation and absolutely no clue about combinatorial problems. I knew what a SHA256 hash was (sort of) but I didn't know how it was created, nor that it didn't completely protect some of my data. I knew these things were important, but I never understood how they could apply to the types of applications I was building at the time. All of this changed as I put together the first two volumes of The Imposter's Handbook.\r\n\r\nI get to build a lot of fun things in my new position at Microsoft and I've been surprised at how often I use the things I've learned. Avoiding an obvious performance pitfall with Redis, for instance, because I understood the Big-O implications of the data structure I chose. Going back to ensure that a salt was added to a hash which stored sensitive data for an old client and, most importantly, discouraging a friend from trying to solve a problem that was very clearly NP-Complete.\r\n\r\nIn this talk I'll show you some of the fun things I've learned (like mod(%) and remainder being different things) and how I've applied them to the applications I create for my day job. You might know some of these concepts, or maybe you don't - either way: hopefully you'll leave with a few more tools under your belt to help you do your job better.", + "startsAt": "2019-06-21T15:00:00", + "endsAt": "2019-06-21T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "b68738ac-e6ff-4efe-a4e8-16a45b78c2bd", + "name": "Rob Conery" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + { + "id": "99182", + "title": "Advanced Azure App Services", + "description": "You'll find many introductions showing you how to use Azure App Services, so this talk will give you the inside scoop on the real world tips, tricks, and troubles you'll see when moving enterprise projects into App Services. We will discuss best practices for security and deployment, as well as prescriptions to follow to achieve the best performance, scalability, and resiliency.", + "startsAt": "2019-06-21T16:20:00", + "endsAt": "2019-06-21T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "c9c8096e-47a1-41e5-a00c-d49b51d01c4e", + "name": "K. Scott Allen" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4484, + "name": "Room 6", + "sessions": [ + { + "id": "99531", + "title": "Deep Learning in Microsoft Azure: CNTK, CaffeOnSpark and Tensorflow", + "description": "What is Microsoft’s approach to Deep Learning, and how does it differ from Open Source alternatives? In this session, we will look at Deep Learning, and how it can be implemented in Microsoft and Azure technologies with the Cognitive Toolkit, Tensorflow in Azure and CaffeOnSpark on AzureHDInsight. Join this session in order to understand deep learning better, and how we can use it to provide business and technical benefits in our organizations", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f63d9644-1b19-47e1-b84a-ad056419806e", + "name": "Jen Stirrup" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + { + "id": "98305", + "title": "System Stable : Robust connected applications with Polly, the .NET Resilience Framework", + "description": "Short Description\r\n\r\nIn this session I will show you how with just a few lines of code you can make your applications much more resilient and reliable. With Polly, the .NET resilience framework, your application can easily tolerate transient faults and longer outages in remote systems or infrastructure. \r\n\r\nAt the end of this hour you will know how to use all the features of Polly to make your application a rock solid piece of work. We’ll cover the reactive and proactive resilience strategies, starting with simple but very powerful retries and finishing with bulkhead isolation.\r\n\r\nOh, and did I mention Polly is a .NET Standard library so it will work on any application you can think of! \r\n\r\nJoin me for an hour, and your applications will never be the same.\r\n\r\n----------------------------------------------------------------------------------------------------------------------------------\r\n\r\nFull Description\r\n\r\nJoin me for this session and I will show you how with just a few lines of code, you can make your applications much more resilient and reliable. Let me tell you more… \r\n\r\nAlmost all applications now depend on connectivity, but what do you do when the infrastructure is unreliable or the remote system is down or returns an error? Does your application grind to a halt or just drop that single request? What if you could recover from these kinds of error, maybe even so quickly it won’t be noticed? \r\n \r\nWith Polly your application can easily tolerate transient faults and longer outages in remote systems or infrastructure. \r\n\r\nAt the end of this hour you will know how to use all the features of Polly to make your application a rock solid piece of work. \r\n\r\nWe’ll start with the simple but very powerful Retry Policy which lets you retry a failed request. If simple retries are not good enough for you, there is a Wait and Retry policy which introduces a delay between retries, giving the remote service time to recover before being hit again. Then I show you how to use the circuit breaker for when things have really gone wrong and a remote system is struggling under too much load or has failed. If all these attempts are unsuccessful and you are still not getting through to the remote system, you can return a default response or execute arbitrary code to call for human help (or restart the cloud) with the fallback policy. \r\n\r\nThat takes care of what you can do when things go wrong, but Polly also lets you take proactive steps to keep your application and the services it depends on healthy. \r\n\r\nTo get you started with proactive strategies, you will learn how caching can be used to store and return responses from an in-memory or distributed cache without having to hit the remote server every time. Or you can use bulkhead isolation to marshal resources within your application so that no one struggling part can take down the whole. Finally, I’ll show you how to fail quickly when your application is in danger of being overloaded or the remote systems is not responding in a timely fashion, this is done with the bulkhead isolation and the timeout polices. \r\n\r\nOh, and did I mention Polly is a .NET Standard library so it will work on any application you can think of! Join me for an hour, and your applications will never be the same. ", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "de972e57-7765-4c38-9dcd-5981587c1433", + "name": "Bryan Hogan" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + { + "id": "75537", + "title": "Lowering in C#: What's really going on in your code?", + "description": "If you're attending NDC you probably think you know what a foreach loop does - it iterates over a collection, right?\r\n\r\nWell... yes.\r\n\r\nBUT do you know how? Do you know what the C# compiler does when you write a foreach loop? What about a lambda expression? Or the re-entrant magic that is a yield return statement?\r\n\r\nIn this session we'll dive into Roslyn, the C# compiler, and learn about lowering and how it helps the compiler do its job, and what it does to your code. In the process you'll gain the skills to identify some of the common performance pitfalls of .NET, as well as just get a deeper understanding of what the code you write really does.", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "604507ba-fd96-4c48-a29a-67a95760d888", + "name": "David Wengier" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + { + "id": "99269", + "title": "DevOps for Machine Learning", + "description": "Machine learning is easier to use than ever before, but how do we coordinate the teams involved? Software engineering has been maturing for decades, but introducing an unfamiliar parallel workstream like data science brings new challenges. Thankfully, we can draw upon the cross-team collaborative efforts of DevOps to bring data science and software engineering into sync.\r\n\r\nBuilding effective predictive models involves data acquisition and preparation, then resource-intensive experimentation and training. Data scientists don't tend to focus on testing and deploying models to production systems in sync with software releases. Working with software engineers and IT operations in a repeatable, automated, coherent pipeline is still an afterthought in many organisations, and data science teams are left out of the loop.\r\n\r\nLet's look at an end-to-end software and data science delivery pipeline that is repeatable and robust. We'll focus on model source control, repeatable data preparation, model training and continuous retraining, code validation and testing, model storage and versioning, and production deployment. Data scientists and software engineers can work together effectively to produce smart software. Let's learn how!", + "startsAt": "2019-06-21T15:00:00", + "endsAt": "2019-06-21T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "42c43411-422b-455a-8772-3e638e4deb35", + "name": "Damian Brady" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + { + "id": "86610", + "title": "Solving Tricky Coordination Problems in Stateless .NET Services", + "description": "Developing modern, service-oriented architectures requires that our services become stateless to enable horizontal scalability. ASP.NET helps in doing so with IDistributedCache, but caching is only one of many new coordination problems.\r\n\r\nIn this session I will present how to approach some coordination problems, with a deeper focus on using Redis Pub/Sub to prevent concurrent client requests from triggering the same online-but-expensive computation over and over, by creating a distributed lock that does the job once and instantly notifies all other pending requests when the computation is completed.\r\nThis type of computation-locking is useful for preventing “stampedes” when generating reports, serving AI models, running serverless functions, and more. \r\n\r\nDuring the presentation I will also demo a sample ASP.NET Core project that implements said mechanism by making full use of asynchronous code and System.Collections.Concurrent to maximise performance.\r\n", + "startsAt": "2019-06-21T16:20:00", + "endsAt": "2019-06-21T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "fc185a93-d887-4005-b6ea-4099530a862f", + "name": "Loris Cro" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4485, + "name": "Room 7", + "sessions": [ + { + "id": "98731", + "title": "Making the most of Security Tests", + "description": "There is a number of security tests such as security code reviews, white box testing, penetration testing, red teaming to assure the security of a product and an environment where it is deployed.\r\nSome of the tests are mandated by the Secure Development Lifecycle, but some remain optional. The open question remains, when to use a particular test and how it impacts the ultimate decision whether a particular product requires additional investments.\r\n\r\nThis presentation uses a real-world red team attack against a multi-layer product as an example for discussing the differences of security tests. It shows, how the attacker starts with user-facing XML-RPC interface, breaks through multiple defense layers and ends up with root access to the database server and target data exfiltration. The example points out:\r\n- different areas where the tests improve the knowledge about the security risks of the product,\r\n- what are the requirements to obtain actionable results and\r\n- who needs to be involved to actually benefit from the results reported.\r\nThe presentation encourages expanding the security tests beyond the product features towards the security of the environment where it is deployed, supporting processes, as well as a product developers and administrators. It also shows, how the closer collaboration between different teams improves the overall security of the product", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "93cec660-9cdb-4ee8-af10-4eae804e3557", + "name": "Paweł Krzywicki" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + { + "id": "98639", + "title": "Why FIDO Security Keys & Webauthn are Awesome", + "description": "Phishing can happen to anyone, and hackers know that. What could happen if someone compromised your git repo? How about your email?\r\n\r\nFIDO security keys are awesome at preventing phishing. This talk explains how they work, how they can protect you, and what you can implement to protect your users.\r\n", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "ab3a4f70-753c-420a-a1b1-c001af2c460e", + "name": "Jen Tong" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + { + "id": "98908", + "title": "Security – only developers can make it proactive.", + "description": "Whether we use high-level languages like Java, Python, C# or we dive into the world of C/C++, the lists of dependencies of our projects contain more and more external frameworks and libraries. It makes developers’ life easiest and helps us to focus on delivering business value. Do you know what vulnerabilities are known for the version you use? Are you sure you know all the tips and tricks to use the framework in a correct way? Is it good for our software to rely the security of our products on the security of these frameworks and the way we use them?\r\n \r\nJoin me during an exciting LIVE DEMO. Get to know how to weaponize known Spring Boot Data Rest library vulnerability. See how to use Remote Code Execution to actually fully compromise the server hosting an application.\r\n \r\nUsing the vulnerability in an actual attack helps us to understand the underlying mechanism and find if it is applicable to our software. It also allows us to find the detection patterns if it is attempted to be exploited on our infrastructure. And besides all of it – it is fun to hack the servers! It also shows that we can do much better than just blindly upgrading components. There are examples of vulnerabilities, which are fixed not with a single patch, but rather through a series of upgrades leading to more secure solutions, so it is important to stop for a while and think about other attack paths and consequences, that can be faced. The reactive approach of simply keeping up with the latest version leaves us in a position, where we are always exposed to new vulnerabilities that are about to be discovered.", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "4c97bf6e-d874-4a5b-b71a-23c6e07dd53e", + "name": "Beata Szturemska" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + { + "id": "75431", + "title": "Security Vulnerabilities Decomposition: Another way to look at Vulnerabilities", + "description": "In most companies security is driven by compliance regulations. The policies are designed to contain the CWEs each company is interested to comply with. The result of this approach is a high number of insecure applications are still produced and injection is still King. Is there another way to secure the software in a more developer friendly manner? \r\n\r\nThis presentation will look at security vulnerabilities from a different angle. We will decompose the vulnerabilities into the security controls that prevent them and developers are familiar with. We will flip the security from focusing on vulnerabilities (measured at the end) to focus on the security controls which can be used by developers from beginning in software development cycle. \r\n\r\nRecommended to all developers looking to integrate security in their software applications.\r\n", + "startsAt": "2019-06-21T15:00:00", + "endsAt": "2019-06-21T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "b30243a2-2cc9-403e-a146-5496c9d199dc", + "name": "Katy Anton" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + { + "id": "99512", + "title": "Getting started with Azure DevOps", + "description": "DevOps is about people, process, and products. Getting it all right requires effort, but the benefits to your organization and customers can be huge. Microsoft has a fantastic set of products that can help you get the most out of the cloud with any language on any platform. In this demo-heavy session, Donovan Brown shows you how to transform your team.", + "startsAt": "2019-06-21T16:20:00", + "endsAt": "2019-06-21T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "266bf958-048e-4c55-b01f-398b90dfe5e9", + "name": "Donovan Brown" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4486, + "name": "Room 8", + "sessions": [ + { + "id": "98898", + "title": "From circuit board design to finished product: the hobbyist’s guide to hardware manufacturing", + "description": "Ever wondered how hardware is made, or curious about making your own? \r\n\r\nIn this session, we will share our experiences with building a programmable gamepad for use in IoT workshops. The gamepad is equipped with: \r\n\r\n- WiFi and Bluetooth\r\n- Touch screen\r\n- Microphone and speaker\r\n- Joypad and buttons\r\n- Integrated sensors\r\n\r\nWe will cover the entire production process, including:\r\n\r\n- Designing the PCB (Printed Circuit Board)\r\n- Choosing a microcontroller and parts\r\n- Finding, ordering and assembling components\r\n- Pulling together firmware, drivers and software\r\n\r\nWe conclude with live, interactive demos using the gamepad. ", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "d077d84c-cd4a-4f37-a24f-4529c00af63b", + "name": "Sebastian Roll" + }, + { + "id": "176e8ada-747f-4cd3-9244-466f9982ff2b", + "name": "Hans Elias B. Josephsen" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + { + "id": "98762", + "title": "Creating solutions for everyone", + "description": "When we create applications and products we simplify the messy, complex and inconvenient nature of the real world and follow established but flawed approaches to interfaces and interactions.\r\n \r\nIn this session we'll discuss the patterns and practices we can follow to make our solutions work for everyone. We'll cover everything from form design to algorithms to thinking about how we store and structure our applications data. \r\n \r\nEveryone wins when we all play - come to this session and make sure your applications and products work for all.", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "c8fb8671-9000-4565-9d02-e7dfb985268d", + "name": "Alex Mackey" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + { + "id": "98781", + "title": "War stories from .NET team", + "description": "Expect deep dive into a few interesting investigations we faced on .NET team in the last decade.\r\nWar stories about:\r\n\t• Investigations spanning years,\r\n\t• Dormant bugs coming to life after a decade,\r\n\t• Root-causes leading to surprising places,\r\n\t• How we rooted-cause problems with minimal information available,\r\n\t• Shocking impact of bugs on real world.\r\n\r\nWe will also cover:\r\n\t• Root-causing HW bugs (avoid the one-machine problem),\r\n\t• The value and art of minimal repro,\r\n\t• Innovation and compatibility - the age-old rivals.", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "731fd563-13a2-4fa9-87b6-331dc1293ec1", + "name": "Karel Zikmund" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + { + "id": "98812", + "title": "You get an actor, you get an actor, everybody gets an actor - Building personalization with Orleans", + "description": "Everybody is different and with actor modelling we can treat each user in isolation without worrying about consistency, side effects or any other users. \r\n\r\nIn this talk we'll look at why we chose Orleans, an open source Virtual Actor platform for distributed high-scale computing applications, when building a new personalization platform for favorites and progress at tv.nrk.no and radio.nrk.no. We'll dive into how actor modelling is different and discuss some of the design decisions we made and look at how we implemented this in Orleans with f#.\r\n\r\nSoftware without a build pipeline and deployment strategy is not an option, and Orleans is no different. It takes care and planning, so we'll round off with a look at how we build with docker, deploy to Azure Kubernets Service and monitor with Application Insights to sleep well.", + "startsAt": "2019-06-21T15:00:00", + "endsAt": "2019-06-21T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "ff7ad940-8ce5-4b49-86bc-6e47535db8f6", + "name": "Harald Schult Ulriksen" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + { + "id": "99371", + "title": "Futurology for Developers - the Next 30 Years in Tech", + "description": "2019 is the 30th anniversary of my first job in tech. On my first day I was given a Wyse 60 terminal attached via RS232 cables to a Tandon 286, and told to learn C from a dead tree so I could write text applications for an 80x24 character screen. Fast-forward to now: my phone is about a million times more powerful than that Tandon; screens are 3840x2160 pixels; every computer in the world is attached to every other thing with no cables; and we code using... still basically C.\r\n\r\nHaving lived through all these changes in realtime, and as an incurable neophile, I think I can make an educated guess as to what the next 30 years are going to be like, and what we're all going to be doing by 2049. If anything, I'm going to underestimate it, but hopefully you'll be inspired, invigorated and maybe even informed about the future of your career in tech.", + "startsAt": "2019-06-21T16:20:00", + "endsAt": "2019-06-21T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "70590ad0-b1b3-40b8-b05d-b58722ef9d9d", + "name": "Mark Rendle" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4487, + "name": "Room 9", + "sessions": [ + { + "id": "98843", + "title": "Cognitive biases in software development", + "description": "Our brains have evolved over millions of years to help us function in a complicated and crazy world, but the heuristics of our ancestors can sometimes give rise to unfortunate beliefs and behaviours that don’t correlate to the world we live in today.\r\n\r\nAs a software consultant, part of my role is helping teams and customers to understand the problems they’re trying to solve and how best to solve them. Throughout my career I have seen and fallen into many of these common cognitive biases and helped myself and others to try to negate them.\r\n\r\nIn this talk I will explore the most common biases I’ve seen in software development teams and how we can build practices and think our way out of these misconceptions.", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "af24f91d-252d-4cdf-b148-78110c91a803", + "name": "Ian Hughes" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + { + "id": "98547", + "title": "The Visible Developer: Why You Shouldn't Blend In", + "description": "Ever wonder how some technical people are recognized and promoted quicker than others with the same skillset? Yes, there is a formula to make it more likely. We will explore the habits of well known developers outside of their coding chops, to identify what additionally allowed them to become a trusted and known voice in their environment. This approach can be a benefit to you, no matter how junior or senior you are.", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "da1a1990-71d2-45dd-a213-c04430b64d87", + "name": "Heather Downing" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + { + "id": "98711", + "title": "Celebrate Your Expert: Overcoming Imposter Syndrome", + "description": "If you were asked “In what areas are you an expert,” how would you answer? Would you answer at all? If your friends, colleagues, and peers were asked about your expertise, would the answer change? That word ‘expert’ gets in our way. Our self-modesty blocks self-assessment of our talents. It damages our self-worth. It leads to imposter syndrome. Break out of the cycle. Learn to acknowledge, accept, and own your talents. Let’s celebrate our expert.", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "5698811a-4c31-4537-970d-e427009e0cca", + "name": "Jay Harris" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + { + "id": "99879", + "title": "Lightning Talks (People)", + "description": "Lightning talks (approx 10-15 minutes each)\r\n\r\nTalk 1: How to tame your team monsters! - Hanne Lian\r\n\r\nIn our everyday lives as designers, we encounter several types of monsters (you know; colleagues and clients). What can we do to tame these monsters into submission so that they will produce our wonderful designs? We will introduce you to the most common monsters in the workplace and give you some of our tools to handle them.\r\n\r\n-----------------------------------------------------------------------\r\n\r\nTalk 2: I Love Learning From People! - Bryan Hogan\r\n\r\nI've been podcasting for almost five years and I love making every single episode. I talk to people from around the world about what they love doing, and share this with everyone. \r\n\r\nMost people you meet love to talk about topics that interest them and with the right questions they will tell you everything they know.\r\n\r\nIn just ten short minutes I'm going to share some of what I've learned about how you can learn from others - how to ask questions, how to listen, how to encourage, when to disagree, when to interrupt and when to stay quiet.\r\n\r\n-----------------------------------------------------------------------\r\n\r\nTalk 3: \"OMG! A Girl?!\" What to do when a woman joins your team - Meg Gotshall\r\n\r\nDon’t panic! Often when I join a team, my new colleagues second guess each and every behavior. Inevitably, this leads to some awkward situations (and in the wake of #MeToo, even fear)!\r\n\r\nAlthough women still make up a rather small percentage of the tech workforce, we’re not as uncommon as narwhals or unicorns, so I’d like to take a few minutes to talk candidly about how we can make this transition smoother and simpler for both sides. Applying a programmer’s pragmatism to social interactions, we can debug our working environment and hopefully make it run more smoothly.\r\n\r\n-----------------------------------------------------------------------\r\n\r\nTalk 4: How to deal with your demons - Lubaba Farin Tanisha\r\n\r\nShould you care to know more about your biases? Does it even remotely related to software development? Is being aware of them make you a better software engineer? The answers to all these questions are: Oh yes! No matter what methodology or process you follow, it is possible to fall through the cracks for numerous amount of facts that you could have avoided if you knew about them before. If you knew that you are actually carrying many of them. So join my talk, I will walk you through a path that would perhaps make you discover a new you, with a brand new mindset to deal with your tasks, and of course to deal with your demons.\r\n\r\n-----------------------------------------------------------------------\r\n\r\nTalk 5: Emojis – the fun and weird parts! - Jøran Vagnby Lillesand\r\n\r\nCome get a time out from useful learning and get a brief introduction to the surprisingly interesting world of emojis!\r\n\r\nEmojis – to most of us they're just a weird distraction from proper language. But they're actually a rather cool piece of technology (!) with a meaningful impact on society. I'll teach you 3 things you didn't know about emojis, but you'll be glad you do!\r\n\r\n-----------------------------------------------------------------------", + "startsAt": "2019-06-21T15:00:00", + "endsAt": "2019-06-21T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e88a72e9-22aa-48d8-8395-704e70a791de", + "name": "Hanne Lian" + }, + { + "id": "de972e57-7765-4c38-9dcd-5981587c1433", + "name": "Bryan Hogan" + }, + { + "id": "0beddeb8-a1af-4cf1-822a-c51124043b43", + "name": "Meg Gotshall" + }, + { + "id": "5ee74d34-d9e2-4dea-ab4f-a32a5a647014", + "name": "Lubaba Farin Tanisha" + }, + { + "id": "7577e0ae-3f98-4649-a043-7dc915581546", + "name": "Jøran Vagnby Lillesand" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + { + "id": "121584", + "title": "Descaling Agile", + "description": "After the agile community solved how to do programming, testing, release and product management, the hot topic for our industry today seems to be scaling. In an ironic twist for a movement started with ‘people over process’, big consultancies today sell scaling models based on everything from tribes to witchcraft, offering to make agile disciplined and safe.\r\n\r\nGojko will help you cut through all the mess and separate out signal from noise.", + "startsAt": "2019-06-21T16:20:00", + "endsAt": "2019-06-21T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "c4a6643a-3233-437c-b1ae-c7024e09fc49", + "name": "Gojko Adzic" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4488, + "name": "Room 10", + "sessions": [ + { + "id": "82082", + "title": "Workshop: Doing Docker DevOps Style - Part 1/2", + "description": "This training introduces you to Docker and container technology for DevOps teams. We will show you how to apply DevOps practices to cloud-based container solutions, complete with hands-on exercises. The training uses Microsoft tooling and technology, but the skills you will learn can be applied in any technology stack. After the workshop you will be able to do Docker DevOps style. \r\n\r\nAgenda:\r\nBig picture: DevOps with cloud-based container clusters \r\nAccelerating your inner development loop\r\nFrom development to production in record-time with confidence \r\nMonitoring and feedback while running in production \r\nAutomated provisioning of infrastructure \r\n\r\nObjectives:\r\nUnderstand the implications for DevOps teams to build, deploy and run container based solutions in a cloud environment.\r\nAutomate everything from infrastructure to deployment\r\nAchieve full traceability from source code to production incidents \r\nPractice finding and fixing a bug without downtime \r\nGet hands-on experience supporting DevOps practices with available tools\r\nTarget audience\r\n\r\nAudience:\r\nThis training is intended for developers and architects that want to learn about the new DevOps practices and tooling for a cloud-based Microsoft solution.\r\n\r\nGet a running start with the labs! \r\nThis workshop is specific towards Windows as the operating system for your machine. (The labs can also be done on Linux, although this can be a bit more challenging.)\r\n\r\nYou will need to have a development IDE installed. The preferred IDE is Visual Studio 2017. Alternatively, you can use Visual Studio Code, but keep in mind that the labs are tailored to Visual Studio 2017. \r\nYou are also going to need Docker Desktop and git. \r\nFor some labs, you'll need an Azure subscription. If you do not have one, you can create a free trial account at Microsoft Azure. It will require a credit card, but it will not be charged.", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "32249d51-53d2-46cd-92d0-4c2ee9ffdb08", + "name": "Loek Duys" + }, + { + "id": "223d2b9d-a582-4e14-bebb-d636fb030bda", + "name": "Alex Thissen" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + { + "id": "128721", + "title": "Workshop: Doing Docker DevOps Style - Part 2/2", + "description": "This training introduces you to Docker and container technology for DevOps teams. We will show you how to apply DevOps practices to cloud-based container solutions, complete with hands-on exercises. The training uses Microsoft tooling and technology, but the skills you will learn can be applied in any technology stack. After the workshop you will be able to do Docker DevOps style.\r\n\r\nAgenda:\r\nBig picture: DevOps with cloud-based container clusters \r\nAccelerating your inner development loop\r\nFrom development to production in record-time with confidence \r\nMonitoring and feedback while running in production \r\nAutomated provisioning of infrastructure \r\n\r\nObjectives:\r\nUnderstand the implications for DevOps teams to build, deploy and run container based solutions in a cloud environment.\r\nAutomate everything from infrastructure to deployment\r\nAchieve full traceability from source code to production incidents \r\nPractice finding and fixing a bug without downtime \r\nGet hands-on experience supporting DevOps practices with available tools\r\nTarget audience\r\n\r\nAudience:\r\nThis training is intended for developers and architects that want to learn about the new DevOps practices and tooling for a cloud-based Microsoft solution.\r\n\r\nGet a running start with the labs! \r\nThis workshop is specific towards Windows as the operating system for your machine. (The labs can also be done on Linux, although this can be a bit more challenging.)\r\n\r\nYou will need to have a development IDE installed. The preferred IDE is Visual Studio 2017. Alternatively, you can use Visual Studio Code, but keep in mind that the labs are tailored to Visual Studio 2017. \r\nYou are also going to need Docker Desktop and git. \r\nFor some labs, you'll need an Azure subscription. If you do not have one, you can create a free trial account at Microsoft Azure. It will require a credit card, but it will not be charged.", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "32249d51-53d2-46cd-92d0-4c2ee9ffdb08", + "name": "Loek Duys" + }, + { + "id": "223d2b9d-a582-4e14-bebb-d636fb030bda", + "name": "Alex Thissen" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + { + "id": "98801", + "title": "Workshop: Learning by failing -Root Cause Analysis in Practice - Part 1/2", + "description": "Do you have this feeling certain features will yet again start failing in upcoming release? When you catch a bug, does it seem like a deja vu? Incidents happen. Most of us think of them as materialised risks, but they also can be considered as opportunity. Opportunity to learn and improve. Would you be interested to learn how to draw conclusions from failures, propose corrective and preventive actions, and with them improve your development process and grow quality mindset in your team? This is a workshop for you.\r\n\r\nWe are all agile nowadays, thus we all strive to self improve iteration over iteration. Regular retrospectives help flush out issues with delivery process, compare current iteration with previous, identify things need addressing, areas worth investing in to increase velocity.\r\n\r\nHowever, what happens when we catch a bug? Do we sit together as a team to identify what went wrong as we would normally do seeing a drop in our velocity in current sprint? I don’t think so. Most likely team will fix the bug and move on with feature development. Probably new regression tests will be added to prevent the bug from happening in future.\r\n\r\nRegression doesn’t prevent bugs from happening. It helps with catching recurring symptoms of deeper problems, before they reach our customer and our users. Tests alone don’t address root causes. We’re like doctors prescribing yet another drugs. Not spending enough time on doing patient interview to find problems with lifestyle. Missing nutrients in our team diet.\r\n\r\nYou will learn how to spot and prevent sources of bugs. We’ll walk you through Root Cause Analysis process on a real life incident you can relate to. Help you understand all vital parts of such analysis, and show you how you can conduct similar process next time you catch a bug.\r\n\r\nDuring workshop you will learn:\r\n-techniques helping build context in which incident happened,\r\n-how to build timeline and why it’s important to have one,\r\n-how to identify causal factors and how they differ from root cause,\r\n-techniques helping figure out root cause,\r\n-what are preventive and corrective actions,\r\n-how root cause analysis can not only help prevent bugs from recurring but improve your testing skills.\r\n \r\nKey takeaways:\r\n- what is root cause analysis\r\n- what are causal factors and how they are different from root causes\r\n- techniques helping identify root cause, propose preventive and corrective actions\r\n- how being better in identifying root causes can help you become better tester by focusing your attention on most likely broken parts of your system\r\n\r\n\r\n\r\nParticipant requirements: Nothing. This is an offline workshop.", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "5382406b-bac8-4507-a490-346adbde4163", + "name": "Kasia Balcerzak" + }, + { + "id": "cb564f46-518e-4ab2-b035-58f8f611eb20", + "name": "Bart Szulc" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + { + "id": "128723", + "title": "Workshop: Learning by failing - Root Cause Analysis in Practice - Part 2/2", + "description": "Do you have this feeling certain features will yet again start failing in upcoming release? When you catch a bug, does it seem like a deja vu? Incidents happen. Most of us think of them as materialised risks, but they also can be considered as opportunity. Opportunity to learn and improve. Would you be interested to learn how to draw conclusions from failures, propose corrective and preventive actions, and with them improve your development process and grow quality mindset in your team? This is a workshop for you.\r\n\r\nWe are all agile nowadays, thus we all strive to self improve iteration over iteration. Regular retrospectives help flush out issues with delivery process, compare current iteration with previous, identify things need addressing, areas worth investing in to increase velocity.\r\n\r\nHowever, what happens when we catch a bug? Do we sit together as a team to identify what went wrong as we would normally do seeing a drop in our velocity in current sprint? I don’t think so. Most likely team will fix the bug and move on with feature development. Probably new regression tests will be added to prevent the bug from happening in future.\r\n\r\nRegression doesn’t prevent bugs from happening. It helps with catching recurring symptoms of deeper problems, before they reach our customer and our users. Tests alone don’t address root causes. We’re like doctors prescribing yet another drugs. Not spending enough time on doing patient interview to find problems with lifestyle. Missing nutrients in our team diet.\r\n\r\nYou will learn how to spot and prevent sources of bugs. We’ll walk you through Root Cause Analysis process on a real life incident you can relate to. Help you understand all vital parts of such analysis, and show you how you can conduct similar process next time you catch a bug.\r\n\r\nDuring workshop you will learn:\r\n-techniques helping build context in which incident happened,\r\n-how to build timeline and why it’s important to have one,\r\n-how to identify causal factors and how they differ from root cause,\r\n-techniques helping figure out root cause,\r\n-what are preventive and corrective actions,\r\n-how root cause analysis can not only help prevent bugs from recurring but improve your testing skills.\r\n\r\nKey takeaways:\r\n- what is root cause analysis\r\n- what are causal factors and how they are different from root causes\r\n- techniques helping identify root cause, propose preventive and corrective actions\r\n- how being better in identifying root causes can help you become better tester by focusing your attention on most likely broken parts of your system\r\n\r\nParticipant requirements: Nothing. This is an offline workshop.", + "startsAt": "2019-06-21T15:00:00", + "endsAt": "2019-06-21T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "5382406b-bac8-4507-a490-346adbde4163", + "name": "Kasia Balcerzak" + }, + { + "id": "cb564f46-518e-4ab2-b035-58f8f611eb20", + "name": "Bart Szulc" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4504, + "name": "Room 11", + "sessions": [ + { + "id": "80729", + "title": "Workshop: Make your own voice assistant application - Part 1/2", + "description": "Do you own a voice assistant such as Google Home or Amazon Alexa? Have you ever wanted to create your own program to talk to? Learn how to create a Google voice assistant action connecting to your custom coded service.\r\n\r\nAt this workshop you will get to know the basics on how to create custom dialogues, parse questions and have your server give dynamic responses to the user. We will provide an existing backend for you to modify to respond to the queries from your new Google voice assistant action. \r\n\r\nRemember to bring your own computer or a friend with a computer :) \r\n", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "8c7086a0-fd3b-4c11-b085-1182faa39e7b", + "name": "Ingrid Guren" + }, + { + "id": "8175530b-f3a8-4830-b102-eb6aa7dd2263", + "name": "Mathias Johan Johansen" + } + ], + "categories": [], + "roomId": 4504, + "room": "Room 11" + }, + { + "id": "128722", + "title": "Workshop: Make your own voice assistant application - Part 2/2", + "description": "Do you own a voice assistant such as Google Home or Amazon Alexa? Have you ever wanted to create your own program to talk to? Learn how to create a Google voice assistant action connecting to your custom coded service.\r\n\r\nAt this workshop you will get to know the basics on how to create custom dialogues, parse questions and have your server give dynamic responses to the user. We will provide an existing backend for you to modify to respond to the queries from your new Google voice assistant action. \r\n\r\nRemember to bring your own computer or a friend with a computer :)", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "8c7086a0-fd3b-4c11-b085-1182faa39e7b", + "name": "Ingrid Guren" + }, + { + "id": "8175530b-f3a8-4830-b102-eb6aa7dd2263", + "name": "Mathias Johan Johansen" + } + ], + "categories": [], + "roomId": 4504, + "room": "Room 11" + }, + { + "id": "98955", + "title": "Workshop: I Don’t Need No Stinkin’ Framework - Mastering Shadow DOM", + "description": "Want to create components that work regardless of the front-end framework you are using?\r\nTired of throwing away your components when you change front-end frameworks?\r\nWish you could just code it once and reuse it on all of your projects?\r\n\r\nMe too! Components are a staple of front-end development as they increase development speed, consistency, and reduce the need for repeat code. To create components often we turn to frameworks such as Angular, React, and Vue but we don't need to. \r\n\r\nUsing nothing more than HTML and Javascript that is readily available to us in all modern browsers we can create components that work without being tied to any one front-end framework. \r\n\r\nYou will walk away with the knowledge you need to go forth and create your own components, understand how to make them look gorgeous, and what if any limitations there are. Also, find out how you can bring back the blink tag!\r\n", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "3336b62f-c81b-4892-8247-d34043767210", + "name": "Martine Dowden" + } + ], + "categories": [], + "roomId": 4504, + "room": "Room 11" + } + ], + "hasOnlyPlenumSessions": false + }, + { + "id": 4489, + "name": "Expo", + "sessions": [ + { + "id": "99510", + "title": "Enterprise transformation (and you can too)", + "description": "“That would never work here.” You’ve likely heard this sentiment (or maybe you’ve even said it yourself). Good news: change is possible. Donovan Brown explains how Microsoft's Azure DevOps formerly VSTS went from a three-year waterfall delivery cycle to three-week iterations and open sourced the Azure DevOps task library and the Git Virtual File System.", + "startsAt": "2019-06-21T09:00:00", + "endsAt": "2019-06-21T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "266bf958-048e-4c55-b01f-398b90dfe5e9", + "name": "Donovan Brown" + } + ], + "categories": [], + "roomId": 4489, + "room": "Expo" + } + ], + "hasOnlyPlenumSessions": false + } + ], + "timeSlots": [ + { + "slotStart": "09:00:00", + "rooms": [ + { + "id": 4489, + "name": "Expo", + "session": { + "id": "99510", + "title": "Enterprise transformation (and you can too)", + "description": "“That would never work here.” You’ve likely heard this sentiment (or maybe you’ve even said it yourself). Good news: change is possible. Donovan Brown explains how Microsoft's Azure DevOps formerly VSTS went from a three-year waterfall delivery cycle to three-week iterations and open sourced the Azure DevOps task library and the Git Virtual File System.", + "startsAt": "2019-06-21T09:00:00", + "endsAt": "2019-06-21T10:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "266bf958-048e-4c55-b01f-398b90dfe5e9", + "name": "Donovan Brown" + } + ], + "categories": [], + "roomId": 4489, + "room": "Expo" + }, + "index": 11 + } + ] + }, + { + "slotStart": "10:20:00", + "rooms": [ + { + "id": 4479, + "name": "Room 1", + "session": { + "id": "81395", + "title": "Machine Learning: The Bare Math Behind Libraries", + "description": "Machine learning is one of the hottest buzzwords in technology today as well as one of the most innovative fields in computer science – yet people use libraries as black boxes without basic knowledge of the field. In this session, we will strip them to bare math, so next time you use a machine learning library, you'll have a deeper understanding of what lies underneath.\r\n\r\nDuring this session, we will first provide a short history of machine learning and an overview of two basic teaching techniques: supervised and unsupervised learning.\r\n\r\nWe will start by defining what machine learning is and equip you with an intuition of how it works. We will then explain gradient descent algorithm with the use of simple linear regression to give you an even deeper understanding of this learning method. Then we will project it to supervised neural networks training.\r\n\r\nWithin unsupervised learning, you will become familiar with Hebb’s learning and learning with concurrency (winner takes all and winner takes most algorithms). We will use Octave for examples in this session; however, you can use your favorite technology to implement presented ideas.\r\n\r\nOur aim is to show the mathematical basics of neural networks for those who want to start using machine learning in their day-to-day work or use it already but find it difficult to understand the underlying processes. After viewing our presentation, you should find it easier to select parameters for your networks and feel more confident in your selection of network type, as well as be encouraged to dive into more complex and powerful deep learning methods.\r\n\r\nLevel: beginner\r\n", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f5715729-0aeb-4945-a65e-9dd0d6ddf424", + "name": "Łukasz Gebel" + }, + { + "id": "826496af-d697-40eb-a5d8-2c16bda34181", + "name": "Piotr Czajka" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + "index": 0 + }, + { + "id": 4480, + "name": "Room 2", + "session": { + "id": "98412", + "title": "Hacking with Go", + "description": "Learning Go programming is easy. Go is popular and becomes even more also in security experts world. Wanted to feel a bit as a hacker? Learn a new language? Or do both at the same time? This session is about it. \r\nSo let's jump into hands-on session and explore how security tools can be written in Go. How to enumerate network resources, extract an information, sniff packets and do port scanning, brute force and more all with Go. \r\nBy the end, you will have more ideas what else can be written or re-written in Go. ", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "4c3efe89-ab58-4b28-a9c3-78251f25ee06", + "name": "Victoria Almazova" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + "index": 1 + }, + { + "id": 4481, + "name": "Room 3", + "session": { + "id": "98167", + "title": "Evolving compositional user interfaces", + "description": "Ever since we started breaking applications into services, be it in the era of SOA or more recently with microservices, we’ve struggled to incorporate user interfaces into our decoupled, distributed architectures. We’ve seen frontends versioned separately with tight coupling to our services, breaking cohesion. We’ve seen the rise of Backend-For-Frontend and the emerge of micro frontends. We talk about composition, yet so many projects fail to implement actual composition. Instead we end up with some kind of compromise, with repeated business logic in the front-end, back-end and API, making it hard to scale – especially when multiple teams are involved – causing lock-step deployment, latency, bottlenecks and coordination issues.\r\n\r\nWhat if we could find a viable solution that allowed us to scale development, keep distribution and cohesion and also provide composition of user interfaces?\r\n\r\nIn this talk you are introduced to the evolution of compositional user interfaces and existing patterns while we discover their pros and cons, before diving into the architecture and development of compositional interfaces using hypermedia and micro-frontends. We go beyond the simple “Hello World” example that always seems to work, and you’ll learn patterns in modelling and design that will get you up and running with decoupled, composed user interfaces in your day job.\r\n", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "a6b5a582-ff8e-4874-84c7-35e095954666", + "name": "Thomas Presthus" + }, + { + "id": "1e4b0b48-cc95-4059-bff4-32103fb3a496", + "name": "Asbjørn Ulsberg" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + "index": 2 + }, + { + "id": 4482, + "name": "Room 4", + "session": { + "id": "97917", + "title": "Modern Continuous Integration with Azure Pipelines", + "description": "CI builds shouldn't be relegated to an old desktop underneath a developers desk: modern software demands a modern build and release system. Edward Thomson introduces a cloud-first way of thinking about your builds, taking advantage of containers for simpler, reproducible configuration of build environments, building and testing across more platforms with Docker and QEMU, leveraging GitHub Actions for automation and other strategies to keep your software project's quality high while keeping your costs and overhead low.", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "fee375b8-047c-4ea2-ab43-9837f2420b19", + "name": "Edward Thomson" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + "index": 3 + }, + { + "id": 4483, + "name": "Room 5", + "session": { + "id": "86189", + "title": "Serverless with Knative", + "description": "When you build a serverless app, you either tie yourself to a cloud provider, or you end up building your own serverless stack. Knative provides a better choice. Knative extends Kubernetes to provide a set of middleware components (build, serving, events) for modern, source-centric, and container-based apps that can run anywhere. In this talk, we’ll see how we can use Knative primitives to build a serverless app that utilizes the Machine Learning magic of the cloud. ", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f79e1173-a28c-4ad1-8885-7c52ba397fe3", + "name": "Mete Atamel" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + "index": 4 + }, + { + "id": 4484, + "name": "Room 6", + "session": { + "id": "99531", + "title": "Deep Learning in Microsoft Azure: CNTK, CaffeOnSpark and Tensorflow", + "description": "What is Microsoft’s approach to Deep Learning, and how does it differ from Open Source alternatives? In this session, we will look at Deep Learning, and how it can be implemented in Microsoft and Azure technologies with the Cognitive Toolkit, Tensorflow in Azure and CaffeOnSpark on AzureHDInsight. Join this session in order to understand deep learning better, and how we can use it to provide business and technical benefits in our organizations", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "f63d9644-1b19-47e1-b84a-ad056419806e", + "name": "Jen Stirrup" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + "index": 5 + }, + { + "id": 4485, + "name": "Room 7", + "session": { + "id": "98731", + "title": "Making the most of Security Tests", + "description": "There is a number of security tests such as security code reviews, white box testing, penetration testing, red teaming to assure the security of a product and an environment where it is deployed.\r\nSome of the tests are mandated by the Secure Development Lifecycle, but some remain optional. The open question remains, when to use a particular test and how it impacts the ultimate decision whether a particular product requires additional investments.\r\n\r\nThis presentation uses a real-world red team attack against a multi-layer product as an example for discussing the differences of security tests. It shows, how the attacker starts with user-facing XML-RPC interface, breaks through multiple defense layers and ends up with root access to the database server and target data exfiltration. The example points out:\r\n- different areas where the tests improve the knowledge about the security risks of the product,\r\n- what are the requirements to obtain actionable results and\r\n- who needs to be involved to actually benefit from the results reported.\r\nThe presentation encourages expanding the security tests beyond the product features towards the security of the environment where it is deployed, supporting processes, as well as a product developers and administrators. It also shows, how the closer collaboration between different teams improves the overall security of the product", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "93cec660-9cdb-4ee8-af10-4eae804e3557", + "name": "Paweł Krzywicki" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + "index": 6 + }, + { + "id": 4486, + "name": "Room 8", + "session": { + "id": "98898", + "title": "From circuit board design to finished product: the hobbyist’s guide to hardware manufacturing", + "description": "Ever wondered how hardware is made, or curious about making your own? \r\n\r\nIn this session, we will share our experiences with building a programmable gamepad for use in IoT workshops. The gamepad is equipped with: \r\n\r\n- WiFi and Bluetooth\r\n- Touch screen\r\n- Microphone and speaker\r\n- Joypad and buttons\r\n- Integrated sensors\r\n\r\nWe will cover the entire production process, including:\r\n\r\n- Designing the PCB (Printed Circuit Board)\r\n- Choosing a microcontroller and parts\r\n- Finding, ordering and assembling components\r\n- Pulling together firmware, drivers and software\r\n\r\nWe conclude with live, interactive demos using the gamepad. ", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "d077d84c-cd4a-4f37-a24f-4529c00af63b", + "name": "Sebastian Roll" + }, + { + "id": "176e8ada-747f-4cd3-9244-466f9982ff2b", + "name": "Hans Elias B. Josephsen" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + "index": 7 + }, + { + "id": 4487, + "name": "Room 9", + "session": { + "id": "98843", + "title": "Cognitive biases in software development", + "description": "Our brains have evolved over millions of years to help us function in a complicated and crazy world, but the heuristics of our ancestors can sometimes give rise to unfortunate beliefs and behaviours that don’t correlate to the world we live in today.\r\n\r\nAs a software consultant, part of my role is helping teams and customers to understand the problems they’re trying to solve and how best to solve them. Throughout my career I have seen and fallen into many of these common cognitive biases and helped myself and others to try to negate them.\r\n\r\nIn this talk I will explore the most common biases I’ve seen in software development teams and how we can build practices and think our way out of these misconceptions.", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "af24f91d-252d-4cdf-b148-78110c91a803", + "name": "Ian Hughes" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + "index": 8 + }, + { + "id": 4488, + "name": "Room 10", + "session": { + "id": "82082", + "title": "Workshop: Doing Docker DevOps Style - Part 1/2", + "description": "This training introduces you to Docker and container technology for DevOps teams. We will show you how to apply DevOps practices to cloud-based container solutions, complete with hands-on exercises. The training uses Microsoft tooling and technology, but the skills you will learn can be applied in any technology stack. After the workshop you will be able to do Docker DevOps style. \r\n\r\nAgenda:\r\nBig picture: DevOps with cloud-based container clusters \r\nAccelerating your inner development loop\r\nFrom development to production in record-time with confidence \r\nMonitoring and feedback while running in production \r\nAutomated provisioning of infrastructure \r\n\r\nObjectives:\r\nUnderstand the implications for DevOps teams to build, deploy and run container based solutions in a cloud environment.\r\nAutomate everything from infrastructure to deployment\r\nAchieve full traceability from source code to production incidents \r\nPractice finding and fixing a bug without downtime \r\nGet hands-on experience supporting DevOps practices with available tools\r\nTarget audience\r\n\r\nAudience:\r\nThis training is intended for developers and architects that want to learn about the new DevOps practices and tooling for a cloud-based Microsoft solution.\r\n\r\nGet a running start with the labs! \r\nThis workshop is specific towards Windows as the operating system for your machine. (The labs can also be done on Linux, although this can be a bit more challenging.)\r\n\r\nYou will need to have a development IDE installed. The preferred IDE is Visual Studio 2017. Alternatively, you can use Visual Studio Code, but keep in mind that the labs are tailored to Visual Studio 2017. \r\nYou are also going to need Docker Desktop and git. \r\nFor some labs, you'll need an Azure subscription. If you do not have one, you can create a free trial account at Microsoft Azure. It will require a credit card, but it will not be charged.", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "32249d51-53d2-46cd-92d0-4c2ee9ffdb08", + "name": "Loek Duys" + }, + { + "id": "223d2b9d-a582-4e14-bebb-d636fb030bda", + "name": "Alex Thissen" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + "index": 9 + }, + { + "id": 4504, + "name": "Room 11", + "session": { + "id": "80729", + "title": "Workshop: Make your own voice assistant application - Part 1/2", + "description": "Do you own a voice assistant such as Google Home or Amazon Alexa? Have you ever wanted to create your own program to talk to? Learn how to create a Google voice assistant action connecting to your custom coded service.\r\n\r\nAt this workshop you will get to know the basics on how to create custom dialogues, parse questions and have your server give dynamic responses to the user. We will provide an existing backend for you to modify to respond to the queries from your new Google voice assistant action. \r\n\r\nRemember to bring your own computer or a friend with a computer :) \r\n", + "startsAt": "2019-06-21T10:20:00", + "endsAt": "2019-06-21T11:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "8c7086a0-fd3b-4c11-b085-1182faa39e7b", + "name": "Ingrid Guren" + }, + { + "id": "8175530b-f3a8-4830-b102-eb6aa7dd2263", + "name": "Mathias Johan Johansen" + } + ], + "categories": [], + "roomId": 4504, + "room": "Room 11" + }, + "index": 10 + } + ] + }, + { + "slotStart": "11:40:00", + "rooms": [ + { + "id": 4479, + "name": "Room 1", + "session": { + "id": "84059", + "title": "Protecting sensitive data in huge datasets: Cloud tools you can use", + "description": "Before releasing a public dataset, practitioners need to thread the needle between utility and protection of individuals. Felipe Hoffa explores how to handle massive public datasets, taking you from theory to real life as they showcase newly available tools that help with PII detection and brings concepts like k-anonymity and l-diversity to the practical realm. You’ll also cover options such as removing, masking, and coarsening.\r\n\r\nWhat you'll learn:\r\n\r\n- Learn how to identify PII in massive datasets\r\n- Explore k-anonymity, l-diversity, and related research and options such as removing, masking, and coarsening\r\n- Gain experience with practical demos over massive datasets", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "28dd5c97-7753-4acf-b956-25e7467c31ab", + "name": "Felipe Hoffa" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + "index": 0 + }, + { + "id": 4480, + "name": "Room 2", + "session": { + "id": "98825", + "title": "Source Instrumentation for Monitoring C++ in Production", + "description": "It is essential to discuss how modern C++ code can be effectively instrumented, in order to effectively monitor it after deployment. This talk will focus on portable source instrumentation techniques such as logging, tracing and metrics. Straightforward, but well designed code additions can drastically ease the troubleshooting of functional issues, and identification of performance bottlenecks, in production.\r\n\r\nOf course when dealing with C++ performance is often critical, and so minimizing the cost of any instrumentation is also critical. Key to this is understanding the trade-off between the detail of information collected, and the overheads of exposing that information. It is also important to understand how best to benefit from advances in contemporary monitoring infrastructure, popularised by cloud environments.\r\n\r\nThis talk will open with some brief motivation towards monitoring and instrumentation. It will then walk through some practical code examples using some generic instrumentation primitives, based on proven principles employed in demanding production software. ", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "8ccea10a-7d68-4c6a-9d59-88f9355ccfff", + "name": "Steven Simpson" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + "index": 1 + }, + { + "id": 4481, + "name": "Room 3", + "session": { + "id": "128875", + "title": "Fabulous – F# for cross-platform mobile apps", + "description": "In this informal talk, I will describe Fabulous, a community-developed framework using F# to build cross-platform mobile and desktop Xamarin apps.\r\n\r\nCome and learn how this radical new approach to app programming makes your code simpler, more testable and helps avoid repetition. By embracing the React-like MVU architecture, you can do away with your Xaml, your behaviours, your converters, your templating, your MVVM and embrace the simplicity of functional model descriptions and view re-evalaution. I will talk about the concepts involved and how this differs from Model-View-ViewModel (MVVM), the tooling available and how yuo can get involved.\r\n\r\nThis is mostly a conceptual talk and won’t be full of sparkling demos: demo apps are available from the Fabulous community.\r\n\r\nNote, Fabulous is a community project and is at version 0.34 as of May 2019. It is not a supported product or framework from Microsoft.\r\n\r\nhttps://fsprojects.github.io/Fabulous/", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "68b8aef8-e1b3-4a1f-9b73-2562ec1af738", + "name": "Don Syme" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + "index": 2 + }, + { + "id": 4482, + "name": "Room 4", + "session": { + "id": "99261", + "title": "Dev and Test Agility for your Database with Docker", + "description": "Agile practices teach us how to deal with evolving applications but so often the data store is overlooked as a component of your application lifecycle. Database servers are monolothic, resource intensive and mostly viewed as set in stone. Encapsulating your database server in a container and your database in a storage container can dramatically lighten the load and make your database as agile as your model and other processes. And you can even use a serious enterprise class database like SQL Server this way. This session will show how to benefit from using a containerized version of SQL Server for Linux during development and testing. We'll also address concerns about data that needs to be persisted. You'll also get a peek at the DevOps side of this, including using images in your CI/CD process.", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "282a4701-f128-4b1d-bd67-da5d1f8b3eb0", + "name": "Julie Lerman" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + "index": 3 + }, + { + "id": 4483, + "name": "Room 5", + "session": { + "id": "99318", + "title": "Architecture: The Stuff That's Hard to Change", + "description": "We’ve all heard of the idea of ‘software architecture’. We’ve read books about domain-driven design and event sourcing, we’ve been to conferences and learned about micro services and REST APIs. Some of us remember working with n-tiers and stored procedures… some of us are still using them. But the role of a systems architect is still one of the most misunderstood things about the software development process. What does the architect actually do? If you’re working with a systems architect, what can you expect from them? And if you are a systems architect, what are your team expecting from you?\r\n\r\nIn this talk, Dylan will share his own insights into the idea of architecture as part of a software development process. We’ll explore some popular architectural patterns and processes - and a couple of obscure ones as well - and look at how, and when, you can incorporate those patterns into your own projects. We’ll talk about how the idea of software architecture has changed over time, and share some tips and advice for developers who find themselves working with architecture as part of their role.", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "1d7dcbfc-1de6-4228-8bd6-04f4ba1c4267", + "name": "Dylan Beattie" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + "index": 4 + }, + { + "id": 4484, + "name": "Room 6", + "session": { + "id": "98305", + "title": "System Stable : Robust connected applications with Polly, the .NET Resilience Framework", + "description": "Short Description\r\n\r\nIn this session I will show you how with just a few lines of code you can make your applications much more resilient and reliable. With Polly, the .NET resilience framework, your application can easily tolerate transient faults and longer outages in remote systems or infrastructure. \r\n\r\nAt the end of this hour you will know how to use all the features of Polly to make your application a rock solid piece of work. We’ll cover the reactive and proactive resilience strategies, starting with simple but very powerful retries and finishing with bulkhead isolation.\r\n\r\nOh, and did I mention Polly is a .NET Standard library so it will work on any application you can think of! \r\n\r\nJoin me for an hour, and your applications will never be the same.\r\n\r\n----------------------------------------------------------------------------------------------------------------------------------\r\n\r\nFull Description\r\n\r\nJoin me for this session and I will show you how with just a few lines of code, you can make your applications much more resilient and reliable. Let me tell you more… \r\n\r\nAlmost all applications now depend on connectivity, but what do you do when the infrastructure is unreliable or the remote system is down or returns an error? Does your application grind to a halt or just drop that single request? What if you could recover from these kinds of error, maybe even so quickly it won’t be noticed? \r\n \r\nWith Polly your application can easily tolerate transient faults and longer outages in remote systems or infrastructure. \r\n\r\nAt the end of this hour you will know how to use all the features of Polly to make your application a rock solid piece of work. \r\n\r\nWe’ll start with the simple but very powerful Retry Policy which lets you retry a failed request. If simple retries are not good enough for you, there is a Wait and Retry policy which introduces a delay between retries, giving the remote service time to recover before being hit again. Then I show you how to use the circuit breaker for when things have really gone wrong and a remote system is struggling under too much load or has failed. If all these attempts are unsuccessful and you are still not getting through to the remote system, you can return a default response or execute arbitrary code to call for human help (or restart the cloud) with the fallback policy. \r\n\r\nThat takes care of what you can do when things go wrong, but Polly also lets you take proactive steps to keep your application and the services it depends on healthy. \r\n\r\nTo get you started with proactive strategies, you will learn how caching can be used to store and return responses from an in-memory or distributed cache without having to hit the remote server every time. Or you can use bulkhead isolation to marshal resources within your application so that no one struggling part can take down the whole. Finally, I’ll show you how to fail quickly when your application is in danger of being overloaded or the remote systems is not responding in a timely fashion, this is done with the bulkhead isolation and the timeout polices. \r\n\r\nOh, and did I mention Polly is a .NET Standard library so it will work on any application you can think of! Join me for an hour, and your applications will never be the same. ", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "de972e57-7765-4c38-9dcd-5981587c1433", + "name": "Bryan Hogan" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + "index": 5 + }, + { + "id": 4485, + "name": "Room 7", + "session": { + "id": "98639", + "title": "Why FIDO Security Keys & Webauthn are Awesome", + "description": "Phishing can happen to anyone, and hackers know that. What could happen if someone compromised your git repo? How about your email?\r\n\r\nFIDO security keys are awesome at preventing phishing. This talk explains how they work, how they can protect you, and what you can implement to protect your users.\r\n", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "ab3a4f70-753c-420a-a1b1-c001af2c460e", + "name": "Jen Tong" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + "index": 6 + }, + { + "id": 4486, + "name": "Room 8", + "session": { + "id": "98762", + "title": "Creating solutions for everyone", + "description": "When we create applications and products we simplify the messy, complex and inconvenient nature of the real world and follow established but flawed approaches to interfaces and interactions.\r\n \r\nIn this session we'll discuss the patterns and practices we can follow to make our solutions work for everyone. We'll cover everything from form design to algorithms to thinking about how we store and structure our applications data. \r\n \r\nEveryone wins when we all play - come to this session and make sure your applications and products work for all.", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "c8fb8671-9000-4565-9d02-e7dfb985268d", + "name": "Alex Mackey" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + "index": 7 + }, + { + "id": 4487, + "name": "Room 9", + "session": { + "id": "98547", + "title": "The Visible Developer: Why You Shouldn't Blend In", + "description": "Ever wonder how some technical people are recognized and promoted quicker than others with the same skillset? Yes, there is a formula to make it more likely. We will explore the habits of well known developers outside of their coding chops, to identify what additionally allowed them to become a trusted and known voice in their environment. This approach can be a benefit to you, no matter how junior or senior you are.", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "da1a1990-71d2-45dd-a213-c04430b64d87", + "name": "Heather Downing" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + "index": 8 + }, + { + "id": 4488, + "name": "Room 10", + "session": { + "id": "128721", + "title": "Workshop: Doing Docker DevOps Style - Part 2/2", + "description": "This training introduces you to Docker and container technology for DevOps teams. We will show you how to apply DevOps practices to cloud-based container solutions, complete with hands-on exercises. The training uses Microsoft tooling and technology, but the skills you will learn can be applied in any technology stack. After the workshop you will be able to do Docker DevOps style.\r\n\r\nAgenda:\r\nBig picture: DevOps with cloud-based container clusters \r\nAccelerating your inner development loop\r\nFrom development to production in record-time with confidence \r\nMonitoring and feedback while running in production \r\nAutomated provisioning of infrastructure \r\n\r\nObjectives:\r\nUnderstand the implications for DevOps teams to build, deploy and run container based solutions in a cloud environment.\r\nAutomate everything from infrastructure to deployment\r\nAchieve full traceability from source code to production incidents \r\nPractice finding and fixing a bug without downtime \r\nGet hands-on experience supporting DevOps practices with available tools\r\nTarget audience\r\n\r\nAudience:\r\nThis training is intended for developers and architects that want to learn about the new DevOps practices and tooling for a cloud-based Microsoft solution.\r\n\r\nGet a running start with the labs! \r\nThis workshop is specific towards Windows as the operating system for your machine. (The labs can also be done on Linux, although this can be a bit more challenging.)\r\n\r\nYou will need to have a development IDE installed. The preferred IDE is Visual Studio 2017. Alternatively, you can use Visual Studio Code, but keep in mind that the labs are tailored to Visual Studio 2017. \r\nYou are also going to need Docker Desktop and git. \r\nFor some labs, you'll need an Azure subscription. If you do not have one, you can create a free trial account at Microsoft Azure. It will require a credit card, but it will not be charged.", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "32249d51-53d2-46cd-92d0-4c2ee9ffdb08", + "name": "Loek Duys" + }, + { + "id": "223d2b9d-a582-4e14-bebb-d636fb030bda", + "name": "Alex Thissen" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + "index": 9 + }, + { + "id": 4504, + "name": "Room 11", + "session": { + "id": "128722", + "title": "Workshop: Make your own voice assistant application - Part 2/2", + "description": "Do you own a voice assistant such as Google Home or Amazon Alexa? Have you ever wanted to create your own program to talk to? Learn how to create a Google voice assistant action connecting to your custom coded service.\r\n\r\nAt this workshop you will get to know the basics on how to create custom dialogues, parse questions and have your server give dynamic responses to the user. We will provide an existing backend for you to modify to respond to the queries from your new Google voice assistant action. \r\n\r\nRemember to bring your own computer or a friend with a computer :)", + "startsAt": "2019-06-21T11:40:00", + "endsAt": "2019-06-21T12:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "8c7086a0-fd3b-4c11-b085-1182faa39e7b", + "name": "Ingrid Guren" + }, + { + "id": "8175530b-f3a8-4830-b102-eb6aa7dd2263", + "name": "Mathias Johan Johansen" + } + ], + "categories": [], + "roomId": 4504, + "room": "Room 11" + }, + "index": 10 + } + ] + }, + { + "slotStart": "13:40:00", + "rooms": [ + { + "id": 4479, + "name": "Room 1", + "session": { + "id": "84838", + "title": "ML BuzzWords demystified", + "description": "Machine Learning is a fast evolving discipline and one of the hottest areas both in industry and academia, and it only keeps getting more traction. With such a quickly advancing field, it becomes increasingly hard to keep up with the new concepts. \r\nIf you find yourself lost in a forest of ML buzzwords and want to catch up, welcome to our session!\r\nWe will give you the gist of the latest trends in Machine Learning - from Reinforcement Learning and AutoML to ML bias - with zero formulas and maximum sense.\r\n\r\nBy the end of the session, you will be up-to-date with what is happening in the field.", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "61a48ebe-ebe0-427f-a1a1-eef2f7e92ed9", + "name": "Oleksandra Sopova" + }, + { + "id": "5937af3f-6906-46e8-86a9-0e9cefd5a080", + "name": "Natalia An" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + "index": 0 + }, + { + "id": 4480, + "name": "Room 2", + "session": { + "id": "99876", + "title": "Lightning Talks (Diverse)", + "description": "Lightning talks (approx 10-15 minutes each)\r\n\r\nTalk 1: 5 Lessons Learned from Implementing 40+ Machine Learning Projects - Xiaopeng Li\r\n\r\nMachine learning has reached the peak of Gartner's hype curve in 2018. Many companies are talking about it, while very few are actually doing it. At Inmeta, we have together with partners and clients implemented 40+ machine learning projects in the past few years. In this talk, I will share the top 5 lessons we learned from doing machine learning for real.\r\n\r\n-----------------------------------------------------------------------\r\n\r\nTalk 2: test && commit || revert. What?! - Kari Eline Strandjord\r\n\r\n`test && commit || revert` is a workflow developed during a week of code camp at Iterate with Kent Beck. The main idea is that your code should always be in a valid state. If the test passes, the code is committed. If it fails, you lose all your changes, and the code is forced back to the last valid state. At first, the idea seemed both unrealistic and a bit harsh. But after trying it out during a longer period writing an application in Elm, it did change my way of coding. \r\n\r\nThe talk will give a brief explanation of the workflow. I will also share my experiences from using it in a real project.\r\n\r\n-----------------------------------------------------------------------\r\n\r\nTalk 3: Five Ways to Break a Git Repository - Edward Thomson\r\n\r\nCan you break your Git repository? I hope not! That's where you keep all your stuff! Edward Thomson shows you five common mistakes that break Git repositories and how to fix them.\r\n\r\n-----------------------------------------------------------------------\r\n\r\nTalk 4: Unlocking the doors of parliament - Sindre Lindstad\r\n\r\nWhen Norway's Minister of Children and Families was instated, he enthusiastically showed the world the key to his new office through press photos.\r\n\r\nThe only problem was that it was a plastic punch-hole keycard, which meant anyone could make a copy.\r\n\r\nSo I made one with 3D printing (and lasers!). But does it work?\r\n\r\n----------------------------------------------------------------------- ", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "99aa52b8-e0ab-4bd8-be19-437cc4b93740", + "name": "Xiaopeng Li" + }, + { + "id": "a5357148-b11b-4ab0-822c-b650881773ef", + "name": "Kari Eline Strandjord" + }, + { + "id": "fee375b8-047c-4ea2-ab43-9837f2420b19", + "name": "Edward Thomson" + }, + { + "id": "5ec0ca76-bf24-4fce-bf3d-80656dadf1f6", + "name": "Sindre Lindstad" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + "index": 1 + }, + { + "id": 4481, + "name": "Room 3", + "session": { + "id": "98611", + "title": "An in-flight port from Angular to React, a tale of performance and happiness", + "description": "A real-world story of how we used some clever trickery to completely rewrite an app, bit by bit from Angular to React, resulting in better performance, a smaller footprint, a shorter feedback loop, less coupling, fewer bugs, increased development velocity and happier developers.\r\nWe did the re-write, while deploying to production frequently. New features were added to the product throughout the whole rewrite process, and stability was maintained throughout the entire process.\r\n\r\nThe application is an e-commerce payment solution (Nets Easy), used by numerous merchants in their web shops to get paid.", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "912bbb93-e7bd-4448-8854-19ef39fa5843", + "name": "Henning Christiansen" + }, + { + "id": "1e49e725-0923-4dae-b00d-f443c518b010", + "name": "Francis Paulin" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + "index": 2 + }, + { + "id": 4482, + "name": "Room 4", + "session": { + "id": "119374", + "title": "Building great teams ", + "description": "How do you build your dream team and ensure it continues to thrive? In this talk I will share interviewing tips, strategies to create a great culture and practical ways to manage those \"difficult\" conversations.\r\n", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "aff02f28-da1d-4681-817c-6cc42bf9484e", + "name": "Donna Edwards" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + "index": 3 + }, + { + "id": 4483, + "name": "Room 5", + "session": { + "id": "83143", + "title": "Microservices without DDD is risky business!", + "description": "Just about everyone is doing microservices these days, at least that's what they're claiming. Microservices is the new black! But, how well are they really doing? When breaking things up there is a risk of ending up in the same rut as SOA did a decade ago, in effect creating distributed monoliths. So, is it at all possible for anyone to reach the promised land consisting of autonomous, cohesive, and loosely coupled services? \r\n\r\nMy claim is that it is doable, but not without some up-front modelling under the guidance of Domain-driven Design concepts like \"bounded context\", \"core domain\", \"ubiquitous language\" and “aggregates”. Distilling the domain, drilling deep into the core business concepts, and breaking it up into isolated and protected contexts will take you a long way. Add some business capability modelling and service-orientation into the mix, and you are halfway there. Use it as a map to guide you on the journey towards an orderly and robust distributed system, built by adding one MVP at the time in a low-risk agile manner. \r\n\r\nThis talk requires no previous experience with DDD, but it is advantageous if you are familiar with the challenges it attempts to solve, such as modularisation of unruly monoliths or managing a flock of microservices that make herding cats seem simple.", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "40a5fba3-0c7b-487c-9dc9-9d836a8ca999", + "name": "Trond Hjorteland" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + "index": 4 + }, + { + "id": 4484, + "name": "Room 6", + "session": { + "id": "75537", + "title": "Lowering in C#: What's really going on in your code?", + "description": "If you're attending NDC you probably think you know what a foreach loop does - it iterates over a collection, right?\r\n\r\nWell... yes.\r\n\r\nBUT do you know how? Do you know what the C# compiler does when you write a foreach loop? What about a lambda expression? Or the re-entrant magic that is a yield return statement?\r\n\r\nIn this session we'll dive into Roslyn, the C# compiler, and learn about lowering and how it helps the compiler do its job, and what it does to your code. In the process you'll gain the skills to identify some of the common performance pitfalls of .NET, as well as just get a deeper understanding of what the code you write really does.", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "604507ba-fd96-4c48-a29a-67a95760d888", + "name": "David Wengier" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + "index": 5 + }, + { + "id": 4485, + "name": "Room 7", + "session": { + "id": "98908", + "title": "Security – only developers can make it proactive.", + "description": "Whether we use high-level languages like Java, Python, C# or we dive into the world of C/C++, the lists of dependencies of our projects contain more and more external frameworks and libraries. It makes developers’ life easiest and helps us to focus on delivering business value. Do you know what vulnerabilities are known for the version you use? Are you sure you know all the tips and tricks to use the framework in a correct way? Is it good for our software to rely the security of our products on the security of these frameworks and the way we use them?\r\n \r\nJoin me during an exciting LIVE DEMO. Get to know how to weaponize known Spring Boot Data Rest library vulnerability. See how to use Remote Code Execution to actually fully compromise the server hosting an application.\r\n \r\nUsing the vulnerability in an actual attack helps us to understand the underlying mechanism and find if it is applicable to our software. It also allows us to find the detection patterns if it is attempted to be exploited on our infrastructure. And besides all of it – it is fun to hack the servers! It also shows that we can do much better than just blindly upgrading components. There are examples of vulnerabilities, which are fixed not with a single patch, but rather through a series of upgrades leading to more secure solutions, so it is important to stop for a while and think about other attack paths and consequences, that can be faced. The reactive approach of simply keeping up with the latest version leaves us in a position, where we are always exposed to new vulnerabilities that are about to be discovered.", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "4c97bf6e-d874-4a5b-b71a-23c6e07dd53e", + "name": "Beata Szturemska" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + "index": 6 + }, + { + "id": 4486, + "name": "Room 8", + "session": { + "id": "98781", + "title": "War stories from .NET team", + "description": "Expect deep dive into a few interesting investigations we faced on .NET team in the last decade.\r\nWar stories about:\r\n\t• Investigations spanning years,\r\n\t• Dormant bugs coming to life after a decade,\r\n\t• Root-causes leading to surprising places,\r\n\t• How we rooted-cause problems with minimal information available,\r\n\t• Shocking impact of bugs on real world.\r\n\r\nWe will also cover:\r\n\t• Root-causing HW bugs (avoid the one-machine problem),\r\n\t• The value and art of minimal repro,\r\n\t• Innovation and compatibility - the age-old rivals.", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "731fd563-13a2-4fa9-87b6-331dc1293ec1", + "name": "Karel Zikmund" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + "index": 7 + }, + { + "id": 4487, + "name": "Room 9", + "session": { + "id": "98711", + "title": "Celebrate Your Expert: Overcoming Imposter Syndrome", + "description": "If you were asked “In what areas are you an expert,” how would you answer? Would you answer at all? If your friends, colleagues, and peers were asked about your expertise, would the answer change? That word ‘expert’ gets in our way. Our self-modesty blocks self-assessment of our talents. It damages our self-worth. It leads to imposter syndrome. Break out of the cycle. Learn to acknowledge, accept, and own your talents. Let’s celebrate our expert.", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "5698811a-4c31-4537-970d-e427009e0cca", + "name": "Jay Harris" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + "index": 8 + }, + { + "id": 4488, + "name": "Room 10", + "session": { + "id": "98801", + "title": "Workshop: Learning by failing -Root Cause Analysis in Practice - Part 1/2", + "description": "Do you have this feeling certain features will yet again start failing in upcoming release? When you catch a bug, does it seem like a deja vu? Incidents happen. Most of us think of them as materialised risks, but they also can be considered as opportunity. Opportunity to learn and improve. Would you be interested to learn how to draw conclusions from failures, propose corrective and preventive actions, and with them improve your development process and grow quality mindset in your team? This is a workshop for you.\r\n\r\nWe are all agile nowadays, thus we all strive to self improve iteration over iteration. Regular retrospectives help flush out issues with delivery process, compare current iteration with previous, identify things need addressing, areas worth investing in to increase velocity.\r\n\r\nHowever, what happens when we catch a bug? Do we sit together as a team to identify what went wrong as we would normally do seeing a drop in our velocity in current sprint? I don’t think so. Most likely team will fix the bug and move on with feature development. Probably new regression tests will be added to prevent the bug from happening in future.\r\n\r\nRegression doesn’t prevent bugs from happening. It helps with catching recurring symptoms of deeper problems, before they reach our customer and our users. Tests alone don’t address root causes. We’re like doctors prescribing yet another drugs. Not spending enough time on doing patient interview to find problems with lifestyle. Missing nutrients in our team diet.\r\n\r\nYou will learn how to spot and prevent sources of bugs. We’ll walk you through Root Cause Analysis process on a real life incident you can relate to. Help you understand all vital parts of such analysis, and show you how you can conduct similar process next time you catch a bug.\r\n\r\nDuring workshop you will learn:\r\n-techniques helping build context in which incident happened,\r\n-how to build timeline and why it’s important to have one,\r\n-how to identify causal factors and how they differ from root cause,\r\n-techniques helping figure out root cause,\r\n-what are preventive and corrective actions,\r\n-how root cause analysis can not only help prevent bugs from recurring but improve your testing skills.\r\n \r\nKey takeaways:\r\n- what is root cause analysis\r\n- what are causal factors and how they are different from root causes\r\n- techniques helping identify root cause, propose preventive and corrective actions\r\n- how being better in identifying root causes can help you become better tester by focusing your attention on most likely broken parts of your system\r\n\r\n\r\n\r\nParticipant requirements: Nothing. This is an offline workshop.", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "5382406b-bac8-4507-a490-346adbde4163", + "name": "Kasia Balcerzak" + }, + { + "id": "cb564f46-518e-4ab2-b035-58f8f611eb20", + "name": "Bart Szulc" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + "index": 9 + }, + { + "id": 4504, + "name": "Room 11", + "session": { + "id": "98955", + "title": "Workshop: I Don’t Need No Stinkin’ Framework - Mastering Shadow DOM", + "description": "Want to create components that work regardless of the front-end framework you are using?\r\nTired of throwing away your components when you change front-end frameworks?\r\nWish you could just code it once and reuse it on all of your projects?\r\n\r\nMe too! Components are a staple of front-end development as they increase development speed, consistency, and reduce the need for repeat code. To create components often we turn to frameworks such as Angular, React, and Vue but we don't need to. \r\n\r\nUsing nothing more than HTML and Javascript that is readily available to us in all modern browsers we can create components that work without being tied to any one front-end framework. \r\n\r\nYou will walk away with the knowledge you need to go forth and create your own components, understand how to make them look gorgeous, and what if any limitations there are. Also, find out how you can bring back the blink tag!\r\n", + "startsAt": "2019-06-21T13:40:00", + "endsAt": "2019-06-21T14:40:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "3336b62f-c81b-4892-8247-d34043767210", + "name": "Martine Dowden" + } + ], + "categories": [], + "roomId": 4504, + "room": "Room 11" + }, + "index": 10 + } + ] + }, + { + "slotStart": "15:00:00", + "rooms": [ + { + "id": 4479, + "name": "Room 1", + "session": { + "id": "98658", + "title": "The Hitchhiker's Guide to the Cloud (AWS vs GCP vs Azure) and their AI/ML API’s capabilities", + "description": "To companies leveraging the capabilities of public cloud (often Amazon Web Services, Google Cloud or Microsoft Azure) the felling of immersion into a single provider platform is constant in their day to day. With a rapid evolution of services becoming available in each cloud provider, companies tend to focus and keep updated with only one of them while other providers capabilities are simply unknown, ignored or forgotten. \r\nOn the other hand, there are many companies that are not yet using public cloud and are now facing the dilemma of which Public Cloud provider to choose.\r\n\r\nAI and Machine Learning are key areas of investment, growth and differentiation for many companies and that is no exception for the three biggest public cloud players (AWS, GCP and Azure). In this context, pre-trained AI/ML API’s in combination with other Serverless services is one area that has been on the rise and with fast adoption. \r\n\r\nIn this talk we will learn about the three major public cloud providers (AWS, GCP and Azure) by having an overview and gain insights about each other pros and cons. In addition, we are going to explore their AI/ML Cloud API’s that allow us to leverage ready-made capabilities such as: Text to Speech, Image & Video Classification, Translation, Speech Recognition, Sentiment Analysis, etc.\r\n\r\n", + "startsAt": "2019-06-21T15:00:00", + "endsAt": "2019-06-21T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "a2e6985d-7ead-4b43-bdde-bfdea9923300", + "name": "Bruno Amaro Almeida" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + "index": 0 + }, + { + "id": 4480, + "name": "Room 2", + "session": { + "id": "99320", + "title": "Trying to learn C#", + "description": "Learning a new language is often colored by the language you come from. As a programmer coming from C++ and Java, with some functional programming background, how did I navigate trying to get a grasp of C#? Should be fun for C# developers, but also educational: How do we teach a new language to folks that already know how to program?", + "startsAt": "2019-06-21T15:00:00", + "endsAt": "2019-06-21T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "0eaa4bb2-cb2a-4b76-800d-de8b1dfdb50c", + "name": "Patricia Aas" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + "index": 1 + }, + { + "id": 4481, + "name": "Room 3", + "session": { + "id": "99143", + "title": "It's about time", + "description": "Time Zones, Daylight savings, Leap years, Leap seconds... Storing it all, testing it, getting it right for every point in time in every country... \r\nWriting correct timing code can be a nightmare! \r\nWe'll be ranting our way through some common pitfalls, tips and tricks to enable you to reason more effectively about time in your applications.", + "startsAt": "2019-06-21T15:00:00", + "endsAt": "2019-06-21T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "d28ae055-13a5-4d0a-8668-24fd93198cef", + "name": "Christin Gorman" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + "index": 2 + }, + { + "id": 4482, + "name": "Room 4", + "session": { + "id": "98866", + "title": "The Neverending Story: Agile Transformation for DevOps", + "description": "The Digital Media division of National Public Radio (NPR) recently went through a period of growth that required scaling up its small sysadmin team to an Agile DevOps team, but the need for change didn’t stop there. \r\n\r\nAs a scrum master, I had to help the team let go of their old, ad hoc way of working and adjust to the Agile mindset of continually inspecting and adapting their processes. In this talk, I’ll take the audience through all aspects of our Agile transformation: overcoming resistance to change within the team and the department, why we struggled with our initial choice of the Scrum framework, why we wanted to try Kanban, how we moved to Scrumban and most importantly, what we’re going to do next since true Agile transformations never really end.\r\n\r\nYou’ll walk away with some ideas to overcome change fatigue and resistance that can work for both small teams and large organizations, an understanding of how Scrum and Kanban both helped us become a better DevOps team, and why the move to Scrumban was the right choice for our team at that time and might be right for you. You’ll also get an idea of where our DevOps model might go next!", + "startsAt": "2019-06-21T15:00:00", + "endsAt": "2019-06-21T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "2775faa3-3ee4-4c76-ac3e-4ee04c51c1b8", + "name": "Sarah Ziegenfuss" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + "index": 3 + }, + { + "id": 4483, + "name": "Room 5", + "session": { + "id": "99471", + "title": "CompSci and My Day Job", + "description": "4 years ago I had a vague idea about Big-O notation and absolutely no clue about combinatorial problems. I knew what a SHA256 hash was (sort of) but I didn't know how it was created, nor that it didn't completely protect some of my data. I knew these things were important, but I never understood how they could apply to the types of applications I was building at the time. All of this changed as I put together the first two volumes of The Imposter's Handbook.\r\n\r\nI get to build a lot of fun things in my new position at Microsoft and I've been surprised at how often I use the things I've learned. Avoiding an obvious performance pitfall with Redis, for instance, because I understood the Big-O implications of the data structure I chose. Going back to ensure that a salt was added to a hash which stored sensitive data for an old client and, most importantly, discouraging a friend from trying to solve a problem that was very clearly NP-Complete.\r\n\r\nIn this talk I'll show you some of the fun things I've learned (like mod(%) and remainder being different things) and how I've applied them to the applications I create for my day job. You might know some of these concepts, or maybe you don't - either way: hopefully you'll leave with a few more tools under your belt to help you do your job better.", + "startsAt": "2019-06-21T15:00:00", + "endsAt": "2019-06-21T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "b68738ac-e6ff-4efe-a4e8-16a45b78c2bd", + "name": "Rob Conery" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + "index": 4 + }, + { + "id": 4484, + "name": "Room 6", + "session": { + "id": "99269", + "title": "DevOps for Machine Learning", + "description": "Machine learning is easier to use than ever before, but how do we coordinate the teams involved? Software engineering has been maturing for decades, but introducing an unfamiliar parallel workstream like data science brings new challenges. Thankfully, we can draw upon the cross-team collaborative efforts of DevOps to bring data science and software engineering into sync.\r\n\r\nBuilding effective predictive models involves data acquisition and preparation, then resource-intensive experimentation and training. Data scientists don't tend to focus on testing and deploying models to production systems in sync with software releases. Working with software engineers and IT operations in a repeatable, automated, coherent pipeline is still an afterthought in many organisations, and data science teams are left out of the loop.\r\n\r\nLet's look at an end-to-end software and data science delivery pipeline that is repeatable and robust. We'll focus on model source control, repeatable data preparation, model training and continuous retraining, code validation and testing, model storage and versioning, and production deployment. Data scientists and software engineers can work together effectively to produce smart software. Let's learn how!", + "startsAt": "2019-06-21T15:00:00", + "endsAt": "2019-06-21T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "42c43411-422b-455a-8772-3e638e4deb35", + "name": "Damian Brady" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + "index": 5 + }, + { + "id": 4485, + "name": "Room 7", + "session": { + "id": "75431", + "title": "Security Vulnerabilities Decomposition: Another way to look at Vulnerabilities", + "description": "In most companies security is driven by compliance regulations. The policies are designed to contain the CWEs each company is interested to comply with. The result of this approach is a high number of insecure applications are still produced and injection is still King. Is there another way to secure the software in a more developer friendly manner? \r\n\r\nThis presentation will look at security vulnerabilities from a different angle. We will decompose the vulnerabilities into the security controls that prevent them and developers are familiar with. We will flip the security from focusing on vulnerabilities (measured at the end) to focus on the security controls which can be used by developers from beginning in software development cycle. \r\n\r\nRecommended to all developers looking to integrate security in their software applications.\r\n", + "startsAt": "2019-06-21T15:00:00", + "endsAt": "2019-06-21T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "b30243a2-2cc9-403e-a146-5496c9d199dc", + "name": "Katy Anton" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + "index": 6 + }, + { + "id": 4486, + "name": "Room 8", + "session": { + "id": "98812", + "title": "You get an actor, you get an actor, everybody gets an actor - Building personalization with Orleans", + "description": "Everybody is different and with actor modelling we can treat each user in isolation without worrying about consistency, side effects or any other users. \r\n\r\nIn this talk we'll look at why we chose Orleans, an open source Virtual Actor platform for distributed high-scale computing applications, when building a new personalization platform for favorites and progress at tv.nrk.no and radio.nrk.no. We'll dive into how actor modelling is different and discuss some of the design decisions we made and look at how we implemented this in Orleans with f#.\r\n\r\nSoftware without a build pipeline and deployment strategy is not an option, and Orleans is no different. It takes care and planning, so we'll round off with a look at how we build with docker, deploy to Azure Kubernets Service and monitor with Application Insights to sleep well.", + "startsAt": "2019-06-21T15:00:00", + "endsAt": "2019-06-21T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "ff7ad940-8ce5-4b49-86bc-6e47535db8f6", + "name": "Harald Schult Ulriksen" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + "index": 7 + }, + { + "id": 4487, + "name": "Room 9", + "session": { + "id": "99879", + "title": "Lightning Talks (People)", + "description": "Lightning talks (approx 10-15 minutes each)\r\n\r\nTalk 1: How to tame your team monsters! - Hanne Lian\r\n\r\nIn our everyday lives as designers, we encounter several types of monsters (you know; colleagues and clients). What can we do to tame these monsters into submission so that they will produce our wonderful designs? We will introduce you to the most common monsters in the workplace and give you some of our tools to handle them.\r\n\r\n-----------------------------------------------------------------------\r\n\r\nTalk 2: I Love Learning From People! - Bryan Hogan\r\n\r\nI've been podcasting for almost five years and I love making every single episode. I talk to people from around the world about what they love doing, and share this with everyone. \r\n\r\nMost people you meet love to talk about topics that interest them and with the right questions they will tell you everything they know.\r\n\r\nIn just ten short minutes I'm going to share some of what I've learned about how you can learn from others - how to ask questions, how to listen, how to encourage, when to disagree, when to interrupt and when to stay quiet.\r\n\r\n-----------------------------------------------------------------------\r\n\r\nTalk 3: \"OMG! A Girl?!\" What to do when a woman joins your team - Meg Gotshall\r\n\r\nDon’t panic! Often when I join a team, my new colleagues second guess each and every behavior. Inevitably, this leads to some awkward situations (and in the wake of #MeToo, even fear)!\r\n\r\nAlthough women still make up a rather small percentage of the tech workforce, we’re not as uncommon as narwhals or unicorns, so I’d like to take a few minutes to talk candidly about how we can make this transition smoother and simpler for both sides. Applying a programmer’s pragmatism to social interactions, we can debug our working environment and hopefully make it run more smoothly.\r\n\r\n-----------------------------------------------------------------------\r\n\r\nTalk 4: How to deal with your demons - Lubaba Farin Tanisha\r\n\r\nShould you care to know more about your biases? Does it even remotely related to software development? Is being aware of them make you a better software engineer? The answers to all these questions are: Oh yes! No matter what methodology or process you follow, it is possible to fall through the cracks for numerous amount of facts that you could have avoided if you knew about them before. If you knew that you are actually carrying many of them. So join my talk, I will walk you through a path that would perhaps make you discover a new you, with a brand new mindset to deal with your tasks, and of course to deal with your demons.\r\n\r\n-----------------------------------------------------------------------\r\n\r\nTalk 5: Emojis – the fun and weird parts! - Jøran Vagnby Lillesand\r\n\r\nCome get a time out from useful learning and get a brief introduction to the surprisingly interesting world of emojis!\r\n\r\nEmojis – to most of us they're just a weird distraction from proper language. But they're actually a rather cool piece of technology (!) with a meaningful impact on society. I'll teach you 3 things you didn't know about emojis, but you'll be glad you do!\r\n\r\n-----------------------------------------------------------------------", + "startsAt": "2019-06-21T15:00:00", + "endsAt": "2019-06-21T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "e88a72e9-22aa-48d8-8395-704e70a791de", + "name": "Hanne Lian" + }, + { + "id": "de972e57-7765-4c38-9dcd-5981587c1433", + "name": "Bryan Hogan" + }, + { + "id": "0beddeb8-a1af-4cf1-822a-c51124043b43", + "name": "Meg Gotshall" + }, + { + "id": "5ee74d34-d9e2-4dea-ab4f-a32a5a647014", + "name": "Lubaba Farin Tanisha" + }, + { + "id": "7577e0ae-3f98-4649-a043-7dc915581546", + "name": "Jøran Vagnby Lillesand" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + "index": 8 + }, + { + "id": 4488, + "name": "Room 10", + "session": { + "id": "128723", + "title": "Workshop: Learning by failing - Root Cause Analysis in Practice - Part 2/2", + "description": "Do you have this feeling certain features will yet again start failing in upcoming release? When you catch a bug, does it seem like a deja vu? Incidents happen. Most of us think of them as materialised risks, but they also can be considered as opportunity. Opportunity to learn and improve. Would you be interested to learn how to draw conclusions from failures, propose corrective and preventive actions, and with them improve your development process and grow quality mindset in your team? This is a workshop for you.\r\n\r\nWe are all agile nowadays, thus we all strive to self improve iteration over iteration. Regular retrospectives help flush out issues with delivery process, compare current iteration with previous, identify things need addressing, areas worth investing in to increase velocity.\r\n\r\nHowever, what happens when we catch a bug? Do we sit together as a team to identify what went wrong as we would normally do seeing a drop in our velocity in current sprint? I don’t think so. Most likely team will fix the bug and move on with feature development. Probably new regression tests will be added to prevent the bug from happening in future.\r\n\r\nRegression doesn’t prevent bugs from happening. It helps with catching recurring symptoms of deeper problems, before they reach our customer and our users. Tests alone don’t address root causes. We’re like doctors prescribing yet another drugs. Not spending enough time on doing patient interview to find problems with lifestyle. Missing nutrients in our team diet.\r\n\r\nYou will learn how to spot and prevent sources of bugs. We’ll walk you through Root Cause Analysis process on a real life incident you can relate to. Help you understand all vital parts of such analysis, and show you how you can conduct similar process next time you catch a bug.\r\n\r\nDuring workshop you will learn:\r\n-techniques helping build context in which incident happened,\r\n-how to build timeline and why it’s important to have one,\r\n-how to identify causal factors and how they differ from root cause,\r\n-techniques helping figure out root cause,\r\n-what are preventive and corrective actions,\r\n-how root cause analysis can not only help prevent bugs from recurring but improve your testing skills.\r\n\r\nKey takeaways:\r\n- what is root cause analysis\r\n- what are causal factors and how they are different from root causes\r\n- techniques helping identify root cause, propose preventive and corrective actions\r\n- how being better in identifying root causes can help you become better tester by focusing your attention on most likely broken parts of your system\r\n\r\nParticipant requirements: Nothing. This is an offline workshop.", + "startsAt": "2019-06-21T15:00:00", + "endsAt": "2019-06-21T16:00:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "5382406b-bac8-4507-a490-346adbde4163", + "name": "Kasia Balcerzak" + }, + { + "id": "cb564f46-518e-4ab2-b035-58f8f611eb20", + "name": "Bart Szulc" + } + ], + "categories": [], + "roomId": 4488, + "room": "Room 10" + }, + "index": 9 + } + ] + }, + { + "slotStart": "16:20:00", + "rooms": [ + { + "id": 4479, + "name": "Room 1", + "session": { + "id": "99155", + "title": "Everything is Cyber-broken 2", + "description": "TBA - submitting this now so you have it in the agenda, it'll be an all new talk in the theme of the first cyber-broken talk", + "startsAt": "2019-06-21T16:20:00", + "endsAt": "2019-06-21T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "735a4b60-42e8-4452-9480-68197372c206", + "name": "Troy Hunt" + } + ], + "categories": [], + "roomId": 4479, + "room": "Room 1" + }, + "index": 0 + }, + { + "id": 4480, + "name": "Room 2", + "session": { + "id": "86521", + "title": "Rediscovering fire - on designing portable, multi-language libraries", + "description": "The session will cover the design choices and lessons learned developing the multi-language free library segyio, or more conceptually, designing libraries for libraries.\r\n\r\nBriefly, it will discuss:\r\n- Stable API, ABI, and how to design them for the future\r\n- How to design C-interface libraries that allows for good foreign-language libraries (in our case python)\r\n- Library design philosophy and the beauty of primitive functions\r\n- How to design for composition and caller flexibility\r\n- Plumbing and porcelain\r\n\r\nThe session should appeal both to library developers for embedded systems, and consumers of higher-level libraries in desktop and scientific applications, as the topic covered is the bridge between primitive and sophisticated systems, and making it beautiful.", + "startsAt": "2019-06-21T16:20:00", + "endsAt": "2019-06-21T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "142b682d-b548-423c-8e51-e36ee08db70f", + "name": "Jørgen Kvalsvik" + } + ], + "categories": [], + "roomId": 4480, + "room": "Room 2" + }, + "index": 1 + }, + { + "id": 4481, + "name": "Room 3", + "session": { + "id": "99253", + "title": "Who's Who? Federating Identity with Azure B2C", + "description": "Often, users of your system will already know who they are, or at least think they do. Making sure you know who they are and what they can do is pretty important too.\r\n\r\nIn this session Microsoft Engineer Andrew Coates will present techniques for allowing users to log into your system with credentials from another system. Using Azure B2C allows you to offload authentication to other identity providers while keeping authorization tasks local to your system.\r\n\r\nOffload the hassles of lost passwords, expiring accounts and more, leaving you time to build and maintain the things that are important to your system.\r\n\r\nAndrew will demonstrate the setup and configuration of this powerful identity federation system allowing integration of any combination of social identities such as Facebook or twitter, as well as organisational accounts like Active Directory and others. He'll also discuss the extension points allowing complete control of the identity system including rules-based identity flows and calling out to custom REST services as part of the claims processing flow,\r\n\r\nIf your system needs to include users from outside your organisation, this is a must-see session.\r\n", + "startsAt": "2019-06-21T16:20:00", + "endsAt": "2019-06-21T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "2809c750-dc83-4e1c-8f06-38ee96b818b6", + "name": "Andrew Coates" + } + ], + "categories": [], + "roomId": 4481, + "room": "Room 3" + }, + "index": 2 + }, + { + "id": 4482, + "name": "Room 4", + "session": { + "id": "127295", + "title": "Avoiding the Agile Alignment Trap with DevOps", + "description": "MIT Sloan Management Review published an article in 2007 titled Avoiding the Alignment Trap in IT. What the researchers discovered is that organizations don’t become high performing by starting initiatives focused on aligning business and technology. Rather, only by improving delivery performance first was it possible to achieve IT Enabled Growth.\r\n\r\nThis presentation shows why Agile transformations won't save your software delivery challenges, what supporting evidence has accumulated in the last decade, and how to avoid the common traps that occur in digital transformations.", + "startsAt": "2019-06-21T16:20:00", + "endsAt": "2019-06-21T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "8cc2a599-d122-4ef2-8433-1132aa0c4a93", + "name": "Mike Long" + } + ], + "categories": [], + "roomId": 4482, + "room": "Room 4" + }, + "index": 3 + }, + { + "id": 4483, + "name": "Room 5", + "session": { + "id": "99182", + "title": "Advanced Azure App Services", + "description": "You'll find many introductions showing you how to use Azure App Services, so this talk will give you the inside scoop on the real world tips, tricks, and troubles you'll see when moving enterprise projects into App Services. We will discuss best practices for security and deployment, as well as prescriptions to follow to achieve the best performance, scalability, and resiliency.", + "startsAt": "2019-06-21T16:20:00", + "endsAt": "2019-06-21T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "c9c8096e-47a1-41e5-a00c-d49b51d01c4e", + "name": "K. Scott Allen" + } + ], + "categories": [], + "roomId": 4483, + "room": "Room 5" + }, + "index": 4 + }, + { + "id": 4484, + "name": "Room 6", + "session": { + "id": "86610", + "title": "Solving Tricky Coordination Problems in Stateless .NET Services", + "description": "Developing modern, service-oriented architectures requires that our services become stateless to enable horizontal scalability. ASP.NET helps in doing so with IDistributedCache, but caching is only one of many new coordination problems.\r\n\r\nIn this session I will present how to approach some coordination problems, with a deeper focus on using Redis Pub/Sub to prevent concurrent client requests from triggering the same online-but-expensive computation over and over, by creating a distributed lock that does the job once and instantly notifies all other pending requests when the computation is completed.\r\nThis type of computation-locking is useful for preventing “stampedes” when generating reports, serving AI models, running serverless functions, and more. \r\n\r\nDuring the presentation I will also demo a sample ASP.NET Core project that implements said mechanism by making full use of asynchronous code and System.Collections.Concurrent to maximise performance.\r\n", + "startsAt": "2019-06-21T16:20:00", + "endsAt": "2019-06-21T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "fc185a93-d887-4005-b6ea-4099530a862f", + "name": "Loris Cro" + } + ], + "categories": [], + "roomId": 4484, + "room": "Room 6" + }, + "index": 5 + }, + { + "id": 4485, + "name": "Room 7", + "session": { + "id": "99512", + "title": "Getting started with Azure DevOps", + "description": "DevOps is about people, process, and products. Getting it all right requires effort, but the benefits to your organization and customers can be huge. Microsoft has a fantastic set of products that can help you get the most out of the cloud with any language on any platform. In this demo-heavy session, Donovan Brown shows you how to transform your team.", + "startsAt": "2019-06-21T16:20:00", + "endsAt": "2019-06-21T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "266bf958-048e-4c55-b01f-398b90dfe5e9", + "name": "Donovan Brown" + } + ], + "categories": [], + "roomId": 4485, + "room": "Room 7" + }, + "index": 6 + }, + { + "id": 4486, + "name": "Room 8", + "session": { + "id": "99371", + "title": "Futurology for Developers - the Next 30 Years in Tech", + "description": "2019 is the 30th anniversary of my first job in tech. On my first day I was given a Wyse 60 terminal attached via RS232 cables to a Tandon 286, and told to learn C from a dead tree so I could write text applications for an 80x24 character screen. Fast-forward to now: my phone is about a million times more powerful than that Tandon; screens are 3840x2160 pixels; every computer in the world is attached to every other thing with no cables; and we code using... still basically C.\r\n\r\nHaving lived through all these changes in realtime, and as an incurable neophile, I think I can make an educated guess as to what the next 30 years are going to be like, and what we're all going to be doing by 2049. If anything, I'm going to underestimate it, but hopefully you'll be inspired, invigorated and maybe even informed about the future of your career in tech.", + "startsAt": "2019-06-21T16:20:00", + "endsAt": "2019-06-21T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "70590ad0-b1b3-40b8-b05d-b58722ef9d9d", + "name": "Mark Rendle" + } + ], + "categories": [], + "roomId": 4486, + "room": "Room 8" + }, + "index": 7 + }, + { + "id": 4487, + "name": "Room 9", + "session": { + "id": "121584", + "title": "Descaling Agile", + "description": "After the agile community solved how to do programming, testing, release and product management, the hot topic for our industry today seems to be scaling. In an ironic twist for a movement started with ‘people over process’, big consultancies today sell scaling models based on everything from tribes to witchcraft, offering to make agile disciplined and safe.\r\n\r\nGojko will help you cut through all the mess and separate out signal from noise.", + "startsAt": "2019-06-21T16:20:00", + "endsAt": "2019-06-21T17:20:00", + "isServiceSession": false, + "isPlenumSession": false, + "speakers": [ + { + "id": "c4a6643a-3233-437c-b1ae-c7024e09fc49", + "name": "Gojko Adzic" + } + ], + "categories": [], + "roomId": 4487, + "room": "Room 9" + }, + "index": 8 + } + ] + } + ] + } +] \ No newline at end of file From 452075d9c452fb5fb5669bbf4e7b9909111541d5 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sun, 16 Jun 2019 20:16:29 -0700 Subject: [PATCH 34/56] Made some tweaks to session2 --- docs/2. Build out BackEnd and Refactor.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/2. Build out BackEnd and Refactor.md b/docs/2. Build out BackEnd and Refactor.md index ca1b6d91..ffc7d9ba 100644 --- a/docs/2. Build out BackEnd and Refactor.md +++ b/docs/2. Build out BackEnd and Refactor.md @@ -193,6 +193,8 @@ We're also going to take this opportunity to rename the `Models` directory in th public class Session : ConferenceDTO.Session { public virtual ICollection SessionSpeakers { get; set; } + + public virtual ICollection SessionAttendees { get; set; } public Track Track { get; set; } } @@ -311,7 +313,6 @@ Okay, now we need to update our `ApplicationDbContext` so Entity Framework knows { public class SpeakerResponse : Speaker { - // TODO: Set order of JSON properties so this shows up last not first public ICollection Sessions { get; set; } = new List(); } } @@ -466,8 +467,8 @@ Okay, now we need to update our `ApplicationDbContext` so Entity Framework knows 1. Copy the `DataLoader.cs` class from [here](/src/BackEnd/Data/DataLoader.cs) into the `Data` directory of the `BackEnd` project. 1. Copy the `SessionizeLoader.cs` and `DevIntersectionLoader.cs` classes from [here](/src/BackEnd/Data/) into the current project's `/src/BackEnd/Data/` directory. > Note: We have data loaders from the two conference series where this workshop has been presented most; you can update this to plug in your own conference file format. -1. Turn enums as strings by changing `AddSwaggerGen` in `Startup.cs` to the following: - ``` +1. To improve the UI for upload, turn on the option to display enums as strings by changing `AddSwaggerGen` in `Startup.cs` to the following: + ```c# services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new OpenApiInfo { Title = "Conference Planner API", Version = "v1" }); @@ -475,6 +476,6 @@ Okay, now we need to update our `ApplicationDbContext` so Entity Framework knows }); ``` 1. Run the application to see the updated data via Swagger UI. -1. Use the Swagger UI to upload [NDC_London_2019.json](/src/BackEnd/Data/Import/NDC_London_2019.json) to the `/api/Conferences/upload` API. +1. Use the Swagger UI to upload [NDC_Oslo_2019.json](/src/BackEnd/Data/Import/NDC_Oslo_2019.json) to the `/api/Sessions/upload` API. **Next**: [Session #3 - Front-end](3.%20Add%20front-end%2C%20render%20agenda%2C%20set%20up%20front-end%20models.md) | **Previous**: [Session #1 - Setup, basic EF model](/docs/1.%20Create%20BackEnd%20API%20project.md) From a8f16f22af6b75898cea7bfbb1e5709c7e60f4c8 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sun, 16 Jun 2019 20:27:59 -0700 Subject: [PATCH 35/56] Use the extension methods to get search results --- ... render agenda, set up front-end models.md | 38 +------------------ 1 file changed, 2 insertions(+), 36 deletions(-) diff --git a/docs/3. Add front-end, render agenda, set up front-end models.md b/docs/3. Add front-end, render agenda, set up front-end models.md index 630c6530..7e14c4a4 100644 --- a/docs/3. Add front-end, render agenda, set up front-end models.md +++ b/docs/3. Add front-end, render agenda, set up front-end models.md @@ -547,46 +547,12 @@ In this session, we'll add the front end web site, with a public (anonymous) hom var results = sessionResults.Select(s => new SearchResult { Type = SearchResultType.Session, - Session = new SessionResponse - { - Id = s.Id, - Title = s.Title, - Abstract = s.Abstract, - StartTime = s.StartTime, - EndTime = s.EndTime, - TrackId = s.TrackId, - Track = new ConferenceDTO.Track - { - Id = s?.TrackId ?? 0, - Name = s.Track?.Name - }, - Speakers = s?.SessionSpeakers - .Select(ss => new ConferenceDTO.Speaker - { - Id = ss.SpeakerId, - Name = ss.Speaker.Name - }) - .ToList() - } + Session = s.MapSessionResponse() }) .Concat(speakerResults.Select(s => new SearchResult { Type = SearchResultType.Speaker, - Speaker = new SpeakerResponse - { - Id = s.Id, - Name = s.Name, - Bio = s.Bio, - WebSite = s.WebSite, - Sessions = s.SessionSpeakers? - .Select(ss => - new ConferenceDTO.Session - { - Id = ss.SessionId, - Title = ss.Session.Title - }) - .ToList() - } + Speaker = s.MapSpeakerResponse() })); return results.ToList(); From a21c2249a1df9c9659aa5ebeed4606dd14cc2694 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sun, 16 Jun 2019 20:33:28 -0700 Subject: [PATCH 36/56] Small nits --- ...ront-end, render agenda, set up front-end models.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/3. Add front-end, render agenda, set up front-end models.md b/docs/3. Add front-end, render agenda, set up front-end models.md index 7e14c4a4..1dd2caf3 100644 --- a/docs/3. Add front-end, render agenda, set up front-end models.md +++ b/docs/3. Add front-end, render agenda, set up front-end models.md @@ -515,18 +515,18 @@ In this session, we'll add the front end web site, with a public (anonymous) hom [ApiController] public class SearchController : ControllerBase { - private readonly ApplicationDbContext _db; + private readonly ApplicationDbContext _context; - public SearchController(ApplicationDbContext db) + public SearchController(ApplicationDbContext context) { - _db = db; + _context = context; } [HttpPost] public async Task>> Search(SearchTerm term) { var query = term.Query; - var sessionResults = await _db.Sessions.Include(s => s.Track) + var sessionResults = await _context.Sessions.Include(s => s.Track) .Include(s => s.SessionSpeakers) .ThenInclude(ss => ss.Speaker) .Where(s => @@ -535,7 +535,7 @@ In this session, we'll add the front end web site, with a public (anonymous) hom ) .ToListAsync(); - var speakerResults = await _db.Speakers.Include(s => s.SessionSpeakers) + var speakerResults = await _context.Speakers.Include(s => s.SessionSpeakers) .ThenInclude(ss => ss.Session) .Where(s => s.Name.Contains(query) || From e28fdcefe2ecce0f40a99bc3b0de209e40471742 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sun, 16 Jun 2019 20:43:11 -0700 Subject: [PATCH 37/56] Add EF error and work around --- docs/2. Build out BackEnd and Refactor.md | 60 +++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/docs/2. Build out BackEnd and Refactor.md b/docs/2. Build out BackEnd and Refactor.md index ffc7d9ba..6e7d7049 100644 --- a/docs/2. Build out BackEnd and Refactor.md +++ b/docs/2. Build out BackEnd and Refactor.md @@ -478,4 +478,64 @@ Okay, now we need to update our `ApplicationDbContext` so Entity Framework knows 1. Run the application to see the updated data via Swagger UI. 1. Use the Swagger UI to upload [NDC_Oslo_2019.json](/src/BackEnd/Data/Import/NDC_Oslo_2019.json) to the `/api/Sessions/upload` API. +## :warning: Using EF Core preview6 preview bits! +There's a known issue where Entity Framework Core preview6 cannot properly handle the resuling model we have just built. Trying to run will result in an error looking something like this: + +``` +System.InvalidOperationException: Operation is not valid due to the current state of the object. + at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions.SubSelectExpression.Verify(SelectExpression selectExpression) + at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions.SubSelectExpression..ctor(SelectExpression subquery) + at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalSqlTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) + at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor) + at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) + at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalSqlTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) + at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor) + at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) + at Microsoft.EntityFrameworkCore.Query.NavigationExpansion.IncludeExpression.VisitChildren(ExpressionVisitor visitor) + at System.Linq.Expressions.ExpressionVisitor.VisitExtension(Expression node) + at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalSqlTranslatingExpressionVisitor.VisitExtension(Expression extensionExpression) + at System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor) + at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) + at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalSqlTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) + at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor) + at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) + at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalSqlTranslatingExpressionVisitor.Translate(Expression expression) + at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression) + at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalProjectionBindingExpressionVisitor.Translate(SelectExpression selectExpression, Expression expression) + at Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateSelect(ShapedQueryExpression source, LambdaExpression selector) + at Microsoft.EntityFrameworkCore.Query.Pipeline.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression) + at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor) + at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) + at Microsoft.EntityFrameworkCore.Query.Pipeline.QueryCompilationContext2.CreateQueryExecutor[TResult](Expression query) + at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery2[TResult](Expression query, Boolean async) + at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async) + at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass12_0`1.b__0() + at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func`1 compiler) + at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler) + at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken) + at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken) + at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.System.Collections.Generic.IAsyncEnumerable.GetEnumerator() + at System.Linq.AsyncEnumerable.Aggregate_[TSource,TAccumulate,TResult](IAsyncEnumerable`1 source, TAccumulate seed, Func`3 accumulator, Func`2 resultSelector, CancellationToken cancellationToken) in D:\a\1\s\Ix.NET\Source\System.Interactive.Async\Aggregate.cs:line 118 + at BackEnd.Controllers.SessionsController.Get() in C:\Users\david\source\repos\ConferencePlannerv3\BackEnd\Controllers\SessionsController.cs:line 27 + at lambda_method(Closure , Object ) + at Microsoft.Extensions.Internal.ObjectMethodExecutorAwaitable.Awaiter.GetResult() + at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) + at System.Threading.Tasks.ValueTask`1.get_Result() + at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask) + at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) + at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) + at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) + at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync() +--- End of stack trace from previous location where exception was thrown --- + at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) + at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|17_1(ResourceInvoker invoker) + at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) + at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext) + at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider) + at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) + at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context) +``` + +To work around this, downgrade `Microsoft.EntityFrameworkCore.SqlServer`, `Microsoft.EntityFrameworkCore.Sqlite` and `Microsoft.EntityFrameworkCore.Tools` to version `2.2.4`. + **Next**: [Session #3 - Front-end](3.%20Add%20front-end%2C%20render%20agenda%2C%20set%20up%20front-end%20models.md) | **Previous**: [Session #1 - Setup, basic EF model](/docs/1.%20Create%20BackEnd%20API%20project.md) From 36cd17e40914b4854cfd14db8cf19ccb40bfab80 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sun, 16 Jun 2019 20:59:15 -0700 Subject: [PATCH 38/56] Small nits in global tool --- docs/1. Create BackEnd API project.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/1. Create BackEnd API project.md b/docs/1. Create BackEnd API project.md index 99113fb7..25d1c802 100644 --- a/docs/1. Create BackEnd API project.md +++ b/docs/1. Create BackEnd API project.md @@ -157,7 +157,7 @@ First, open the `Controllers` folder and take a quick look at the `ValuesControl 1. Install the `aspnet-codegenerator` global tool by running the following command: ```console - dotnet tool install --global dotnet-aspnet-codegenerator + dotnet tool install -g dotnet-aspnet-codegenerator --version 3.0.0-preview5-19264-04 ``` > Note: You will need to close and reopen the console window to be able to use this tool. From c8074790ad4dc308648cbae1f7754b2f4407fec1 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sun, 16 Jun 2019 21:03:10 -0700 Subject: [PATCH 39/56] Use preview6 image --- docs/images/vs2019-new-web-api.png | Bin 82916 -> 82915 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/images/vs2019-new-web-api.png b/docs/images/vs2019-new-web-api.png index 1e88d0673fc91b68ccdcb66534c573a808047087..2ddd0c69caed766bb1fa4397c2a553d352dae3e8 100644 GIT binary patch delta 38308 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 D_LRKj delta 38504 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 From 339b020daed43a33d516d7c8b3b9bf4144a8a97c Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sun, 16 Jun 2019 21:32:03 -0700 Subject: [PATCH 40/56] Added the first snapshot --- docs/1. Create BackEnd API project.md | 2 +- .../ConferencePlanner/BackEnd/BackEnd.csproj | 21 ++++++---- .../BackEnd/Controllers/SpeakersController.cs | 10 ++--- ....cs => 20190614215301_Initial.Designer.cs} | 8 ++-- ...9_Initial.cs => 20190614215301_Initial.cs} | 4 +- .../ApplicationDbContextModelSnapshot.cs | 6 +-- .../BackEnd/Models/Speaker.cs | 6 +-- .../ConferencePlanner/BackEnd/Program.cs | 16 ++++---- .../BackEnd/Properties/launchSettings.json | 30 --------------- .../ConferencePlanner/BackEnd/Startup.cs | 38 ++++++++++--------- .../BackEnd/appsettings.json | 14 ++++--- .../ConferencePlanner/ConferencePlanner.sln | 16 ++++---- 12 files changed, 74 insertions(+), 97 deletions(-) rename save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Migrations/{20190128054119_Initial.Designer.cs => 20190614215301_Initial.Designer.cs} (87%) rename save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Migrations/{20190128054119_Initial.cs => 20190614215301_Initial.cs} (89%) delete mode 100644 save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Properties/launchSettings.json diff --git a/docs/1. Create BackEnd API project.md b/docs/1. Create BackEnd API project.md index 25d1c802..8c472bde 100644 --- a/docs/1. Create BackEnd API project.md +++ b/docs/1. Create BackEnd API project.md @@ -7,7 +7,7 @@ ## Creating a new project using the Command Line -1. Create folder ConferencePlanner and call `dotnet new sln` at the cmd line to create a solution +1. Create folder `ConferencePlanner` and call `dotnet new sln` at the cmd line to create a solution 1. Create a project using `dotnet new webapi -n BackEnd` at the cmd line inside the folder BackEnd 1. Add the project to the solution using `dotnet sln add BackEnd` diff --git a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/BackEnd.csproj b/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/BackEnd.csproj index 73f1ba9f..7f51f969 100644 --- a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/BackEnd.csproj +++ b/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/BackEnd.csproj @@ -1,16 +1,21 @@ - + - netcoreapp2.2 - InProcess + netcoreapp3.0 - - - - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Controllers/SpeakersController.cs b/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Controllers/SpeakersController.cs index b0ad5f40..6419354d 100644 --- a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Controllers/SpeakersController.cs +++ b/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Controllers/SpeakersController.cs @@ -1,8 +1,6 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using BackEnd.Models; @@ -45,7 +43,7 @@ public async Task> GetSpeaker(int id) [HttpPut("{id}")] public async Task PutSpeaker(int id, Speaker speaker) { - if (id != speaker.ID) + if (id != speaker.Id) { return BadRequest(); } @@ -78,7 +76,7 @@ public async Task> PostSpeaker(Speaker speaker) _context.Speakers.Add(speaker); await _context.SaveChangesAsync(); - return CreatedAtAction("GetSpeaker", new { id = speaker.ID }, speaker); + return CreatedAtAction("GetSpeaker", new { id = speaker.Id }, speaker); } // DELETE: api/Speakers/5 @@ -99,7 +97,7 @@ public async Task> DeleteSpeaker(int id) private bool SpeakerExists(int id) { - return _context.Speakers.Any(e => e.ID == id); + return _context.Speakers.Any(e => e.Id == id); } } } diff --git a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Migrations/20190128054119_Initial.Designer.cs b/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Migrations/20190614215301_Initial.Designer.cs similarity index 87% rename from save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Migrations/20190128054119_Initial.Designer.cs rename to save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Migrations/20190614215301_Initial.Designer.cs index 7d22ef86..830bd0e7 100644 --- a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Migrations/20190128054119_Initial.Designer.cs +++ b/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Migrations/20190614215301_Initial.Designer.cs @@ -9,20 +9,20 @@ namespace BackEnd.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20190128054119_Initial")] + [Migration("20190614215301_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.1-servicing-10028") + .HasAnnotation("ProductVersion", "3.0.0-preview6.19304.10") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("BackEnd.Models.Speaker", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); @@ -36,7 +36,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("WebSite") .HasMaxLength(1000); - b.HasKey("ID"); + b.HasKey("Id"); b.ToTable("Speakers"); }); diff --git a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Migrations/20190128054119_Initial.cs b/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Migrations/20190614215301_Initial.cs similarity index 89% rename from save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Migrations/20190128054119_Initial.cs rename to save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Migrations/20190614215301_Initial.cs index 9eb54949..b56fda42 100644 --- a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Migrations/20190128054119_Initial.cs +++ b/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Migrations/20190614215301_Initial.cs @@ -11,7 +11,7 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "Speakers", columns: table => new { - ID = table.Column(nullable: false) + Id = table.Column(nullable: false) .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), Name = table.Column(maxLength: 200, nullable: false), Bio = table.Column(maxLength: 4000, nullable: true), @@ -19,7 +19,7 @@ protected override void Up(MigrationBuilder migrationBuilder) }, constraints: table => { - table.PrimaryKey("PK_Speakers", x => x.ID); + table.PrimaryKey("PK_Speakers", x => x.Id); }); } diff --git a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Migrations/ApplicationDbContextModelSnapshot.cs b/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Migrations/ApplicationDbContextModelSnapshot.cs index d20032b9..964f7d5d 100644 --- a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Migrations/ApplicationDbContextModelSnapshot.cs @@ -14,13 +14,13 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.1-servicing-10028") + .HasAnnotation("ProductVersion", "3.0.0-preview6.19304.10") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("BackEnd.Models.Speaker", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); @@ -34,7 +34,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("WebSite") .HasMaxLength(1000); - b.HasKey("ID"); + b.HasKey("Id"); b.ToTable("Speakers"); }); diff --git a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Models/Speaker.cs b/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Models/Speaker.cs index ff745b6f..23f3760f 100644 --- a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Models/Speaker.cs +++ b/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Models/Speaker.cs @@ -3,14 +3,12 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.EntityFrameworkCore.Design; namespace BackEnd.Models { public class Speaker { - public int ID { get; set; } + public int Id { get; set; } [Required] [StringLength(200)] @@ -22,4 +20,4 @@ public class Speaker [StringLength(1000)] public virtual string WebSite { get; set; } } -} \ No newline at end of file +} diff --git a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Program.cs b/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Program.cs index c38605c3..e427203e 100644 --- a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Program.cs +++ b/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Program.cs @@ -1,11 +1,10 @@ -using System; +using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace BackEnd @@ -14,11 +13,14 @@ public class Program { public static void Main(string[] args) { - CreateWebHostBuilder(args).Build().Run(); + CreateHostBuilder(args).Build().Run(); } - public static IWebHostBuilder CreateWebHostBuilder(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup(); + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); } } diff --git a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Properties/launchSettings.json b/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Properties/launchSettings.json deleted file mode 100644 index a42a9703..00000000 --- a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Properties/launchSettings.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "$schema": "http://json.schemastore.org/launchsettings.json", - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:54962", - "sslPort": 44357 - } - }, - "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "launchUrl": "api/values", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "BackEnd": { - "commandName": "Project", - "launchBrowser": true, - "launchUrl": "api/values", - "applicationUrl": "https://localhost:5001;http://localhost:5000", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} \ No newline at end of file diff --git a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Startup.cs b/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Startup.cs index f9be6f5a..937b0c5d 100644 --- a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Startup.cs +++ b/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/Startup.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; @@ -11,9 +11,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Swashbuckle.AspNetCore.Swagger; +using Microsoft.OpenApi.Models; namespace BackEnd { @@ -41,34 +41,36 @@ public void ConfigureServices(IServiceCollection services) } }); - services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); + services.AddControllers(); services.AddSwaggerGen(options => - options.SwaggerDoc("v1", new Info { Title = "Conference Planner API", Version = "v1" }) - ); + options.SwaggerDoc("v1", new OpenApiInfo { Title = "Conference Planner API", Version = "v1" })); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseHttpsRedirection(); + + app.UseRouting(); + + app.UseAuthorization(); + app.UseSwagger(); app.UseSwaggerUI(options => options.SwaggerEndpoint("/swagger/v1/swagger.json", "Conference Planner API v1") ); - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else + app.UseEndpoints(endpoints => { - // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); - } - - app.UseHttpsRedirection(); - app.UseMvc(); + endpoints.MapControllers(); + }); app.Run(context => { diff --git a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/appsettings.json b/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/appsettings.json index cba9e003..a723bdab 100644 --- a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/appsettings.json +++ b/save-points/1-Create-API-and-EF-Model/ConferencePlanner/BackEnd/appsettings.json @@ -2,10 +2,12 @@ "ConnectionStrings": { "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-BackEnd-931E56BD-86CB-4A96-BD99-2C6A6ABB0829;Trusted_Connection=True;MultipleActiveResultSets=true" }, - "Logging": { - "LogLevel": { - "Default": "Warning" - } - }, - "AllowedHosts": "*" + "Logging": { + "LogLevel": { + "Default": "Warning", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" } \ No newline at end of file diff --git a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/ConferencePlanner.sln b/save-points/1-Create-API-and-EF-Model/ConferencePlanner/ConferencePlanner.sln index b3a4a8d2..6729f03b 100644 --- a/save-points/1-Create-API-and-EF-Model/ConferencePlanner/ConferencePlanner.sln +++ b/save-points/1-Create-API-and-EF-Model/ConferencePlanner/ConferencePlanner.sln @@ -1,9 +1,9 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.329 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29007.179 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackEnd", "BackEnd\BackEnd.csproj", "{E7864CB1-70EF-4BDE-95D7-6078DE7F1F13}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackEnd", "BackEnd\BackEnd.csproj", "{54B73C40-8060-4718-A682-5A1C32C1E83A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -11,15 +11,15 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E7864CB1-70EF-4BDE-95D7-6078DE7F1F13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E7864CB1-70EF-4BDE-95D7-6078DE7F1F13}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E7864CB1-70EF-4BDE-95D7-6078DE7F1F13}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E7864CB1-70EF-4BDE-95D7-6078DE7F1F13}.Release|Any CPU.Build.0 = Release|Any CPU + {54B73C40-8060-4718-A682-5A1C32C1E83A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {54B73C40-8060-4718-A682-5A1C32C1E83A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {54B73C40-8060-4718-A682-5A1C32C1E83A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {54B73C40-8060-4718-A682-5A1C32C1E83A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {716BD0AE-1BA1-4372-B4C1-BFE9CFA5FA18} + SolutionGuid = {7C5D815A-7FB9-4BB2-962E-F66EC67114A4} EndGlobalSection EndGlobal From 60c19a74f4acafb4a3fafa197c787b4634bedc6f Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sun, 16 Jun 2019 21:37:25 -0700 Subject: [PATCH 41/56] Added more save points --- .../ConferencePlanner/BackEnd/BackEnd.csproj | 26 +- .../Controllers/AttendeesController.cs | 137 +++++++++ .../BackEnd/Controllers/SessionsController.cs | 143 +++++++++ .../BackEnd/Controllers/SpeakersController.cs | 84 +----- .../BackEnd/Data/ApplicationDbContext.cs | 31 +- .../BackEnd/Data/Attendee.cs | 4 +- .../BackEnd/Data/Conference.cs | 17 -- .../BackEnd/Data/ConferenceAttendee.cs | 18 -- .../BackEnd/Data/DataLoader.cs | 12 + .../BackEnd/Data/DevIntersectionLoader.cs | 73 +++++ .../ConferencePlanner/BackEnd/Data/Session.cs | 6 +- .../{SessionTag.cs => SessionAttendee.cs} | 8 +- .../BackEnd/Data/SessionSpeaker.cs | 1 + .../BackEnd/Data/SessionizeLoader.cs | 122 ++++++++ .../ConferencePlanner/BackEnd/Data/Tag.cs | 9 - .../ConferencePlanner/BackEnd/Data/Track.cs | 3 - .../Infrastructure/EntityExtensions.cs | 70 +++++ .../Migrations/20190128064407_Refactor.cs | 281 ------------------ ....cs => 20190614215301_Initial.Designer.cs} | 8 +- ...9_Initial.cs => 20190614215301_Initial.cs} | 4 +- ...cs => 20190614225827_Refactor.Designer.cs} | 172 +++-------- .../Migrations/20190614225827_Refactor.cs | 151 ++++++++++ .../ApplicationDbContextModelSnapshot.cs | 170 +++-------- .../ConferencePlanner/BackEnd/Program.cs | 16 +- .../BackEnd/Properties/launchSettings.json | 30 -- .../ConferencePlanner/BackEnd/Startup.cs | 41 +-- .../BackEnd/appsettings.json | 14 +- .../ConferenceDTO/Attendee.cs | 2 +- .../ConferenceDTO/AttendeeResponse.cs | 11 + .../ConferenceDTO/Conference.cs | 16 - .../ConferenceDTO/ConferenceDTO.csproj | 4 +- .../ConferenceDTO/Session.cs | 5 +- .../ConferenceDTO/SessionResponse.cs | 13 + .../ConferenceDTO/Speaker.cs | 4 +- .../ConferenceDTO/SpeakerResponse.cs | 12 + .../ConferencePlanner/ConferenceDTO/Tag.cs | 14 - .../ConferencePlanner/ConferenceDTO/Track.cs | 5 +- .../ConferencePlanner/ConferencePlanner.sln | 26 +- 38 files changed, 931 insertions(+), 832 deletions(-) create mode 100644 save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Controllers/AttendeesController.cs create mode 100644 save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Controllers/SessionsController.cs delete mode 100644 save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/Conference.cs delete mode 100644 save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/ConferenceAttendee.cs create mode 100644 save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/DataLoader.cs create mode 100644 save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/DevIntersectionLoader.cs rename save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/{SessionTag.cs => SessionAttendee.cs} (52%) create mode 100644 save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/SessionizeLoader.cs delete mode 100644 save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/Tag.cs create mode 100644 save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Infrastructure/EntityExtensions.cs delete mode 100644 save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190128064407_Refactor.cs rename save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/{20190128054119_Initial.Designer.cs => 20190614215301_Initial.Designer.cs} (87%) rename save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/{20190128054119_Initial.cs => 20190614215301_Initial.cs} (89%) rename save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/{20190128064407_Refactor.Designer.cs => 20190614225827_Refactor.Designer.cs} (51%) create mode 100644 save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190614225827_Refactor.cs delete mode 100644 save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Properties/launchSettings.json create mode 100644 save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/AttendeeResponse.cs delete mode 100644 save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Conference.cs create mode 100644 save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/SessionResponse.cs create mode 100644 save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/SpeakerResponse.cs delete mode 100644 save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Tag.cs diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/BackEnd.csproj b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/BackEnd.csproj index 9a61bce4..02be98f1 100644 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/BackEnd.csproj +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/BackEnd.csproj @@ -1,18 +1,22 @@ - + - netcoreapp2.2 - InProcess - - + netcoreapp3.0 + - - - - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - + diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Controllers/AttendeesController.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Controllers/AttendeesController.cs new file mode 100644 index 00000000..a844202b --- /dev/null +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Controllers/AttendeesController.cs @@ -0,0 +1,137 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using BackEnd.Data; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.AspNetCore.Http; +using ConferenceDTO; + +namespace BackEnd.Controllers +{ + [Route("/api/[controller]")] + [ApiController] + public class AttendeesController : ControllerBase + { + private readonly ApplicationDbContext _context; + + public AttendeesController(ApplicationDbContext context) + { + _context = context; + } + + [HttpGet("{username}")] + public async Task> Get(string username) + { + var attendee = await _context.Attendees.Include(a => a.SessionsAttendees) + .ThenInclude(sa => sa.Session) + .SingleOrDefaultAsync(a => a.UserName == username); + + if (attendee == null) + { + return NotFound(); + } + + var result = attendee.MapAttendeeResponse(); + + return result; + } + + [HttpPost] + [ProducesResponseType(StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status409Conflict)] + public async Task> Post(ConferenceDTO.Attendee input) + { + // Check if the attendee already exists + var existingAttendee = await _context.Attendees + .Where(a => a.UserName == input.UserName) + .FirstOrDefaultAsync(); + + if (existingAttendee != null) + { + return Conflict(input); + } + + var attendee = new Data.Attendee + { + FirstName = input.FirstName, + LastName = input.LastName, + UserName = input.UserName, + EmailAddress = input.EmailAddress + }; + + _context.Attendees.Add(attendee); + await _context.SaveChangesAsync(); + + var result = attendee.MapAttendeeResponse(); + + return CreatedAtAction(nameof(Get), new { username = result.UserName }, result); + } + + [HttpPost("{username}/session/{sessionId}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesDefaultResponseType] + public async Task> AddSession(string username, int sessionId) + { + var attendee = await _context.Attendees.Include(a => a.SessionsAttendees) + .ThenInclude(sa => sa.Session) + .SingleOrDefaultAsync(a => a.UserName == username); + + if (attendee == null) + { + return NotFound(); + } + + var session = await _context.Sessions.FindAsync(sessionId); + + if (session == null) + { + return BadRequest(); + } + + attendee.SessionsAttendees.Add(new SessionAttendee + { + AttendeeId = attendee.Id, + SessionId = sessionId + }); + + await _context.SaveChangesAsync(); + + var result = attendee.MapAttendeeResponse(); + + return result; + } + + [HttpDelete("{username}/session/{sessionId}")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesDefaultResponseType] + public async Task RemoveSession(string username, int sessionId) + { + var attendee = await _context.Attendees.Include(a => a.SessionsAttendees) + .SingleOrDefaultAsync(a => a.UserName == username); + + if (attendee == null) + { + return NotFound(); + } + + var session = await _context.Sessions.FindAsync(sessionId); + + if (session == null) + { + return BadRequest(); + } + + var sessionAttendee = attendee.SessionsAttendees.FirstOrDefault(sa => sa.SessionId == sessionId); + attendee.SessionsAttendees.Remove(sessionAttendee); + + await _context.SaveChangesAsync(); + + return NoContent(); + } + } +} diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Controllers/SessionsController.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Controllers/SessionsController.cs new file mode 100644 index 00000000..ffa252f9 --- /dev/null +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Controllers/SessionsController.cs @@ -0,0 +1,143 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Threading.Tasks; +using BackEnd.Data; +using ConferenceDTO; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace BackEnd.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class SessionsController : Controller + { + private readonly ApplicationDbContext _context; + + public SessionsController(ApplicationDbContext context) + { + _context = context; + } + + [HttpGet] + public async Task>> Get() + { + var sessions = await _context.Sessions.AsNoTracking() + .Include(s => s.Track) + .Include(s => s.SessionSpeakers) + .ThenInclude(ss => ss.Speaker) + .Select(m => m.MapSessionResponse()) + .ToListAsync(); + return sessions; + } + + [HttpGet("{id}")] + public async Task> Get(int id) + { + var session = await _context.Sessions.AsNoTracking() + .Include(s => s.Track) + .Include(s => s.SessionSpeakers) + .ThenInclude(ss => ss.Speaker) + .SingleOrDefaultAsync(s => s.Id == id); + + if (session == null) + { + return NotFound(); + } + + return session.MapSessionResponse(); + } + + [HttpPost] + public async Task> Post(ConferenceDTO.Session input) + { + var session = new Data.Session + { + Title = input.Title, + StartTime = input.StartTime, + EndTime = input.EndTime, + Abstract = input.Abstract, + TrackId = input.TrackId + }; + + _context.Sessions.Add(session); + await _context.SaveChangesAsync(); + + var result = session.MapSessionResponse(); + + return CreatedAtAction(nameof(Get), new { id = result.Id }, result); + } + + [HttpPut("{id}")] + public async Task Put(int id, ConferenceDTO.Session input) + { + var session = await _context.Sessions.FindAsync(id); + + if (session == null) + { + return NotFound(); + } + + session.Id = input.Id; + session.Title = input.Title; + session.Abstract = input.Abstract; + session.StartTime = input.StartTime; + session.EndTime = input.EndTime; + session.TrackId = input.TrackId; + + await _context.SaveChangesAsync(); + + return NoContent(); + } + + [HttpDelete("{id}")] + public async Task> Delete(int id) + { + var session = await _context.Sessions.FindAsync(id); + + if (session == null) + { + return NotFound(); + } + + _context.Sessions.Remove(session); + await _context.SaveChangesAsync(); + + return session.MapSessionResponse(); + } + + + [HttpPost("upload")] + [Consumes("multipart/form-data")] + public async Task Upload([FromForm]ConferenceFormat format, IFormFile file) + { + var loader = GetLoader(format); + + using (var stream = file.OpenReadStream()) + { + await loader.LoadDataAsync(stream, _context); + } + + await _context.SaveChangesAsync(); + + return Ok(); + } + + private static DataLoader GetLoader(ConferenceFormat format) + { + if (format == ConferenceFormat.Sessionize) + { + return new SessionizeLoader(); + } + return new DevIntersectionLoader(); + } + + public enum ConferenceFormat + { + Sessionize, + DevIntersections + } + } +} diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Controllers/SpeakersController.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Controllers/SpeakersController.cs index c625f97d..6e8829bb 100644 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Controllers/SpeakersController.cs +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Controllers/SpeakersController.cs @@ -1,8 +1,6 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using BackEnd.Data; @@ -22,84 +20,30 @@ public SpeakersController(ApplicationDbContext context) // GET: api/Speakers [HttpGet] - public async Task>> GetSpeakers() + public async Task>> GetSpeakers() { - return await _context.Speakers.ToListAsync(); + var speakers = await _context.Speakers.AsNoTracking() + .Include(s => s.SessionSpeakers) + .ThenInclude(ss => ss.Session) + .Select(s => s.MapSpeakerResponse()) + .ToListAsync(); + return speakers; } // GET: api/Speakers/5 [HttpGet("{id}")] - public async Task> GetSpeaker(int id) + public async Task> GetSpeaker(int id) { - var speaker = await _context.Speakers.FindAsync(id); - + var speaker = await _context.Speakers.AsNoTracking() + .Include(s => s.SessionSpeakers) + .ThenInclude(ss => ss.Session) + .SingleOrDefaultAsync(s => s.Id == id); if (speaker == null) { return NotFound(); } - return speaker; - } - - // PUT: api/Speakers/5 - [HttpPut("{id}")] - public async Task PutSpeaker(int id, Speaker speaker) - { - if (id != speaker.ID) - { - return BadRequest(); - } - - _context.Entry(speaker).State = EntityState.Modified; - - try - { - await _context.SaveChangesAsync(); - } - catch (DbUpdateConcurrencyException) - { - if (!SpeakerExists(id)) - { - return NotFound(); - } - else - { - throw; - } - } - - return NoContent(); - } - - // POST: api/Speakers - [HttpPost] - public async Task> PostSpeaker(Speaker speaker) - { - _context.Speakers.Add(speaker); - await _context.SaveChangesAsync(); - - return CreatedAtAction("GetSpeaker", new { id = speaker.ID }, speaker); - } - - // DELETE: api/Speakers/5 - [HttpDelete("{id}")] - public async Task> DeleteSpeaker(int id) - { - var speaker = await _context.Speakers.FindAsync(id); - if (speaker == null) - { - return NotFound(); - } - - _context.Speakers.Remove(speaker); - await _context.SaveChangesAsync(); - - return speaker; - } - - private bool SpeakerExists(int id) - { - return _context.Speakers.Any(e => e.ID == id); + return speaker.MapSpeakerResponse(); } } } diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/ApplicationDbContext.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/ApplicationDbContext.cs index 1209ee3a..975faec3 100644 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/ApplicationDbContext.cs +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/ApplicationDbContext.cs @@ -1,11 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Design; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.EntityFrameworkCore; namespace BackEnd.Data { @@ -20,34 +13,22 @@ public ApplicationDbContext(DbContextOptions options) protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity() - .HasIndex(a => a.UserName) - .IsUnique(); + .HasIndex(a => a.UserName) + .IsUnique(); - // Ignore the computed property - modelBuilder.Entity() - .Ignore(s => s.Duration); - - // Many-to-many: Conference <-> Attendee - modelBuilder.Entity() - .HasKey(ca => new { ca.ConferenceID, ca.AttendeeID }); + // Many-to-many: Session <-> Attendee + modelBuilder.Entity() + .HasKey(ca => new { ca.SessionId, ca.AttendeeId }); // Many-to-many: Speaker <-> Session modelBuilder.Entity() .HasKey(ss => new { ss.SessionId, ss.SpeakerId }); - - // Many-to-many: Session <-> Tag - modelBuilder.Entity() - .HasKey(st => new { st.SessionID, st.TagID }); } - public DbSet Conferences { get; set; } - public DbSet Sessions { get; set; } public DbSet Tracks { get; set; } - public DbSet Tags { get; set; } - public DbSet Speakers { get; set; } public DbSet Attendees { get; set; } diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/Attendee.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/Attendee.cs index 7359b296..18270157 100644 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/Attendee.cs +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/Attendee.cs @@ -5,8 +5,6 @@ namespace BackEnd.Data { public class Attendee : ConferenceDTO.Attendee { - public virtual ICollection ConferenceAttendees { get; set; } - - public virtual ICollection Sessions { get; set; } + public virtual ICollection SessionsAttendees { get; set; } } } \ No newline at end of file diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/Conference.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/Conference.cs deleted file mode 100644 index 82612927..00000000 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/Conference.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace BackEnd.Data -{ - public class Conference : ConferenceDTO.Conference - { - public virtual ICollection Tracks { get; set; } - - public virtual ICollection Speakers { get; set; } - - public virtual ICollection Sessions { get; set; } - - public virtual ICollection ConferenceAttendees { get; set; } - } -} \ No newline at end of file diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/ConferenceAttendee.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/ConferenceAttendee.cs deleted file mode 100644 index 4e6877d1..00000000 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/ConferenceAttendee.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace BackEnd.Data -{ - public class ConferenceAttendee - { - public int ConferenceID { get; set; } - - public Conference Conference { get; set; } - - public int AttendeeID { get; set; } - - public Attendee Attendee { get; set; } - } -} \ No newline at end of file diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/DataLoader.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/DataLoader.cs new file mode 100644 index 00000000..589c1384 --- /dev/null +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/DataLoader.cs @@ -0,0 +1,12 @@ +using System; +using System.IO; +using System.Threading.Tasks; + +namespace BackEnd.Data +{ + public abstract class DataLoader + { + public abstract Task LoadDataAsync(Stream fileStream, ApplicationDbContext db); + } + +} \ No newline at end of file diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/DevIntersectionLoader.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/DevIntersectionLoader.cs new file mode 100644 index 00000000..932b6ab3 --- /dev/null +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/DevIntersectionLoader.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using BackEnd.Data; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace BackEnd +{ + public class DevIntersectionLoader : DataLoader + { + public override async Task LoadDataAsync(Stream fileStream, ApplicationDbContext db) + { + var reader = new JsonTextReader(new StreamReader(fileStream)); + + var speakerNames = new Dictionary(); + var tracks = new Dictionary(); + + JArray doc = await JArray.LoadAsync(reader); + + foreach (JObject item in doc) + { + var theseSpeakers = new List(); + foreach (var thisSpeakerName in item["speakerNames"]) + { + if (!speakerNames.ContainsKey(thisSpeakerName.Value())) + { + var thisSpeaker = new Speaker { Name = thisSpeakerName.Value() }; + db.Speakers.Add(thisSpeaker); + speakerNames.Add(thisSpeakerName.Value(), thisSpeaker); + Console.WriteLine(thisSpeakerName.Value()); + } + theseSpeakers.Add(speakerNames[thisSpeakerName.Value()]); + } + + var theseTracks = new List(); + foreach (var thisTrackName in item["trackNames"]) + { + if (!tracks.ContainsKey(thisTrackName.Value())) + { + var thisTrack = new Track { Name = thisTrackName.Value() }; + db.Tracks.Add(thisTrack); + tracks.Add(thisTrackName.Value(), thisTrack); + } + theseTracks.Add(tracks[thisTrackName.Value()]); + } + + var session = new Session + { + Title = item["title"].Value(), + StartTime = item["startTime"].Value(), + EndTime = item["endTime"].Value(), + Track = theseTracks[0], + Abstract = item["abstract"].Value() + }; + + session.SessionSpeakers = new List(); + foreach (var sp in theseSpeakers) + { + session.SessionSpeakers.Add(new SessionSpeaker + { + Session = session, + Speaker = sp + }); + } + + db.Sessions.Add(session); + } + } + } +} + diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/Session.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/Session.cs index 27b6ae5c..a3b7cbf4 100644 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/Session.cs +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/Session.cs @@ -6,12 +6,10 @@ namespace BackEnd.Data { public class Session : ConferenceDTO.Session { - public Conference Conference { get; set; } - public virtual ICollection SessionSpeakers { get; set; } - public Track Track { get; set; } + public virtual ICollection SessionAttendees { get; set; } - public virtual ICollection SessionTags { get; set; } + public Track Track { get; set; } } } \ No newline at end of file diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/SessionTag.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/SessionAttendee.cs similarity index 52% rename from save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/SessionTag.cs rename to save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/SessionAttendee.cs index d2f59a17..6c358231 100644 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/SessionTag.cs +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/SessionAttendee.cs @@ -5,14 +5,14 @@ namespace BackEnd.Data { - public class SessionTag + public class SessionAttendee { - public int SessionID { get; set; } + public int SessionId { get; set; } public Session Session { get; set; } - public int TagID { get; set; } + public int AttendeeId { get; set; } - public Tag Tag { get; set; } + public Attendee Attendee { get; set; } } } \ No newline at end of file diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/SessionSpeaker.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/SessionSpeaker.cs index 73cf57b9..e69ffca2 100644 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/SessionSpeaker.cs +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/SessionSpeaker.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using ConferenceDTO; namespace BackEnd.Data { diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/SessionizeLoader.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/SessionizeLoader.cs new file mode 100644 index 00000000..a65c399f --- /dev/null +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/SessionizeLoader.cs @@ -0,0 +1,122 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using BackEnd.Data; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace BackEnd +{ + public class SessionizeLoader : DataLoader + { + public override async Task LoadDataAsync(Stream fileStream, ApplicationDbContext db) + { + // var blah = new RootObject().rooms[0].sessions[0].speakers[0].name; + + var addedSpeakers = new Dictionary(); + var addedTracks = new Dictionary(); + + var array = await JToken.LoadAsync(new JsonTextReader(new StreamReader(fileStream))); + + var root = array.ToObject>(); + + foreach (var date in root) + { + foreach (var room in date.rooms) + { + if (!addedTracks.ContainsKey(room.name)) + { + var thisTrack = new Track { Name = room.name }; + db.Tracks.Add(thisTrack); + addedTracks.Add(thisTrack.Name, thisTrack); + } + + foreach (var thisSession in room.sessions) + { + foreach (var speaker in thisSession.speakers) + { + if (!addedSpeakers.ContainsKey(speaker.name)) + { + var thisSpeaker = new Speaker { Name = speaker.name }; + db.Speakers.Add(thisSpeaker); + addedSpeakers.Add(thisSpeaker.Name, thisSpeaker); + } + } + + var session = new Session + { + Title = thisSession.title, + StartTime = thisSession.startsAt, + EndTime = thisSession.endsAt, + Track = addedTracks[room.name], + Abstract = thisSession.description + }; + + session.SessionSpeakers = new List(); + foreach (var sp in thisSession.speakers) + { + session.SessionSpeakers.Add(new SessionSpeaker + { + Session = session, + Speaker = addedSpeakers[sp.name] + }); + } + + db.Sessions.Add(session); + } + } + } + } + + private class RootObject + { + public DateTime date { get; set; } + public List rooms { get; set; } + public List timeSlots { get; set; } + } + + private class ImportSpeaker + { + public string id { get; set; } + public string name { get; set; } + } + + private class Category + { + public int id { get; set; } + public string name { get; set; } + public List categoryItems { get; set; } + public int sort { get; set; } + } + + private class ImportSession + { + public int id { get; set; } + public string title { get; set; } + public string description { get; set; } + public DateTime startsAt { get; set; } + public DateTime endsAt { get; set; } + public bool isServiceSession { get; set; } + public bool isPlenumSession { get; set; } + public List speakers { get; set; } + public List categories { get; set; } + public int roomId { get; set; } + public string room { get; set; } + } + + private class Room + { + public int id { get; set; } + public string name { get; set; } + public List sessions { get; set; } + public bool hasOnlyPlenumSessions { get; set; } + } + + private class TimeSlot + { + public string slotStart { get; set; } + public List rooms { get; set; } + } + } +} \ No newline at end of file diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/Tag.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/Tag.cs deleted file mode 100644 index 6e872ac5..00000000 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/Tag.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Collections.Generic; - -namespace BackEnd.Data -{ - public class Tag : ConferenceDTO.Tag - { - public virtual ICollection SessionTags { get; set; } - } -} \ No newline at end of file diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/Track.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/Track.cs index 6f72f990..ea8393b0 100644 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/Track.cs +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Data/Track.cs @@ -6,9 +6,6 @@ namespace BackEnd.Data { public class Track : ConferenceDTO.Track { - [Required] - public Conference Conference { get; set; } - public virtual ICollection Sessions { get; set; } } } \ No newline at end of file diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Infrastructure/EntityExtensions.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Infrastructure/EntityExtensions.cs new file mode 100644 index 00000000..26dc76ac --- /dev/null +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Infrastructure/EntityExtensions.cs @@ -0,0 +1,70 @@ +using BackEnd.Data; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace BackEnd.Data +{ + public static class EntityExtensions + { + public static ConferenceDTO.SessionResponse MapSessionResponse(this Session session) => + new ConferenceDTO.SessionResponse + { + Id = session.Id, + Title = session.Title, + StartTime = session.StartTime, + EndTime = session.EndTime, + Speakers = session.SessionSpeakers? + .Select(ss => new ConferenceDTO.Speaker + { + Id = ss.SpeakerId, + Name = ss.Speaker.Name + }) + .ToList(), + TrackId = session.TrackId, + Track = new ConferenceDTO.Track + { + Id = session?.TrackId ?? 0, + Name = session.Track?.Name + }, + Abstract = session.Abstract + }; + + public static ConferenceDTO.SpeakerResponse MapSpeakerResponse(this Speaker speaker) => + new ConferenceDTO.SpeakerResponse + { + Id = speaker.Id, + Name = speaker.Name, + Bio = speaker.Bio, + WebSite = speaker.WebSite, + Sessions = speaker.SessionSpeakers? + .Select(ss => + new ConferenceDTO.Session + { + Id = ss.SessionId, + Title = ss.Session.Title + }) + .ToList() + }; + + public static ConferenceDTO.AttendeeResponse MapAttendeeResponse(this Attendee attendee) => + new ConferenceDTO.AttendeeResponse + { + Id = attendee.Id, + FirstName = attendee.FirstName, + LastName = attendee.LastName, + UserName = attendee.UserName, + Sessions = attendee.SessionsAttendees? + .Select(sa => + new ConferenceDTO.Session + { + Id = sa.SessionId, + Title = sa.Session.Title, + StartTime = sa.Session.StartTime, + EndTime = sa.Session.EndTime + }) + .ToList() + }; + } +} \ No newline at end of file diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190128064407_Refactor.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190128064407_Refactor.cs deleted file mode 100644 index 5effcda7..00000000 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190128064407_Refactor.cs +++ /dev/null @@ -1,281 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace BackEnd.Migrations -{ - public partial class Refactor : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "ConferenceID", - table: "Speakers", - nullable: true); - - migrationBuilder.CreateTable( - name: "Attendees", - columns: table => new - { - ID = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - FirstName = table.Column(maxLength: 200, nullable: false), - LastName = table.Column(maxLength: 200, nullable: false), - UserName = table.Column(maxLength: 200, nullable: false), - EmailAddress = table.Column(maxLength: 256, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Attendees", x => x.ID); - }); - - migrationBuilder.CreateTable( - name: "Conferences", - columns: table => new - { - ID = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - Name = table.Column(maxLength: 200, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Conferences", x => x.ID); - }); - - migrationBuilder.CreateTable( - name: "Tags", - columns: table => new - { - ID = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - Name = table.Column(maxLength: 32, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Tags", x => x.ID); - }); - - migrationBuilder.CreateTable( - name: "ConferenceAttendee", - columns: table => new - { - ConferenceID = table.Column(nullable: false), - AttendeeID = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ConferenceAttendee", x => new { x.ConferenceID, x.AttendeeID }); - table.ForeignKey( - name: "FK_ConferenceAttendee_Attendees_AttendeeID", - column: x => x.AttendeeID, - principalTable: "Attendees", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_ConferenceAttendee_Conferences_ConferenceID", - column: x => x.ConferenceID, - principalTable: "Conferences", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Tracks", - columns: table => new - { - TrackID = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - ConferenceID = table.Column(nullable: false), - Name = table.Column(maxLength: 200, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Tracks", x => x.TrackID); - table.ForeignKey( - name: "FK_Tracks_Conferences_ConferenceID", - column: x => x.ConferenceID, - principalTable: "Conferences", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Sessions", - columns: table => new - { - ID = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - ConferenceID = table.Column(nullable: false), - Title = table.Column(maxLength: 200, nullable: false), - Abstract = table.Column(maxLength: 4000, nullable: true), - StartTime = table.Column(nullable: true), - EndTime = table.Column(nullable: true), - TrackId = table.Column(nullable: true), - AttendeeID = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Sessions", x => x.ID); - table.ForeignKey( - name: "FK_Sessions_Attendees_AttendeeID", - column: x => x.AttendeeID, - principalTable: "Attendees", - principalColumn: "ID", - onDelete: ReferentialAction.Restrict); - table.ForeignKey( - name: "FK_Sessions_Conferences_ConferenceID", - column: x => x.ConferenceID, - principalTable: "Conferences", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_Sessions_Tracks_TrackId", - column: x => x.TrackId, - principalTable: "Tracks", - principalColumn: "TrackID", - onDelete: ReferentialAction.Restrict); - }); - - migrationBuilder.CreateTable( - name: "SessionSpeaker", - columns: table => new - { - SessionId = table.Column(nullable: false), - SpeakerId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_SessionSpeaker", x => new { x.SessionId, x.SpeakerId }); - table.ForeignKey( - name: "FK_SessionSpeaker_Sessions_SessionId", - column: x => x.SessionId, - principalTable: "Sessions", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_SessionSpeaker_Speakers_SpeakerId", - column: x => x.SpeakerId, - principalTable: "Speakers", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "SessionTag", - columns: table => new - { - SessionID = table.Column(nullable: false), - TagID = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_SessionTag", x => new { x.SessionID, x.TagID }); - table.ForeignKey( - name: "FK_SessionTag_Sessions_SessionID", - column: x => x.SessionID, - principalTable: "Sessions", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_SessionTag_Tags_TagID", - column: x => x.TagID, - principalTable: "Tags", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_Speakers_ConferenceID", - table: "Speakers", - column: "ConferenceID"); - - migrationBuilder.CreateIndex( - name: "IX_Attendees_UserName", - table: "Attendees", - column: "UserName", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ConferenceAttendee_AttendeeID", - table: "ConferenceAttendee", - column: "AttendeeID"); - - migrationBuilder.CreateIndex( - name: "IX_Sessions_AttendeeID", - table: "Sessions", - column: "AttendeeID"); - - migrationBuilder.CreateIndex( - name: "IX_Sessions_ConferenceID", - table: "Sessions", - column: "ConferenceID"); - - migrationBuilder.CreateIndex( - name: "IX_Sessions_TrackId", - table: "Sessions", - column: "TrackId"); - - migrationBuilder.CreateIndex( - name: "IX_SessionSpeaker_SpeakerId", - table: "SessionSpeaker", - column: "SpeakerId"); - - migrationBuilder.CreateIndex( - name: "IX_SessionTag_TagID", - table: "SessionTag", - column: "TagID"); - - migrationBuilder.CreateIndex( - name: "IX_Tracks_ConferenceID", - table: "Tracks", - column: "ConferenceID"); - - migrationBuilder.AddForeignKey( - name: "FK_Speakers_Conferences_ConferenceID", - table: "Speakers", - column: "ConferenceID", - principalTable: "Conferences", - principalColumn: "ID", - onDelete: ReferentialAction.Restrict); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_Speakers_Conferences_ConferenceID", - table: "Speakers"); - - migrationBuilder.DropTable( - name: "ConferenceAttendee"); - - migrationBuilder.DropTable( - name: "SessionSpeaker"); - - migrationBuilder.DropTable( - name: "SessionTag"); - - migrationBuilder.DropTable( - name: "Sessions"); - - migrationBuilder.DropTable( - name: "Tags"); - - migrationBuilder.DropTable( - name: "Attendees"); - - migrationBuilder.DropTable( - name: "Tracks"); - - migrationBuilder.DropTable( - name: "Conferences"); - - migrationBuilder.DropIndex( - name: "IX_Speakers_ConferenceID", - table: "Speakers"); - - migrationBuilder.DropColumn( - name: "ConferenceID", - table: "Speakers"); - } - } -} diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190128054119_Initial.Designer.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190614215301_Initial.Designer.cs similarity index 87% rename from save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190128054119_Initial.Designer.cs rename to save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190614215301_Initial.Designer.cs index 497774c4..e0ccbb77 100644 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190128054119_Initial.Designer.cs +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190614215301_Initial.Designer.cs @@ -9,20 +9,20 @@ namespace BackEnd.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20190128054119_Initial")] + [Migration("20190614215301_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.1-servicing-10028") + .HasAnnotation("ProductVersion", "3.0.0-preview6.19304.10") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("BackEnd.Models.Speaker", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); @@ -36,7 +36,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("WebSite") .HasMaxLength(1000); - b.HasKey("ID"); + b.HasKey("Id"); b.ToTable("Speakers"); }); diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190128054119_Initial.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190614215301_Initial.cs similarity index 89% rename from save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190128054119_Initial.cs rename to save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190614215301_Initial.cs index 9eb54949..b56fda42 100644 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190128054119_Initial.cs +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190614215301_Initial.cs @@ -11,7 +11,7 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "Speakers", columns: table => new { - ID = table.Column(nullable: false) + Id = table.Column(nullable: false) .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), Name = table.Column(maxLength: 200, nullable: false), Bio = table.Column(maxLength: 4000, nullable: true), @@ -19,7 +19,7 @@ protected override void Up(MigrationBuilder migrationBuilder) }, constraints: table => { - table.PrimaryKey("PK_Speakers", x => x.ID); + table.PrimaryKey("PK_Speakers", x => x.Id); }); } diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190128064407_Refactor.Designer.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190614225827_Refactor.Designer.cs similarity index 51% rename from save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190128064407_Refactor.Designer.cs rename to save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190614225827_Refactor.Designer.cs index 17d90fbe..a9bfe2fc 100644 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190128064407_Refactor.Designer.cs +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190614225827_Refactor.Designer.cs @@ -10,20 +10,20 @@ namespace BackEnd.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20190128064407_Refactor")] + [Migration("20190614225827_Refactor")] partial class Refactor { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.1-servicing-10028") + .HasAnnotation("ProductVersion", "3.0.0-preview6.19304.10") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("BackEnd.Data.Attendee", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); @@ -42,7 +42,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .IsRequired() .HasMaxLength(200); - b.HasKey("ID"); + b.HasKey("Id"); b.HasIndex("UserName") .IsUnique(); @@ -50,47 +50,15 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("Attendees"); }); - modelBuilder.Entity("BackEnd.Data.Conference", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("ID"); - - b.ToTable("Conferences"); - }); - - modelBuilder.Entity("BackEnd.Data.ConferenceAttendee", b => - { - b.Property("ConferenceID"); - - b.Property("AttendeeID"); - - b.HasKey("ConferenceID", "AttendeeID"); - - b.HasIndex("AttendeeID"); - - b.ToTable("ConferenceAttendee"); - }); - modelBuilder.Entity("BackEnd.Data.Session", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("Abstract") .HasMaxLength(4000); - b.Property("AttendeeID"); - - b.Property("ConferenceID"); - b.Property("EndTime"); b.Property("StartTime"); @@ -101,54 +69,48 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("TrackId"); - b.HasKey("ID"); - - b.HasIndex("AttendeeID"); - - b.HasIndex("ConferenceID"); + b.HasKey("Id"); b.HasIndex("TrackId"); b.ToTable("Sessions"); }); - modelBuilder.Entity("BackEnd.Data.SessionSpeaker", b => + modelBuilder.Entity("BackEnd.Data.SessionAttendee", b => { b.Property("SessionId"); - b.Property("SpeakerId"); + b.Property("AttendeeId"); - b.HasKey("SessionId", "SpeakerId"); + b.HasKey("SessionId", "AttendeeId"); - b.HasIndex("SpeakerId"); + b.HasIndex("AttendeeId"); - b.ToTable("SessionSpeaker"); + b.ToTable("SessionAttendee"); }); - modelBuilder.Entity("BackEnd.Data.SessionTag", b => + modelBuilder.Entity("BackEnd.Data.SessionSpeaker", b => { - b.Property("SessionID"); + b.Property("SessionId"); - b.Property("TagID"); + b.Property("SpeakerId"); - b.HasKey("SessionID", "TagID"); + b.HasKey("SessionId", "SpeakerId"); - b.HasIndex("TagID"); + b.HasIndex("SpeakerId"); - b.ToTable("SessionTag"); + b.ToTable("SessionSpeaker"); }); modelBuilder.Entity("BackEnd.Data.Speaker", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("Bio") .HasMaxLength(4000); - b.Property("ConferenceID"); - b.Property("Name") .IsRequired() .HasMaxLength(200); @@ -156,115 +118,61 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("WebSite") .HasMaxLength(1000); - b.HasKey("ID"); - - b.HasIndex("ConferenceID"); + b.HasKey("Id"); b.ToTable("Speakers"); }); - modelBuilder.Entity("BackEnd.Data.Tag", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("Name") - .IsRequired() - .HasMaxLength(32); - - b.HasKey("ID"); - - b.ToTable("Tags"); - }); - modelBuilder.Entity("BackEnd.Data.Track", b => { - b.Property("TrackID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - b.Property("ConferenceID"); - b.Property("Name") .IsRequired() .HasMaxLength(200); - b.HasKey("TrackID"); - - b.HasIndex("ConferenceID"); + b.HasKey("Id"); b.ToTable("Tracks"); }); - modelBuilder.Entity("BackEnd.Data.ConferenceAttendee", b => - { - b.HasOne("BackEnd.Data.Attendee", "Attendee") - .WithMany("ConferenceAttendees") - .HasForeignKey("AttendeeID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("BackEnd.Data.Conference", "Conference") - .WithMany("ConferenceAttendees") - .HasForeignKey("ConferenceID") - .OnDelete(DeleteBehavior.Cascade); - }); - modelBuilder.Entity("BackEnd.Data.Session", b => { - b.HasOne("BackEnd.Data.Attendee") - .WithMany("Sessions") - .HasForeignKey("AttendeeID"); - - b.HasOne("BackEnd.Data.Conference", "Conference") - .WithMany("Sessions") - .HasForeignKey("ConferenceID") - .OnDelete(DeleteBehavior.Cascade); - b.HasOne("BackEnd.Data.Track", "Track") .WithMany("Sessions") .HasForeignKey("TrackId"); }); + modelBuilder.Entity("BackEnd.Data.SessionAttendee", b => + { + b.HasOne("BackEnd.Data.Attendee", "Attendee") + .WithMany("SessionsAttendees") + .HasForeignKey("AttendeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("BackEnd.Data.Session", "Session") + .WithMany() + .HasForeignKey("SessionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("BackEnd.Data.SessionSpeaker", b => { b.HasOne("BackEnd.Data.Session", "Session") .WithMany("SessionSpeakers") .HasForeignKey("SessionId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); b.HasOne("BackEnd.Data.Speaker", "Speaker") .WithMany("SessionSpeakers") .HasForeignKey("SpeakerId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("BackEnd.Data.SessionTag", b => - { - b.HasOne("BackEnd.Data.Session", "Session") - .WithMany("SessionTags") - .HasForeignKey("SessionID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("BackEnd.Data.Tag", "Tag") - .WithMany("SessionTags") - .HasForeignKey("TagID") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("BackEnd.Data.Speaker", b => - { - b.HasOne("BackEnd.Data.Conference") - .WithMany("Speakers") - .HasForeignKey("ConferenceID"); - }); - - modelBuilder.Entity("BackEnd.Data.Track", b => - { - b.HasOne("BackEnd.Data.Conference", "Conference") - .WithMany("Tracks") - .HasForeignKey("ConferenceID") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); #pragma warning restore 612, 618 } diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190614225827_Refactor.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190614225827_Refactor.cs new file mode 100644 index 00000000..168a0ca7 --- /dev/null +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/20190614225827_Refactor.cs @@ -0,0 +1,151 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace BackEnd.Migrations +{ + public partial class Refactor : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Attendees", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), + FirstName = table.Column(maxLength: 200, nullable: false), + LastName = table.Column(maxLength: 200, nullable: false), + UserName = table.Column(maxLength: 200, nullable: false), + EmailAddress = table.Column(maxLength: 256, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Attendees", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Tracks", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), + Name = table.Column(maxLength: 200, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Tracks", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Sessions", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), + Title = table.Column(maxLength: 200, nullable: false), + Abstract = table.Column(maxLength: 4000, nullable: true), + StartTime = table.Column(nullable: true), + EndTime = table.Column(nullable: true), + TrackId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Sessions", x => x.Id); + table.ForeignKey( + name: "FK_Sessions_Tracks_TrackId", + column: x => x.TrackId, + principalTable: "Tracks", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "SessionAttendee", + columns: table => new + { + SessionId = table.Column(nullable: false), + AttendeeId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SessionAttendee", x => new { x.SessionId, x.AttendeeId }); + table.ForeignKey( + name: "FK_SessionAttendee_Attendees_AttendeeId", + column: x => x.AttendeeId, + principalTable: "Attendees", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_SessionAttendee_Sessions_SessionId", + column: x => x.SessionId, + principalTable: "Sessions", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "SessionSpeaker", + columns: table => new + { + SessionId = table.Column(nullable: false), + SpeakerId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SessionSpeaker", x => new { x.SessionId, x.SpeakerId }); + table.ForeignKey( + name: "FK_SessionSpeaker_Sessions_SessionId", + column: x => x.SessionId, + principalTable: "Sessions", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_SessionSpeaker_Speakers_SpeakerId", + column: x => x.SpeakerId, + principalTable: "Speakers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Attendees_UserName", + table: "Attendees", + column: "UserName", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_SessionAttendee_AttendeeId", + table: "SessionAttendee", + column: "AttendeeId"); + + migrationBuilder.CreateIndex( + name: "IX_Sessions_TrackId", + table: "Sessions", + column: "TrackId"); + + migrationBuilder.CreateIndex( + name: "IX_SessionSpeaker_SpeakerId", + table: "SessionSpeaker", + column: "SpeakerId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "SessionAttendee"); + + migrationBuilder.DropTable( + name: "SessionSpeaker"); + + migrationBuilder.DropTable( + name: "Attendees"); + + migrationBuilder.DropTable( + name: "Sessions"); + + migrationBuilder.DropTable( + name: "Tracks"); + } + } +} diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/ApplicationDbContextModelSnapshot.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/ApplicationDbContextModelSnapshot.cs index 6be8902f..5bec0e4c 100644 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Migrations/ApplicationDbContextModelSnapshot.cs @@ -15,13 +15,13 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.1-servicing-10028") + .HasAnnotation("ProductVersion", "3.0.0-preview6.19304.10") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("BackEnd.Data.Attendee", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); @@ -40,7 +40,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasMaxLength(200); - b.HasKey("ID"); + b.HasKey("Id"); b.HasIndex("UserName") .IsUnique(); @@ -48,47 +48,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("Attendees"); }); - modelBuilder.Entity("BackEnd.Data.Conference", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("ID"); - - b.ToTable("Conferences"); - }); - - modelBuilder.Entity("BackEnd.Data.ConferenceAttendee", b => - { - b.Property("ConferenceID"); - - b.Property("AttendeeID"); - - b.HasKey("ConferenceID", "AttendeeID"); - - b.HasIndex("AttendeeID"); - - b.ToTable("ConferenceAttendee"); - }); - modelBuilder.Entity("BackEnd.Data.Session", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("Abstract") .HasMaxLength(4000); - b.Property("AttendeeID"); - - b.Property("ConferenceID"); - b.Property("EndTime"); b.Property("StartTime"); @@ -99,54 +67,48 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("TrackId"); - b.HasKey("ID"); - - b.HasIndex("AttendeeID"); - - b.HasIndex("ConferenceID"); + b.HasKey("Id"); b.HasIndex("TrackId"); b.ToTable("Sessions"); }); - modelBuilder.Entity("BackEnd.Data.SessionSpeaker", b => + modelBuilder.Entity("BackEnd.Data.SessionAttendee", b => { b.Property("SessionId"); - b.Property("SpeakerId"); + b.Property("AttendeeId"); - b.HasKey("SessionId", "SpeakerId"); + b.HasKey("SessionId", "AttendeeId"); - b.HasIndex("SpeakerId"); + b.HasIndex("AttendeeId"); - b.ToTable("SessionSpeaker"); + b.ToTable("SessionAttendee"); }); - modelBuilder.Entity("BackEnd.Data.SessionTag", b => + modelBuilder.Entity("BackEnd.Data.SessionSpeaker", b => { - b.Property("SessionID"); + b.Property("SessionId"); - b.Property("TagID"); + b.Property("SpeakerId"); - b.HasKey("SessionID", "TagID"); + b.HasKey("SessionId", "SpeakerId"); - b.HasIndex("TagID"); + b.HasIndex("SpeakerId"); - b.ToTable("SessionTag"); + b.ToTable("SessionSpeaker"); }); modelBuilder.Entity("BackEnd.Data.Speaker", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("Bio") .HasMaxLength(4000); - b.Property("ConferenceID"); - b.Property("Name") .IsRequired() .HasMaxLength(200); @@ -154,115 +116,61 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("WebSite") .HasMaxLength(1000); - b.HasKey("ID"); - - b.HasIndex("ConferenceID"); + b.HasKey("Id"); b.ToTable("Speakers"); }); - modelBuilder.Entity("BackEnd.Data.Tag", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("Name") - .IsRequired() - .HasMaxLength(32); - - b.HasKey("ID"); - - b.ToTable("Tags"); - }); - modelBuilder.Entity("BackEnd.Data.Track", b => { - b.Property("TrackID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - b.Property("ConferenceID"); - b.Property("Name") .IsRequired() .HasMaxLength(200); - b.HasKey("TrackID"); - - b.HasIndex("ConferenceID"); + b.HasKey("Id"); b.ToTable("Tracks"); }); - modelBuilder.Entity("BackEnd.Data.ConferenceAttendee", b => - { - b.HasOne("BackEnd.Data.Attendee", "Attendee") - .WithMany("ConferenceAttendees") - .HasForeignKey("AttendeeID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("BackEnd.Data.Conference", "Conference") - .WithMany("ConferenceAttendees") - .HasForeignKey("ConferenceID") - .OnDelete(DeleteBehavior.Cascade); - }); - modelBuilder.Entity("BackEnd.Data.Session", b => { - b.HasOne("BackEnd.Data.Attendee") - .WithMany("Sessions") - .HasForeignKey("AttendeeID"); - - b.HasOne("BackEnd.Data.Conference", "Conference") - .WithMany("Sessions") - .HasForeignKey("ConferenceID") - .OnDelete(DeleteBehavior.Cascade); - b.HasOne("BackEnd.Data.Track", "Track") .WithMany("Sessions") .HasForeignKey("TrackId"); }); + modelBuilder.Entity("BackEnd.Data.SessionAttendee", b => + { + b.HasOne("BackEnd.Data.Attendee", "Attendee") + .WithMany("SessionsAttendees") + .HasForeignKey("AttendeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("BackEnd.Data.Session", "Session") + .WithMany() + .HasForeignKey("SessionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("BackEnd.Data.SessionSpeaker", b => { b.HasOne("BackEnd.Data.Session", "Session") .WithMany("SessionSpeakers") .HasForeignKey("SessionId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); b.HasOne("BackEnd.Data.Speaker", "Speaker") .WithMany("SessionSpeakers") .HasForeignKey("SpeakerId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("BackEnd.Data.SessionTag", b => - { - b.HasOne("BackEnd.Data.Session", "Session") - .WithMany("SessionTags") - .HasForeignKey("SessionID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("BackEnd.Data.Tag", "Tag") - .WithMany("SessionTags") - .HasForeignKey("TagID") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("BackEnd.Data.Speaker", b => - { - b.HasOne("BackEnd.Data.Conference") - .WithMany("Speakers") - .HasForeignKey("ConferenceID"); - }); - - modelBuilder.Entity("BackEnd.Data.Track", b => - { - b.HasOne("BackEnd.Data.Conference", "Conference") - .WithMany("Tracks") - .HasForeignKey("ConferenceID") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); #pragma warning restore 612, 618 } diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Program.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Program.cs index c38605c3..e427203e 100644 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Program.cs +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Program.cs @@ -1,11 +1,10 @@ -using System; +using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace BackEnd @@ -14,11 +13,14 @@ public class Program { public static void Main(string[] args) { - CreateWebHostBuilder(args).Build().Run(); + CreateHostBuilder(args).Build().Run(); } - public static IWebHostBuilder CreateWebHostBuilder(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup(); + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); } } diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Properties/launchSettings.json b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Properties/launchSettings.json deleted file mode 100644 index a42a9703..00000000 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Properties/launchSettings.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "$schema": "http://json.schemastore.org/launchsettings.json", - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:54962", - "sslPort": 44357 - } - }, - "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "launchUrl": "api/values", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "BackEnd": { - "commandName": "Project", - "launchBrowser": true, - "launchUrl": "api/values", - "applicationUrl": "https://localhost:5001;http://localhost:5000", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} \ No newline at end of file diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Startup.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Startup.cs index 89eff7ed..f58f6356 100644 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Startup.cs +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/Startup.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; @@ -11,9 +11,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Swashbuckle.AspNetCore.Swagger; +using Microsoft.OpenApi.Models; namespace BackEnd { @@ -41,34 +41,39 @@ public void ConfigureServices(IServiceCollection services) } }); - services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); + services.AddControllers(); services.AddSwaggerGen(options => - options.SwaggerDoc("v1", new Info { Title = "Conference Planner API", Version = "v1" }) - ); + { + options.SwaggerDoc("v1", new OpenApiInfo { Title = "Conference Planner API", Version = "v1" }); + options.DescribeAllEnumsAsStrings(); + }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseHttpsRedirection(); + + app.UseRouting(); + + app.UseAuthorization(); + app.UseSwagger(); app.UseSwaggerUI(options => options.SwaggerEndpoint("/swagger/v1/swagger.json", "Conference Planner API v1") ); - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else + app.UseEndpoints(endpoints => { - // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); - } - - app.UseHttpsRedirection(); - app.UseMvc(); + endpoints.MapControllers(); + }); app.Run(context => { diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/appsettings.json b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/appsettings.json index cba9e003..a723bdab 100644 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/appsettings.json +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/BackEnd/appsettings.json @@ -2,10 +2,12 @@ "ConnectionStrings": { "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-BackEnd-931E56BD-86CB-4A96-BD99-2C6A6ABB0829;Trusted_Connection=True;MultipleActiveResultSets=true" }, - "Logging": { - "LogLevel": { - "Default": "Warning" - } - }, - "AllowedHosts": "*" + "Logging": { + "LogLevel": { + "Default": "Warning", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" } \ No newline at end of file diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Attendee.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Attendee.cs index ec5a3a50..6fb8b5e5 100644 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Attendee.cs +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Attendee.cs @@ -6,7 +6,7 @@ namespace ConferenceDTO { public class Attendee { - public int ID { get; set; } + public int Id { get; set; } [Required] [StringLength(200)] diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/AttendeeResponse.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/AttendeeResponse.cs new file mode 100644 index 00000000..8f75153b --- /dev/null +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/AttendeeResponse.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ConferenceDTO +{ + public class AttendeeResponse : Attendee + { + public ICollection Sessions { get; set; } = new List(); + } +} diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Conference.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Conference.cs deleted file mode 100644 index bee6bcb3..00000000 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Conference.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Text; - -namespace ConferenceDTO -{ - public class Conference - { - public int ID { get; set; } - - [Required] - [StringLength(200)] - public string Name { get; set; } - } -} \ No newline at end of file diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/ConferenceDTO.csproj b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/ConferenceDTO.csproj index 56cdff24..2160f683 100644 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/ConferenceDTO.csproj +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/ConferenceDTO.csproj @@ -1,11 +1,9 @@ - + netstandard2.0 - - diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Session.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Session.cs index d20b39b3..5ad7540e 100644 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Session.cs +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Session.cs @@ -7,10 +7,7 @@ namespace ConferenceDTO { public class Session { - public int ID { get; set; } - - [Required] - public int ConferenceID { get; set; } + public int Id { get; set; } [Required] [StringLength(200)] diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/SessionResponse.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/SessionResponse.cs new file mode 100644 index 00000000..0834be99 --- /dev/null +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/SessionResponse.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ConferenceDTO +{ + public class SessionResponse : Session + { + public Track Track { get; set; } + + public List Speakers { get; set; } = new List(); + } +} diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Speaker.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Speaker.cs index 99104980..f807e327 100644 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Speaker.cs +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Speaker.cs @@ -8,7 +8,7 @@ namespace ConferenceDTO { public class Speaker { - public int ID { get; set; } + public int Id { get; set; } [Required] [StringLength(200)] @@ -20,4 +20,4 @@ public class Speaker [StringLength(1000)] public virtual string WebSite { get; set; } } -} \ No newline at end of file +} diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/SpeakerResponse.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/SpeakerResponse.cs new file mode 100644 index 00000000..ef7dcd56 --- /dev/null +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/SpeakerResponse.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ConferenceDTO +{ + public class SpeakerResponse : Speaker + { + // TODO: Set order of JSON properties so this shows up last not first + public ICollection Sessions { get; set; } = new List(); + } +} \ No newline at end of file diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Tag.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Tag.cs deleted file mode 100644 index d9966b74..00000000 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Tag.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; - -namespace ConferenceDTO -{ - public class Tag - { - public int ID { get; set; } - - [Required] - [StringLength(32)] - public string Name { get; set; } - } -} \ No newline at end of file diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Track.cs b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Track.cs index 773e6281..c18691f1 100644 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Track.cs +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferenceDTO/Track.cs @@ -6,10 +6,7 @@ namespace ConferenceDTO { public class Track { - public int TrackID { get; set; } - - [Required] - public int ConferenceID { get; set; } + public int Id { get; set; } [Required] [StringLength(200)] diff --git a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferencePlanner.sln b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferencePlanner.sln index 7afa0557..eb7e6477 100644 --- a/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferencePlanner.sln +++ b/save-points/2a-Refactor-to-ConferenceDTO/ConferencePlanner/ConferencePlanner.sln @@ -1,11 +1,11 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.329 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29007.179 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackEnd", "BackEnd\BackEnd.csproj", "{E7864CB1-70EF-4BDE-95D7-6078DE7F1F13}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackEnd", "BackEnd\BackEnd.csproj", "{54B73C40-8060-4718-A682-5A1C32C1E83A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConferenceDTO", "ConferenceDTO\ConferenceDTO.csproj", "{49122DB1-E07B-47E4-B855-9FF6B8BD4DCC}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConferenceDTO", "ConferenceDTO\ConferenceDTO.csproj", "{B88921B6-460D-4B9B-A3EB-431AA1A2347B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -13,19 +13,19 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E7864CB1-70EF-4BDE-95D7-6078DE7F1F13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E7864CB1-70EF-4BDE-95D7-6078DE7F1F13}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E7864CB1-70EF-4BDE-95D7-6078DE7F1F13}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E7864CB1-70EF-4BDE-95D7-6078DE7F1F13}.Release|Any CPU.Build.0 = Release|Any CPU - {49122DB1-E07B-47E4-B855-9FF6B8BD4DCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {49122DB1-E07B-47E4-B855-9FF6B8BD4DCC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {49122DB1-E07B-47E4-B855-9FF6B8BD4DCC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {49122DB1-E07B-47E4-B855-9FF6B8BD4DCC}.Release|Any CPU.Build.0 = Release|Any CPU + {54B73C40-8060-4718-A682-5A1C32C1E83A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {54B73C40-8060-4718-A682-5A1C32C1E83A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {54B73C40-8060-4718-A682-5A1C32C1E83A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {54B73C40-8060-4718-A682-5A1C32C1E83A}.Release|Any CPU.Build.0 = Release|Any CPU + {B88921B6-460D-4B9B-A3EB-431AA1A2347B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B88921B6-460D-4B9B-A3EB-431AA1A2347B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B88921B6-460D-4B9B-A3EB-431AA1A2347B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B88921B6-460D-4B9B-A3EB-431AA1A2347B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {716BD0AE-1BA1-4372-B4C1-BFE9CFA5FA18} + SolutionGuid = {7C5D815A-7FB9-4BB2-962E-F66EC67114A4} EndGlobalSection EndGlobal From 51c8e7efa6f7144804f3c84842c3eec4c08d97e9 Mon Sep 17 00:00:00 2001 From: David Fowler Date: Sun, 16 Jun 2019 21:39:54 -0700 Subject: [PATCH 42/56] Added more save points --- .../ConferencePlanner/BackEnd/BackEnd.csproj | 26 +- .../Controllers/AttendeesController.cs | 50 +- .../Controllers/ConferencesController.cs | 146 - .../BackEnd/Controllers/SearchController.cs | 58 +- .../BackEnd/Controllers/SessionsController.cs | 85 +- .../BackEnd/Controllers/SpeakersController.cs | 98 +- .../BackEnd/Data/ApplicationDbContext.cs | 31 +- .../BackEnd/Data/Attendee.cs | 2 - .../BackEnd/Data/Conference.cs | 17 - .../BackEnd/Data/ConferenceAttendee.cs | 18 - .../BackEnd/Data/DataLoader.cs | 2 +- .../BackEnd/Data/DevIntersectionLoader.cs | 7 +- .../Import/DevIntersection_Vegas_2017.json | 1871 ---- .../BackEnd/Data/Import/NDC_London_2019.json | 8119 ----------------- .../BackEnd/Data/Import/NDC_Sydney_2018.json | Bin 1158566 -> 0 bytes .../ConferencePlanner/BackEnd/Data/Session.cs | 6 +- .../BackEnd/Data/SessionAttendee.cs | 6 +- .../BackEnd/Data/SessionSpeaker.cs | 1 + .../BackEnd/Data/SessionTag.cs | 18 - .../BackEnd/Data/SessionizeLoader.cs | 21 +- .../ConferencePlanner/BackEnd/Data/Tag.cs | 9 - .../ConferencePlanner/BackEnd/Data/Track.cs | 3 - .../Infrastructure/EntityExtensions.cs | 40 +- .../Migrations/20190128064407_Refactor.cs | 281 - ....cs => 20190614215301_Initial.Designer.cs} | 8 +- ...9_Initial.cs => 20190614215301_Initial.cs} | 4 +- ...cs => 20190614225827_Refactor.Designer.cs} | 172 +- .../Migrations/20190614225827_Refactor.cs | 151 + .../ApplicationDbContextModelSnapshot.cs | 170 +- .../ConferencePlanner/BackEnd/Program.cs | 16 +- .../BackEnd/Properties/launchSettings.json | 30 - .../ConferencePlanner/BackEnd/Startup.cs | 41 +- .../BackEnd/appsettings.json | 14 +- .../ConferenceDTO/Attendee.cs | 2 +- .../ConferenceDTO/AttendeeResponse.cs | 2 - .../ConferenceDTO/Conference.cs | 16 - .../ConferenceDTO/ConferenceDTO.csproj | 5 +- .../ConferenceDTO/ConferenceResponse.cs | 15 - .../ConferenceDTO/SearchResult.cs | 8 +- .../ConferenceDTO/Session.cs | 5 +- .../ConferenceDTO/SessionResponse.cs | 4 +- .../ConferenceDTO/Speaker.cs | 4 +- .../ConferenceDTO/SpeakerResponse.cs | 2 +- .../ConferencePlanner/ConferenceDTO/Tag.cs | 14 - .../ConferenceDTO/TagResponse.cs | 11 - .../ConferencePlanner/ConferenceDTO/Track.cs | 5 +- .../ConferenceDTO/TrackResponse.cs | 13 - .../ConferencePlanner/ConferencePlanner.sln | 36 +- .../FrontEnd/FrontEnd.csproj | 20 +- .../FrontEnd/Pages/Error.cshtml.cs | 7 + .../FrontEnd/Pages/Index.cshtml | 6 +- .../FrontEnd/Pages/Index.cshtml.cs | 13 +- .../FrontEnd/Pages/Privacy.cshtml.cs | 9 +- .../FrontEnd/Pages/Search.cshtml | 22 +- .../FrontEnd/Pages/Search.cshtml.cs | 18 +- .../FrontEnd/Pages/Session.cshtml | 19 +- .../FrontEnd/Pages/Session.cshtml.cs | 17 +- .../Pages/Shared/_CookieConsentPartial.cshtml | 25 - .../FrontEnd/Pages/Shared/_Layout.cshtml | 38 +- .../Shared/_ValidationScriptsPartial.cshtml | 20 +- .../FrontEnd/Pages/Speaker.cshtml | 6 +- .../FrontEnd/Pages/Speaker.cshtml.cs | 4 +- .../ConferencePlanner/FrontEnd/Program.cs | 16 +- .../FrontEnd/Properties/launchSettings.json | 27 - .../FrontEnd/Services/ApiClient.cs | 2 +- .../ConferencePlanner/FrontEnd/Startup.cs | 27 +- .../FrontEnd/appsettings.json | 8 +- .../FrontEnd/wwwroot/css/site.css | 19 +- .../lib/bootstrap/dist/css/bootstrap-grid.css | 1833 +++- .../bootstrap/dist/css/bootstrap-grid.css.map | 2 +- .../bootstrap/dist/css/bootstrap-grid.min.css | 8 +- .../dist/css/bootstrap-grid.min.css.map | 2 +- .../bootstrap/dist/css/bootstrap-reboot.css | 36 +- .../dist/css/bootstrap-reboot.css.map | 2 +- .../dist/css/bootstrap-reboot.min.css | 8 +- .../dist/css/bootstrap-reboot.min.css.map | 2 +- .../lib/bootstrap/dist/css/bootstrap.css | 1906 +++- .../lib/bootstrap/dist/css/bootstrap.css.map | 2 +- .../lib/bootstrap/dist/css/bootstrap.min.css | 8 +- .../bootstrap/dist/css/bootstrap.min.css.map | 2 +- .../lib/bootstrap/dist/js/bootstrap.bundle.js | 6662 +++++++------- .../bootstrap/dist/js/bootstrap.bundle.js.map | 2 +- .../bootstrap/dist/js/bootstrap.bundle.min.js | 6 +- .../dist/js/bootstrap.bundle.min.js.map | 2 +- .../lib/bootstrap/dist/js/bootstrap.js | 6475 +++++++------ .../lib/bootstrap/dist/js/bootstrap.js.map | 2 +- .../lib/bootstrap/dist/js/bootstrap.min.js | 6 +- .../bootstrap/dist/js/bootstrap.min.js.map | 2 +- 88 files changed, 11007 insertions(+), 17947 deletions(-) delete mode 100644 save-points/3-Front-End-started/ConferencePlanner/BackEnd/Controllers/ConferencesController.cs delete mode 100644 save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Conference.cs delete mode 100644 save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/ConferenceAttendee.cs delete mode 100644 save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Import/DevIntersection_Vegas_2017.json delete mode 100644 save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Import/NDC_London_2019.json delete mode 100644 save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Import/NDC_Sydney_2018.json delete mode 100644 save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/SessionTag.cs delete mode 100644 save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Tag.cs delete mode 100644 save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190128064407_Refactor.cs rename save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/{20190128054119_Initial.Designer.cs => 20190614215301_Initial.Designer.cs} (87%) rename save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/{20190128054119_Initial.cs => 20190614215301_Initial.cs} (89%) rename save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/{20190128064407_Refactor.Designer.cs => 20190614225827_Refactor.Designer.cs} (51%) create mode 100644 save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190614225827_Refactor.cs delete mode 100644 save-points/3-Front-End-started/ConferencePlanner/BackEnd/Properties/launchSettings.json delete mode 100644 save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Conference.cs delete mode 100644 save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/ConferenceResponse.cs delete mode 100644 save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Tag.cs delete mode 100644 save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/TagResponse.cs delete mode 100644 save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/TrackResponse.cs delete mode 100644 save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Shared/_CookieConsentPartial.cshtml delete mode 100644 save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Properties/launchSettings.json diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/BackEnd.csproj b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/BackEnd.csproj index 9a61bce4..02be98f1 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/BackEnd.csproj +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/BackEnd.csproj @@ -1,18 +1,22 @@ - + - netcoreapp2.2 - InProcess - - + netcoreapp3.0 + - - - - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - + diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Controllers/AttendeesController.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Controllers/AttendeesController.cs index 1781d9a2..a844202b 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Controllers/AttendeesController.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Controllers/AttendeesController.cs @@ -7,25 +7,25 @@ using Microsoft.AspNetCore.Http; using ConferenceDTO; -namespace BackEnd +namespace BackEnd.Controllers { [Route("/api/[controller]")] [ApiController] public class AttendeesController : ControllerBase { - private readonly ApplicationDbContext _db; + private readonly ApplicationDbContext _context; - public AttendeesController(ApplicationDbContext db) + public AttendeesController(ApplicationDbContext context) { - _db = db; + _context = context; } - [HttpGet("{id}")] - public async Task> Get(string id) + [HttpGet("{username}")] + public async Task> Get(string username) { - var attendee = await _db.Attendees.Include(a => a.SessionsAttendees) + var attendee = await _context.Attendees.Include(a => a.SessionsAttendees) .ThenInclude(sa => sa.Session) - .SingleOrDefaultAsync(a => a.UserName == id); + .SingleOrDefaultAsync(a => a.UserName == username); if (attendee == null) { @@ -43,7 +43,7 @@ public async Task> Get(string id) public async Task> Post(ConferenceDTO.Attendee input) { // Check if the attendee already exists - var existingAttendee = await _db.Attendees + var existingAttendee = await _context.Attendees .Where(a => a.UserName == input.UserName) .FirstOrDefaultAsync(); @@ -60,25 +60,23 @@ public async Task> Post(ConferenceDTO.Attendee in EmailAddress = input.EmailAddress }; - _db.Attendees.Add(attendee); - await _db.SaveChangesAsync(); + _context.Attendees.Add(attendee); + await _context.SaveChangesAsync(); var result = attendee.MapAttendeeResponse(); - return CreatedAtAction(nameof(Get), new { id = result.UserName }, result); + return CreatedAtAction(nameof(Get), new { username = result.UserName }, result); } - [HttpPost("{username}/session/{sessionId:int}")] + [HttpPost("{username}/session/{sessionId}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesDefaultResponseType] public async Task> AddSession(string username, int sessionId) { - var attendee = await _db.Attendees.Include(a => a.SessionsAttendees) + var attendee = await _context.Attendees.Include(a => a.SessionsAttendees) .ThenInclude(sa => sa.Session) - .Include(a => a.ConferenceAttendees) - .ThenInclude(ca => ca.Conference) .SingleOrDefaultAsync(a => a.UserName == username); if (attendee == null) @@ -86,7 +84,7 @@ public async Task> AddSession(string username, in return NotFound(); } - var session = await _db.Sessions.FindAsync(sessionId); + var session = await _context.Sessions.FindAsync(sessionId); if (session == null) { @@ -95,25 +93,25 @@ public async Task> AddSession(string username, in attendee.SessionsAttendees.Add(new SessionAttendee { - AttendeeID = attendee.ID, - SessionID = sessionId + AttendeeId = attendee.Id, + SessionId = sessionId }); - await _db.SaveChangesAsync(); + await _context.SaveChangesAsync(); var result = attendee.MapAttendeeResponse(); return result; } - [HttpDelete("{username}/session/{sessionId:int}")] + [HttpDelete("{username}/session/{sessionId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesDefaultResponseType] public async Task RemoveSession(string username, int sessionId) { - var attendee = await _db.Attendees.Include(a => a.SessionsAttendees) + var attendee = await _context.Attendees.Include(a => a.SessionsAttendees) .SingleOrDefaultAsync(a => a.UserName == username); if (attendee == null) @@ -121,19 +119,19 @@ public async Task RemoveSession(string username, int sessionId) return NotFound(); } - var session = await _db.Sessions.FindAsync(sessionId); + var session = await _context.Sessions.FindAsync(sessionId); if (session == null) { return BadRequest(); } - var sessionAttendee = attendee.SessionsAttendees.FirstOrDefault(sa => sa.SessionID == sessionId); + var sessionAttendee = attendee.SessionsAttendees.FirstOrDefault(sa => sa.SessionId == sessionId); attendee.SessionsAttendees.Remove(sessionAttendee); - await _db.SaveChangesAsync(); + await _context.SaveChangesAsync(); return NoContent(); } } -} \ No newline at end of file +} diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Controllers/ConferencesController.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Controllers/ConferencesController.cs deleted file mode 100644 index ca26f68a..00000000 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Controllers/ConferencesController.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Threading.Tasks; -using BackEnd.Data; -using ConferenceDTO; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; - -namespace BackEnd.Controllers -{ - [Route("api/[controller]")] - [ApiController] - public class ConferencesController : ControllerBase - { - private readonly ApplicationDbContext _db; - - public ConferencesController(ApplicationDbContext db) - { - _db = db; - } - - [HttpGet] - public async Task>> GetConferences() - { - var conferences = await _db.Conferences.AsNoTracking().Select(s => new ConferenceResponse - { - ID = s.ID, - Name = s.Name - }) - .ToListAsync(); - - return conferences; - } - - [HttpGet("{id:int}")] - public async Task> GetConference(int id) - { - var conference = await _db.FindAsync(id); - - if (conference == null) - { - return NotFound(); - } - - var result = new ConferenceResponse - { - ID = conference.ID, - Name = conference.Name - }; - - return result; - } - - [HttpPost("upload")] - [Consumes("multipart/form-data")] - public async Task UploadConference([Required, FromForm]string conferenceName, [FromForm]ConferenceFormat format, IFormFile file) - { - var loader = GetLoader(format); - - using (var stream = file.OpenReadStream()) - { - await loader.LoadDataAsync(conferenceName, stream, _db); - } - - await _db.SaveChangesAsync(); - - return Ok(); - } - - [HttpPost] - public async Task> CreateConference(ConferenceDTO.Conference input) - { - var conference = new Data.Conference - { - Name = input.Name - }; - - _db.Conferences.Add(conference); - await _db.SaveChangesAsync(); - - var result = new ConferenceDTO.ConferenceResponse - { - ID = conference.ID, - Name = conference.Name - }; - - return CreatedAtAction(nameof(GetConference), new { id = conference.ID }, result); - } - - [HttpPut("{id:int}")] - public async Task PutConference(int id, ConferenceDTO.Conference input) - { - var conference = await _db.FindAsync(id); - - if (conference == null) - { - return NotFound(); - } - - conference.Name = input.Name; - - await _db.SaveChangesAsync(); - - return NoContent(); - } - - [HttpDelete("{id:int}")] - public async Task> DeleteConference(int id) - { - var conference = await _db.FindAsync(id); - - if (conference == null) - { - return NotFound(); - } - - _db.Remove(conference); - - await _db.SaveChangesAsync(); - - var result = new ConferenceDTO.ConferenceResponse - { - ID = conference.ID, - Name = conference.Name - }; - return result; - } - - private static DataLoader GetLoader(ConferenceFormat format) - { - if (format == ConferenceFormat.Sessionize) - { - return new SessionizeLoader(); - } - return new DevIntersectionLoader(); - } - - public enum ConferenceFormat - { - Sessionize, - DevIntersections - } - } -} diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Controllers/SearchController.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Controllers/SearchController.cs index ac2c7b70..abc3b6f9 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Controllers/SearchController.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Controllers/SearchController.cs @@ -6,60 +6,54 @@ using ConferenceDTO; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -using Newtonsoft.Json.Linq; namespace BackEnd.Controllers { [Route("api/[controller]")] - public class SearchController : Controller + [ApiController] + public class SearchController : ControllerBase { - private readonly ApplicationDbContext _db; + private readonly ApplicationDbContext _context; - public SearchController(ApplicationDbContext db) + public SearchController(ApplicationDbContext context) { - _db = db; + _context = context; } [HttpPost] - public async Task Search([FromBody] SearchTerm term) + public async Task>> Search(SearchTerm term) { var query = term.Query; - - var sessionResultsTask = _db.Sessions.AsNoTracking() - .Include(s => s.Track) - .Include(s => s.SessionSpeakers) - .ThenInclude(ss => ss.Speaker) - .Where(s => - s.Title.Contains(query) || - s.Track.Name.Contains(query) - ) - .ToListAsync(); - - var speakerResultsTask = _db.Speakers.AsNoTracking() - .Include(s => s.SessionSpeakers) - .ThenInclude(ss => ss.Session) - .Where(s => - s.Name.Contains(query) || - s.Bio.Contains(query) || - s.WebSite.Contains(query) - ) - .ToListAsync(); - - var sessionResults = await sessionResultsTask; - var speakerResults = await speakerResultsTask; + var sessionResults = await _context.Sessions.Include(s => s.Track) + .Include(s => s.SessionSpeakers) + .ThenInclude(ss => ss.Speaker) + .Where(s => + s.Title.Contains(query) || + s.Track.Name.Contains(query) + ) + .ToListAsync(); + + var speakerResults = await _context.Speakers.Include(s => s.SessionSpeakers) + .ThenInclude(ss => ss.Session) + .Where(s => + s.Name.Contains(query) || + s.Bio.Contains(query) || + s.WebSite.Contains(query) + ) + .ToListAsync(); var results = sessionResults.Select(s => new SearchResult { Type = SearchResultType.Session, - Value = JObject.FromObject(s.MapSessionResponse()) + Session = s.MapSessionResponse() }) .Concat(speakerResults.Select(s => new SearchResult { Type = SearchResultType.Speaker, - Value = JObject.FromObject(s.MapSpeakerResponse()) + Speaker = s.MapSpeakerResponse() })); - return Ok(results); + return results.ToList(); } } } \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Controllers/SessionsController.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Controllers/SessionsController.cs index 6b103b23..ffa252f9 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Controllers/SessionsController.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Controllers/SessionsController.cs @@ -1,11 +1,12 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; using BackEnd.Data; using ConferenceDTO; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; namespace BackEnd.Controllers { @@ -13,37 +14,33 @@ namespace BackEnd.Controllers [ApiController] public class SessionsController : Controller { - private readonly ApplicationDbContext _db; + private readonly ApplicationDbContext _context; - public SessionsController(ApplicationDbContext db) + public SessionsController(ApplicationDbContext context) { - _db = db; + _context = context; } [HttpGet] public async Task>> Get() { - var sessions = await _db.Sessions.AsNoTracking() + var sessions = await _context.Sessions.AsNoTracking() .Include(s => s.Track) .Include(s => s.SessionSpeakers) .ThenInclude(ss => ss.Speaker) - .Include(s => s.SessionTags) - .ThenInclude(st => st.Tag) .Select(m => m.MapSessionResponse()) .ToListAsync(); return sessions; } - [HttpGet("{id:int}")] + [HttpGet("{id}")] public async Task> Get(int id) { - var session = await _db.Sessions.AsNoTracking() + var session = await _context.Sessions.AsNoTracking() .Include(s => s.Track) .Include(s => s.SessionSpeakers) .ThenInclude(ss => ss.Speaker) - .Include(s => s.SessionTags) - .ThenInclude(st => st.Tag) - .SingleOrDefaultAsync(s => s.ID == id); + .SingleOrDefaultAsync(s => s.Id == id); if (session == null) { @@ -59,58 +56,88 @@ public async Task> Post(ConferenceDTO.Session inpu var session = new Data.Session { Title = input.Title, - ConferenceID = input.ConferenceID, StartTime = input.StartTime, EndTime = input.EndTime, Abstract = input.Abstract, TrackId = input.TrackId }; - _db.Sessions.Add(session); - await _db.SaveChangesAsync(); + _context.Sessions.Add(session); + await _context.SaveChangesAsync(); var result = session.MapSessionResponse(); - return CreatedAtAction(nameof(Get), new { id = result.ID }, result); + return CreatedAtAction(nameof(Get), new { id = result.Id }, result); } - [HttpPut("{id:int}")] + [HttpPut("{id}")] public async Task Put(int id, ConferenceDTO.Session input) { - var session = await _db.Sessions.FindAsync(id); + var session = await _context.Sessions.FindAsync(id); if (session == null) { return NotFound(); } - session.ID = input.ID; + session.Id = input.Id; session.Title = input.Title; session.Abstract = input.Abstract; session.StartTime = input.StartTime; session.EndTime = input.EndTime; session.TrackId = input.TrackId; - session.ConferenceID = input.ConferenceID; - await _db.SaveChangesAsync(); + await _context.SaveChangesAsync(); return NoContent(); } - [HttpDelete("{id:int}")] + [HttpDelete("{id}")] public async Task> Delete(int id) { - var session = await _db.Sessions.FindAsync(id); + var session = await _context.Sessions.FindAsync(id); if (session == null) { return NotFound(); } - _db.Sessions.Remove(session); - await _db.SaveChangesAsync(); + _context.Sessions.Remove(session); + await _context.SaveChangesAsync(); return session.MapSessionResponse(); } + + + [HttpPost("upload")] + [Consumes("multipart/form-data")] + public async Task Upload([FromForm]ConferenceFormat format, IFormFile file) + { + var loader = GetLoader(format); + + using (var stream = file.OpenReadStream()) + { + await loader.LoadDataAsync(stream, _context); + } + + await _context.SaveChangesAsync(); + + return Ok(); + } + + private static DataLoader GetLoader(ConferenceFormat format) + { + if (format == ConferenceFormat.Sessionize) + { + return new SessionizeLoader(); + } + return new DevIntersectionLoader(); + } + + public enum ConferenceFormat + { + Sessionize, + DevIntersections + } } -} \ No newline at end of file +} diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Controllers/SpeakersController.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Controllers/SpeakersController.cs index 639477ad..6e8829bb 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Controllers/SpeakersController.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Controllers/SpeakersController.cs @@ -1,12 +1,9 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using BackEnd.Data; -using ConferenceDTO; namespace BackEnd.Controllers { @@ -14,96 +11,39 @@ namespace BackEnd.Controllers [ApiController] public class SpeakersController : ControllerBase { - private readonly ApplicationDbContext _db; + private readonly ApplicationDbContext _context; - public SpeakersController(ApplicationDbContext db) + public SpeakersController(ApplicationDbContext context) { - _db = db; + _context = context; } + // GET: api/Speakers [HttpGet] - public async Task>> GetSpeakers() + public async Task>> GetSpeakers() { - var speakers = await _db.Speakers.AsNoTracking() - .Include(s => s.SessionSpeakers) - .ThenInclude(ss => ss.Session) - .Select(s => s.MapSpeakerResponse()) - .ToListAsync(); - + var speakers = await _context.Speakers.AsNoTracking() + .Include(s => s.SessionSpeakers) + .ThenInclude(ss => ss.Session) + .Select(s => s.MapSpeakerResponse()) + .ToListAsync(); return speakers; } - [HttpGet("{id:int}")] - public async Task> GetSpeaker(int id) + // GET: api/Speakers/5 + [HttpGet("{id}")] + public async Task> GetSpeaker(int id) { - var speaker = await _db.Speakers.AsNoTracking() - .Include(s => s.SessionSpeakers) - .ThenInclude(ss => ss.Session) - .SingleOrDefaultAsync(s => s.ID == id); - + var speaker = await _context.Speakers.AsNoTracking() + .Include(s => s.SessionSpeakers) + .ThenInclude(ss => ss.Session) + .SingleOrDefaultAsync(s => s.Id == id); if (speaker == null) { return NotFound(); } - var result = speaker.MapSpeakerResponse(); - return result; - } - - [HttpPost] - public async Task CreateSpeaker(ConferenceDTO.Speaker input) - { - var speaker = new Data.Speaker - { - Name = input.Name, - WebSite = input.WebSite, - Bio = input.Bio - }; - - _db.Speakers.Add(speaker); - await _db.SaveChangesAsync(); - - var result = speaker.MapSpeakerResponse(); - - return CreatedAtAction(nameof(GetSpeaker), new { id = speaker.ID }, result); - } - - [HttpPut("{id:int}")] - public async Task PutSpeaker(int id, ConferenceDTO.Speaker input) - { - var speaker = await _db.FindAsync(id); - - if (speaker == null) - { - return NotFound(); - } - - speaker.Name = input.Name; - speaker.WebSite = input.WebSite; - speaker.Bio = input.Bio; - - // TODO: Handle exceptions, e.g. concurrency - await _db.SaveChangesAsync(); - - return NoContent(); - } - - [HttpDelete("{id:int}")] - public async Task> DeleteSpeaker(int id) - { - var speaker = await _db.FindAsync(id); - - if (speaker == null) - { - return NotFound(); - } - - _db.Remove(speaker); - - // TODO: Handle exceptions, e.g. concurrency - await _db.SaveChangesAsync(); - return speaker.MapSpeakerResponse(); } } -} \ No newline at end of file +} diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/ApplicationDbContext.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/ApplicationDbContext.cs index 9d4a279f..975faec3 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/ApplicationDbContext.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/ApplicationDbContext.cs @@ -1,11 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Design; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.EntityFrameworkCore; namespace BackEnd.Data { @@ -20,38 +13,22 @@ public ApplicationDbContext(DbContextOptions options) protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity() - .HasIndex(a => a.UserName) - .IsUnique(); - - // Ignore the computed property - modelBuilder.Entity() - .Ignore(s => s.Duration); - - // Many-to-many: Conference <-> Attendee - modelBuilder.Entity() - .HasKey(ca => new { ca.ConferenceID, ca.AttendeeID }); + .HasIndex(a => a.UserName) + .IsUnique(); // Many-to-many: Session <-> Attendee modelBuilder.Entity() - .HasKey(ca => new { ca.SessionID, ca.AttendeeID }); + .HasKey(ca => new { ca.SessionId, ca.AttendeeId }); // Many-to-many: Speaker <-> Session modelBuilder.Entity() .HasKey(ss => new { ss.SessionId, ss.SpeakerId }); - - // Many-to-many: Session <-> Tag - modelBuilder.Entity() - .HasKey(st => new { st.SessionID, st.TagID }); } - public DbSet Conferences { get; set; } - public DbSet Sessions { get; set; } public DbSet Tracks { get; set; } - public DbSet Tags { get; set; } - public DbSet Speakers { get; set; } public DbSet Attendees { get; set; } diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Attendee.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Attendee.cs index 8a86b87d..18270157 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Attendee.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Attendee.cs @@ -5,8 +5,6 @@ namespace BackEnd.Data { public class Attendee : ConferenceDTO.Attendee { - public virtual ICollection ConferenceAttendees { get; set; } - public virtual ICollection SessionsAttendees { get; set; } } } \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Conference.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Conference.cs deleted file mode 100644 index 82612927..00000000 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Conference.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace BackEnd.Data -{ - public class Conference : ConferenceDTO.Conference - { - public virtual ICollection Tracks { get; set; } - - public virtual ICollection Speakers { get; set; } - - public virtual ICollection Sessions { get; set; } - - public virtual ICollection ConferenceAttendees { get; set; } - } -} \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/ConferenceAttendee.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/ConferenceAttendee.cs deleted file mode 100644 index 4e6877d1..00000000 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/ConferenceAttendee.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace BackEnd.Data -{ - public class ConferenceAttendee - { - public int ConferenceID { get; set; } - - public Conference Conference { get; set; } - - public int AttendeeID { get; set; } - - public Attendee Attendee { get; set; } - } -} \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/DataLoader.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/DataLoader.cs index 0b4eb353..589c1384 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/DataLoader.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/DataLoader.cs @@ -6,7 +6,7 @@ namespace BackEnd.Data { public abstract class DataLoader { - public abstract Task LoadDataAsync(string conferenceName, Stream fileStream, ApplicationDbContext db); + public abstract Task LoadDataAsync(Stream fileStream, ApplicationDbContext db); } } \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/DevIntersectionLoader.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/DevIntersectionLoader.cs index 9438fe3f..932b6ab3 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/DevIntersectionLoader.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/DevIntersectionLoader.cs @@ -10,12 +10,10 @@ namespace BackEnd { public class DevIntersectionLoader : DataLoader { - public override async Task LoadDataAsync(string conferenceName, Stream fileStream, ApplicationDbContext db) + public override async Task LoadDataAsync(Stream fileStream, ApplicationDbContext db) { var reader = new JsonTextReader(new StreamReader(fileStream)); - var conference = new Conference { Name = conferenceName }; - var speakerNames = new Dictionary(); var tracks = new Dictionary(); @@ -41,7 +39,7 @@ public override async Task LoadDataAsync(string conferenceName, Stream fileStrea { if (!tracks.ContainsKey(thisTrackName.Value())) { - var thisTrack = new Track { Name = thisTrackName.Value(), Conference = conference }; + var thisTrack = new Track { Name = thisTrackName.Value() }; db.Tracks.Add(thisTrack); tracks.Add(thisTrackName.Value(), thisTrack); } @@ -50,7 +48,6 @@ public override async Task LoadDataAsync(string conferenceName, Stream fileStrea var session = new Session { - Conference = conference, Title = item["title"].Value(), StartTime = item["startTime"].Value(), EndTime = item["endTime"].Value(), diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Import/DevIntersection_Vegas_2017.json b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Import/DevIntersection_Vegas_2017.json deleted file mode 100644 index 804cf596..00000000 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Import/DevIntersection_Vegas_2017.json +++ /dev/null @@ -1,1871 +0,0 @@ -[ - { - "_id": "595672306a83e8a414c21b62", - "ID": 2605, - "title": ".NET Code Style: Code your way in Visual Studio 2017", - "abstract": "Visual Studio 2017 allows teams and individuals to enforce and configure their own coding conventions. Come learn how you can help make your codebases consistent and readable and how you can control live code analysis to give you feedback when you want it. For those perfectionists out there, come learn how you can prevent people from checking-in code that doesn’t adhere to your team rules!", - "sessioncode": "VS32", - "eventName": "2017 Fall", - "sessionID": 2605, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS", "AB" ], - "tracks": [ "186", "190" ], - "speakerNames": [ "Kasey Uhlenhuth" ], - "speakers": [ "1470" ], - "__v": 0 - }, - { - "_id": "594c09edb6c6abf442787398", - "ID": 2527, - "sessioncode": "AP21", - "title": ".NET For Developers in 2017", - "abstract": "With the release of Visual Studio 2017 and Visual Studio for Mac as well as .NET Core 2.0 framework, a lot has changed in for the .NET frameworks and tools. In this demo-filled session, Scott will highlight the most important new features in the .NET frameworks, languages and tools that will make you a more productive developer in the year ahead.", - "eventName": "2017 Fall", - "sessionID": 2527, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "VS", "AB" ], - "tracks": [ "187", "186", "190" ], - "speakerNames": [ "Scott Hunter" ], - "speakers": [ "1248" ], - "__v": 1 - }, - { - "_id": "594c0aa4b6c6abf44278739c", - "ID": 2529, - "sessioncode": "AP22", - "title": ".NET Framework Improvements, Tips, and Tricks", - "abstract": "There’s a lot of talk about the .NET Core framework, but what about the .NET Framework for Windows? With the 4.7 release of .NET and the Windows 10 Creators Update, there are lots of improvements that you can use in your existing applications. Join Jeff Fritz as he demos many of the cool updates in the .NET Framework that you can use in your ASP.NET and windows applications.", - "eventName": "2017 Fall", - "sessionID": 2529, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB", "VS" ], - "tracks": [ "187", "190", "186" ], - "speakerNames": [ "Jeff Fritz" ], - "speakers": [ "1109" ], - "__v": 1 - }, - { - "_id": "594bde3db6c6abf44278738e", - "ID": 2523, - "sessioncode": "VS24", - "title": ".NET Standard: The Easy Route to Platform Independence", - "abstract": "Microsoft is moving to an Open Source and cross platform world, and they’ve created .NET Standard as a super-highway to get you there. With the .NET Standard 2.0 release, the specification includes most of the API’s you depend on in the .NET full framework (.NET 4.n). Because .NET Standard, .NET Core, Xamarin and UWP are all embracing this standard, your class libraries can be easily be cross platform. In this talk, you’ll learn more about the goals of .NET Standard and how it differs from PCLs (Portable Class Libraries). You’ll also see how to use the .NET Portability Analyzer to find any changes your app needs. To show that .NET Standard is not actual magic, you’ll learn a little about how redirects support binary compatibility. And, you’ll learn what happens when an API just doesn’t make sense on a particular platform and other potential pitfalls. You’ll leave this talk understanding why you care about .NET Standard and the path to move your applications to it.", - "eventName": "2017 Fall", - "sessionID": 2523, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-2T11:30", - "endTime": "2017-11-2T12:45", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS", "AB" ], - "tracks": [ "186", "190" ], - "speakerNames": [ "Kathleen Dollard" ], - "speakers": [ "1007" ], - "__v": 0 - }, - { - "_id": "59401b6fecc8333822007fb8", - "ID": 2449, - "sessioncode": "AP08", - "title": "5 Popular Choices for NoSQL on a Microsoft Platform", - "abstract": "If you are thinking of trying out a NoSQL document database, there are many good options available to Microsoft-oriented developers. In this session, we’ll compare some of the more popular databases, including: DocumentDb, Couchbase, MongoDb, CouchDb, and RavenDb. We’ll look at the strengths and weaknesses of each system. Querying, scaling, usability, speed, deployment, support and flexibility will all be covered. This session will include a discussion about when NoSQL is right for your project and give you an idea of which technology to pursue for your use case.", - "eventName": "2017 Fall", - "sessionID": 2449, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T10:00", - "endTime": "2017-10-31T11:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Matthew D. Groves" ], - "speakers": [ "1426" ], - "__v": 1 - }, - { - "_id": "59669972d57919680d73ff8c", - "ID": 2641, - "sessioncode": "AI01", - "title": "A lap around Microsoft Cognitive Services Vision APIs", - "abstract": "How would you like to learn how to leverage machine learning in countless Computer Vision use cases the easy way? Recently, Computer Vision Technologies have skyrocketed. Why? Machine Learning and a number of brilliant people working on Computer Vision.\n

    \nMachine Learning is currently a hot topic and holds a bold promise yet to be truly exploited. But, no matter what your level of understanding of Machine Learning is, we all can agree that it is a broad technology whose pioneers and leaders have a very specific expertise in. In other words, it just does not make sense for all developers to be experts in machine learning. It is more important for developers to understand how to leverage machine learning in your applications.\n

    \nThe Vision APIs of Microsoft Cognitive Services are easy to implement, free to prototype and inexpensive to scale in production. There is a rich set of services and a comprehensive SDK. And best of all the Vision APIs leverage billions of dollars spent in Microsoft Research and cloud infrastructure. \n

    \nThe Vision of Microsoft Cognitive Services (formerly Project Oxford) is for more personal computing experiences and enhanced productivity aided by systems that increasingly can see, hear, speak, understand and even begin to reason. \n

    \nMicrosoft Cognitive Services are a set of APIs, SDKs and services available to developers to make their applications more intelligent, engaging and discoverable. Microsoft Cognitive Services expands on Microsoft’s evolving portfolio of machine learning APIs and enables developers to easily add intelligent features – such as emotion and video detection; facial, speech and vision recognition; and speech and language understanding – into their applications. \n

    \nTake a lap around the features and functionality of the Microsoft Cognitive Services Vision APIs with Tim Huckaby to see how powerful these services are and how easy they are to implement in your own applications.", - "eventName": "2017 Fall", - "sessionID": 2641, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "AI", "VS", "AB" ], - "tracks": [ "193", "186", "190" ], - "speakerNames": [ "Tim Huckaby" ], - "speakers": [ "1013" ], - "__v": 0 - }, - { - "_id": "594023a9ecc8333822007fcf", - "ID": 2460, - "sessioncode": "AP17", - "title": "ASP.NET Web API Best Practices", - "abstract": "It seems like most web apps these days require at least some web APIs. This session covers best practices on designing, versioning, testing, and securing your ASP.NET Core Web APIs.", - "eventName": "2017 Fall", - "sessionID": 2460, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Steve Smith" ], - "speakers": [ "1262" ], - "__v": 0 - }, - { - "_id": "59cba742ea15de94182b625a", - "ID": 2730, - "sessioncode": "VS41", - "title": "AZURE DIAGNOSTICS: FIXING CLOUD APPLICATIONS ISSUES AND PERFORMANCE ON AZURE", - "abstract": "If you want to be 10x more efficient solving cloud reliability and performance issues, this session is for you. We’ll cover top issues we encounter in your application and infrastructure, and provide you with modern tools and techniques to effectively monitor, diagnose and fix these issues in all your environments, from dev-test to production at-scale. The session will cover our modern APM metrics and logging technology, Application Insights Profiler, and using the new Snapshot Debugger in production. Put on your seatbelts for this one!", - "eventName": "2017 Fall", - "sessionID": 2730, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-2T13:45", - "endTime": "2017-11-2T14:45", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "Azure", "VS" ], - "tracks": [ "191", "186" ], - "speakerNames": [ "Paul Yuknewicz" ], - "speakers": [ "1292" ], - "__v": 0 - }, - { - "_id": "59400871ecc8333822007f96", - "ID": 2432, - "sessioncode": "AP02", - "title": "Adding Realtime Features to Your Applications with SignalR", - "abstract": "Ever wondered how hard is to add real time eventing to your ASP.NET application? SignalR is a new library that makes bi-directional communication easy and fun. In this session we'll cover the features and approaches SignalR offers on both client and server sides. If you're interesting in adding real time eventing to your applications today, you don't want to miss this talk.", - "eventName": "2017 Fall", - "sessionID": 2432, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T10:15", - "endTime": "2017-10-31T11:30", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Javier Lozano" ], - "speakers": [ "1212" ], - "__v": 0 - }, - { - "_id": "59400fadecc8333822007fa2", - "ID": 2438, - "sessioncode": "AB01", - "title": "An Introduction to React", - "abstract": "\"Facebook's React library has received quite a bit of attention lately. In this session we will describe what React is, who uses it, and why it's a compelling technology to use.\nAfter a high level overview we will start to unpacking the ins and outs of React components (creation/JSX/props/state/etc) and then discuss some of the gotchas when first starting development.

    \n\"\"My favorite part of React is what I loved about MooTools: to use it effectively you learn JavaScript, not a DSL: useful your whole career.\"\" --Ryan Florence\nReact by itself is fairly small and not overly complex. For a more comprehensive Single Page Application you need much more than just React. To address this concern we will discuss Facebook Flux architecture, introduce the concept of Isomorphic JavaScript, and identify other libraries that are common when building a full application.\"", - "eventName": "2017 Fall", - "sessionID": 2438, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T10:00", - "endTime": "2017-10-31T11:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "AB", "ASP" ], - "tracks": [ "190", "187" ], - "speakerNames": [ "Elijah Manor" ], - "speakers": [ "1075" ], - "__v": 0 - }, - { - "_id": "594cf87fb6c6abf4427873aa", - "ID": 2535, - "sessioncode": "VS26", - "title": "And Now, EF Core 2!", - "abstract": "Entity Framework Core is rapidly evolving and EF Core 2.0 brings a slew of important new capabilities, improvements and additional parity with features you relied on in EF6. Julie Lerman, one of the most trusted authorities on Entity Framework, will give you a tour through features you really shouldn't miss as you plan the data access for software you are building. You may discover that EF Core is ready for your solutions.", - "eventName": "2017 Fall", - "sessionID": 2535, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T10:00", - "endTime": "2017-11-1T11:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS", "ASP", "AB" ], - "tracks": [ "186", "187", "190" ], - "speakerNames": [ "Julie Lerman" ], - "speakers": [ "1045" ], - "__v": 0 - }, - { - "_id": "59401f36ecc8333822007fc3", - "ID": 2454, - "sessioncode": "AP12", - "title": "Angular Applications with ASP.NET Core: Part 1 - Getting Started", - "abstract": "Want to find out more about using Angular and ASP.NET Core together? In this talk Rick gives an introduction to Angular and what you need to get started from scratch and how to also set up an ASP.NET Core application and run it as a backend for the Angular front end. This talk goes through the basics of setting up an Angular application with Angular CLI, creating a few starter components and accessing remote data. For the ASP.NET Core bits Rick demonstrates how to create a new project, run and debug the application both from the command line and using Visual Studio. This talk focuses on the fundamentals to get you started with these two technologies in combination. Part 2 covers a more realistic example and best practices for creating Angular applications with ASP.NET Core.", - "eventName": "2017 Fall", - "sessionID": 2454, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Rick Strahl" ], - "speakers": [ "1438" ], - "__v": 0 - }, - { - "_id": "59401f74ecc8333822007fc5", - "ID": 2455, - "sessioncode": "AP13", - "title": "Angular Applications with ASP.NET Core: Part 2 - Putting it all together", - "abstract": "This talk builds on the basic concepts of Part 1 by creating a more involved Angular application using ASP.NET Core as a backend. In this session we'll look at separating application concerns cleanly both in Angular and in ASP.NET, and setting up your project for easy development of both technologies. Rick describes some of the best practices for setting up your ASP.NET Core and Angular projects, adding important core features like CORS support, authentication and application caching and demonstrates how to run your Angular and ASP.NET Core app on Windows and Linux, and deploying the application to IIS on Windows and on Linux with Docker.", - "eventName": "2017 Fall", - "sessionID": 2455, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Rick Strahl" ], - "speakers": [ "1438" ], - "__v": 0 - }, - { - "_id": "59512a896a83e8a414c21aca", - "ID": 2542, - "sessioncode": "AB13", - "title": "Angular Dynamic Pages", - "abstract": "The Angular pages you know have static layout, fully described by their component templates.\n

    \nIn Angular, a component template and its class are inseparable, compiled into a single execution unit during the build. It's hard to imagine an Angular application that generates layout dynamically from data-driven logic. Can it be done?\n

    \nIt is done! This session shows how the official angular.io docs open-source, Angular documentation viewer dynamically generates each document page from a blend of HTML content and Angular components​. The documentation viewer itself has no idea what these pages look like.\n

    \nThe components embedded in HTML content come from a widget toolbox. We'll leverage this idea in a dashboard example app in which users drag-and-drop panels from a dashboard toolbox onto their personalized dashboard canvas. We'll look at using lazy loading to manage the toolbox and keep the initial dashboard light.", - "eventName": "2017 Fall", - "sessionID": 2542, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-2T10:00", - "endTime": "2017-11-2T11:15", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "AB", "ASP" ], - "tracks": [ "190", "187" ], - "speakerNames": [ "Ward Bell" ], - "speakers": [ "1107" ], - "__v": 0 - }, - { - "_id": "59401065ecc8333822007fa4", - "ID": 2439, - "title": "Angular in 60ish Minutes", - "sessioncode": "AB02", - "abstract": "\"Angular provides a robust new way to build Single Page Applications (SPAs) that can run on a variety of devices. With the framework adding many new features ranging from ES6 and TypeScript support to a more efficient way to bind data, there's a lot of new concepts to learn. In this session, you’ll learn about core features and concepts such as data binding, components, directives, using ES6/TypeScript languages, decorators and more. If you’re interested in getting a jump start on the Angular 2 framework then this session is for you!\n

    \n1. Get a jump start on the TypeScript language.
    \n2. Learn about the role of components in Angular apps.
    \n3. Understand key new features that Angular provides and how they can be used in SPAs.\"", - "eventName": "2017 Fall", - "sessionID": 2439, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "AB", "ASP" ], - "tracks": [ "190", "187" ], - "speakerNames": [ "Dan Wahlin" ], - "speakers": [ "1022" ], - "__v": 0 - }, - { - "_id": "594d86db0d45f50435e597ad", - "ID": 2539, - "sessioncode": "AP25", - "title": "Artificial Intelligence for the Impatient Developer", - "abstract": "Curious how Machine Learning, Cortana, the Bot Framework and the Cognitive Services fits into the overall architecture of an Azure Solution? Machine Learning usually does not stand by itself in the solution…whether you are using as Azure ML as the foundation for a data mining effort, using it as web service to inform automated processes or simply employing ML directly to realize new, untapped values in your data, Azure ML sits as an important and integrated component of your solution architecture. New services such as those provided with Microsoft Cognitive Services speed your development time by providing you with sophisticated, fully trained models for performing speech, text, vision and recommendation functions with the east of integrating a REST API, and along with Cortana and the Bot framework can yield richer and deeper interactive user experiences than was possible without having a specialized team huge development budgets. Learn to bring intelligence to your solutions by attending this session!", - "eventName": "2017 Fall", - "sessionID": 2539, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "Azure", "VS", "AB", "AI" ], - "tracks": [ "191", "186", "190", "193" ], - "speakerNames": [ "Zoiner Tejada" ], - "speakers": [ "1012" ], - "__v": 1 - }, - { - "_id": "59401c44ecc8333822007fbc", - "ID": 2451, - "sessioncode": "AP07", - "title": "Automated Delivery for .NET Applications", - "abstract": "Implementing an automated delivery process for your applications could seem like daunting, complicated task. In this session, we will cover how you can create build and deploy process that will help you streamline delivery and most importantly, make things predictable. If you're currently in the process of setting up a delivery process for your applications, you'll want to attend this sessions and participate in the conversation!", - "eventName": "2017 Fall", - "sessionID": 2451, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T13:30", - "endTime": "2017-11-1T14:30", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Javier Lozano" ], - "speakers": [ "1212" ], - "__v": 0 - }, - { - "_id": "59cbc9b4ea15de94182b629d", - "ID": 2735, - "sessioncode": "AI06", - "title": "Azure Bot Service Overview", - "abstract": "The Azure Bot Service enables you build, connect, test, and deploy intelligent bots. Bots are apps that users interact with in a conversational way. Bots can communicate conversationally with text, cards, or speech. Bots can leverage Microsoft Cognitive Services to provide advanced AI capabilities around vision, speech, language, and knowledge. Bots can connect with users on over a dozen different messaging applications such as Skype or Facebook Messenger. Bots can extend intelligent agents such as Cortana with new skills. In this session, you will learn about all the new capabilities of the Azure Bot Service and learn how to build intelligent bots.", - "eventName": "2017 Fall", - "sessionID": 2735, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-2T13:45", - "endTime": "2017-11-2T14:45", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "AI", "Azure" ], - "tracks": [ "193", "191" ], - "speakerNames": [ "Paul Stubbs" ], - "speakers": [ "1509" ], - "__v": 0 - }, - { - "_id": "59404bcb672304ec08c13cb0", - "ID": 2475, - "sessioncode": "VS15", - "title": "Azure IoT Edge in the Real World", - "abstract": "Microsoft has been a leader in cloud based IoT services for a number of years. The heart of Azure’s IoT offering is IoT Hubs. IoT Hubs provide a secure bidirectional communication service with devices in the field using standard protocols like HTTPS, AMQPS, and MQTTS. The open standards make it possible for many but not ALL devices in the field to communicate directly with IoT Hubs. For devices that don’t have TCP/IP connectivity but may have Bluetooth, RF, or other communication capabilities a gateway device is needed. In this session we’ll see how Azure IoT Edge (formerly the Azure IoT Gateway SDK) can be used to connect “edge” devices in the field to Azure IoT Hubs as well as how to move some of the analytics and filtering to the edge helping to reduce latency, bandwidth and costs when a roundtrip to the cloud can be avoided.", - "eventName": "2017 Fall", - "sessionID": 2475, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-2T11:30", - "endTime": "2017-11-2T12:45", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS", "Azure" ], - "tracks": [ "186", "191" ], - "speakerNames": [ "Bret Stateham" ], - "speakers": [ "1440" ], - "__v": 0 - }, - { - "_id": "59b6ce6aef10d7a0185d1abd", - "ID": 2672, - "sessioncode": "AP29", - "title": "Azure Search blended with AI: The key to Improving Customer’s Search Experience", - "abstract": "How to best serve customers and anticipate what they require even before they realize the need for it? By leveraging Microsoft’s AI capabilities smartly coupled with Azure Machine Learning processing power, now you can easily predict and recommend items your customers’ need by optimizing Azure Search content to improve your customers’ search experience.\n

    \nIn the session, we will talk about Azure Search powered by AI and a robust cloud infrastructure that can help you to learn from previous transactions and predict which items are more likely to be of interest to your customer, and how to coherently condense actionable information into conversational and easy-to-navigate answers. \n

    \nTake a quick peek around the beauty of Azure Search and AI to understand how it delivers value in a decoupled fashion.", - "eventName": "2017 Fall", - "sessionID": 2672, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T10:00", - "endTime": "2017-11-1T11:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Vineet Arora" ], - "speakers": [ "1338" ], - "__v": 0 - }, - { - "_id": "594009adecc8333822007f9a", - "ID": 2434, - "sessioncode": "AP04", - "title": "Azure for ASP.NET Developers", - "abstract": "Microsoft Azure is a simple, flexible, and open platform that makes developing Web applications extremely easy. In this session, we'll cover the features, practices, and patterns ASP.NET developers should consider when targeting the Azure platform. If you're curious on how you can take your applications, current and future, to the next level with ease, you won't want to miss this presentation.", - "eventName": "2017 Fall", - "sessionID": 2434, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T14:30", - "endTime": "2017-10-31T15:30", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Javier Lozano" ], - "speakers": [ "1212" ], - "__v": 0 - }, - { - "_id": "594029eaecc8333822007fd7", - "ID": 2464, - "sessioncode": "VS04", - "title": "Build Your First Xamarin App in 75 Minutes", - "abstract": "Xamarin enables C# developers to reuse their skills and build native mobile apps that run on iOS, Android and Windows. In this session, we will build a mobile app from scratch. You will see how to build the UI, handle navigation, connect to Azure, work with data when offline and how to deploy the app to multiple devices.", - "eventName": "2017 Fall", - "sessionID": 2464, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS" ], - "tracks": [ "186" ], - "speakerNames": [ "Robert Green" ], - "speakers": [ "1042" ], - "__v": 1 - }, - { - "_id": "59edea72a4cd12f41e1f3d22", - "ID": 2754, - "sessioncode": "AP30", - "title": "Build serverless apps on AWS with .NET Core and AWS Lambda", - "abstract": "Serverless architectures are revolutionizing how we delivering applications, but a scalable, high performance approach for .NET applications has been traditionally limited. With the introduction of .NET Core support on AWS Lambda, it is easier than ever to starting building. You can now deploy serveless .NET applications directly to AWS Lambda to support a variety of applications, from mobile backends to event processing to workflow systems to Alexa skills. This webinar will cover the latest innovations for AWS Lambda support for .NET Core and demo how to get started from within either Visual Studio, or VSTS.", - "eventName": "2017 Fall", - "sessionID": 2754, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "VS", "AB" ], - "tracks": [ "187", "186", "190" ], - "speakerNames": [ "Akhtar Hossain" ], - "speakers": [ "1515" ], - "__v": 0 - }, - { - "_id": "59a58c67ef10d7a0185d1a55", - "ID": 2668, - "sessioncode": "AP28", - "title": "Building ASP.NET apps on Google Cloud", - "abstract": "With high performance Virtual Machines (VM) and networking, blazing fast VM provisioning and autoscaling and a rich set of services, Google Cloud is a great platform to deploy and run your traditional ASP.NET and new containerised ASP.NET Core applications. In this session, we will cover:\n

    \n· How to run traditional Windows and SQL Server based ASP.NET apps on Compute Engine.
    \n· How to run the new Linux based containerised ASP.NET Core apps App Engine and Kubernetes/Container Engine.
    \n· How to integrate with Google Cloud services such as Cloud Storage and use machine learning APIs such as Vision API and Speech API.
    \n· How to use Google Cloud PowerShell cmdlets and Visual Studio extension to manage your projects.
    \n

    \nThis is your opportunity to learn about what Google Cloud offers for your ASP.NET app!", - "eventName": "2017 Fall", - "sessionID": 2668, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T11:15", - "endTime": "2017-11-1T12:15", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Mete Atamel" ], - "speakers": [ "1491" ], - "__v": 0 - }, - { - "_id": "594cf925b6c6abf4427873ae", - "ID": 2537, - "title": "Building Cross-Platform Server-Side Data APIs", - "abstract": "Front ends are cool but mostly useless without data. Sure, some of your data sources provide REST APIs so you can just write queries directly against them but that is so old school. Instead, you can build back end APIs that address the specific data needs of your web application and relieve front end devs from tangling with database schema, query syntax and other distractions. In this session you’ll learn the basics of creating a back end API to make moving data between your front end and your data store. We’ll use cross platform tools (dotnet and Visual Studio Code) and Azure CosmosDB’s document database to do the job.", - "sessioncode": "VS28", - "eventName": "2017 Fall", - "sessionID": 2537, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-2T13:45", - "endTime": "2017-11-2T14:45", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS", "ASP", "AB" ], - "tracks": [ "186", "187", "190" ], - "speakerNames": [ "Julie Lerman" ], - "speakers": [ "1045" ], - "__v": 0 - }, - { - "_id": "5940302becc8333822007fe3", - "ID": 2470, - "sessioncode": "VS10", - "title": "Building Enterprise Bots – Yes you can and should", - "abstract": "While many of the bots that you have seen can help you buy tickets to a movie, or book flights, or even add a mustache to a picture, bots can also be integrated into the enterprise. From bots that integrate with Jenkins to help you manage your build process, to handling first level support in a call center, conversation bots can be deployed in an enterprise in a very effective way. Let you users interact with systems in the communication channels they prefer (Facebook, Slack, Kik, Skype, email, sms) in one integrated solution. In this session we will show you how to utilize the BotFramework to build bots for your enterprise.", - "eventName": "2017 Fall", - "sessionID": 2470, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS" ], - "tracks": [ "186" ], - "speakerNames": [ "Daniel Egan" ], - "speakers": [ "1037" ], - "__v": 0 - }, - { - "_id": "594012dbecc8333822007fa6", - "ID": 2440, - "sessioncode": "AB03", - "title": "Building and Deploying Angular to Azure", - "abstract": "You did it! You wrote the code and the app works ... locally. But how will you get it to work in the cloud? We'll explore how to build Angular for optimal performance, push it to github, use CI tooling to perform custom builds, and host in Azure hitting serverless functions.", - "eventName": "2017 Fall", - "sessionID": 2440, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "AB", "ASP" ], - "tracks": [ "190", "187" ], - "speakerNames": [ "John Papa" ], - "speakers": [ "1002" ], - "__v": 0 - }, - { - "_id": "59402079ecc8333822007fc7", - "ID": 2456, - "sessioncode": "AP14", - "title": "Clean Architecture with ASP.NET Core", - "abstract": "ASP.NET Core provides better support for clean, testable, maintainable architectures than any of its predecessors. Learn how to create an ASP.NET project from scratch, and break it up into separate projects to maximize testability, maintainability, and modularization.", - "eventName": "2017 Fall", - "sessionID": 2456, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Steve Smith" ], - "speakers": [ "1262" ], - "__v": 0 - }, - { - "_id": "594d87450d45f50435e597af", - "ID": 2540, - "sessioncode": "AP26", - "title": "Creating Intelligent Bots", - "abstract": "Bots are powering a new way to converse and interact with users, whether you are ordering pizza with an emoji via text, remotely checking into your hotel room or searching for information. Bots can power both text based and voice activated conversations so users can leverage the mode most convenient to them. In this session we’ll take a journey building a solution that leverages Cortana, the Microsoft Bot Framework and Microsoft Cognitive services to make an application come alive to spoken and typed conversations.", - "eventName": "2017 Fall", - "sessionID": 2540, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "Azure", "VS", "AB", "AI" ], - "tracks": [ "191", "186", "190", "193" ], - "speakerNames": [ "Zoiner Tejada" ], - "speakers": [ "1012" ], - "__v": 1 - }, - { - "_id": "59402117ecc8333822007fc9", - "ID": 2457, - "sessioncode": "VS01", - "title": "Debugging Tips and Tricks with Microsoft Visual Studio", - "abstract": "Debugging an issue with an application is hard! In this session, we'll walk through all of the powerful debugging features that Visual Studio provides. We'll cover how to use breakpoints. Introduce data tips. Show you how you can share your debugging information. Work with the different debugging windows like Locals, Autos, and Watch. Then we'll look at ways we can follow or step through the code to find issues using the call stack and Intellitrace.", - "eventName": "2017 Fall", - "sessionID": 2457, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-2T11:30", - "endTime": "2017-11-2T12:45", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS", "AB" ], - "tracks": [ "186", "190" ], - "speakerNames": [ "Joe Guadagno" ], - "speakers": [ "1077" ], - "__v": 0 - }, - { - "_id": "59401633ecc8333822007fac", - "ID": 2443, - "sessioncode": "AB06", - "title": "Debugging in Node.js and Azure", - "abstract": "Debugging your application is a critical part of the development process and can aid in discovering why the application may be behaving differently than expected. Doing this using JavaScript server-side with Node.js can be quite elusive. In this session we'll talk about the typical hurdles developers run into while debugging and look at better ways to approach it. We'll go over the various techniques and tools that are available to help making debugging Node.js an easy task. We'll also see how we can remote debug an application running in Azure.", - "eventName": "2017 Fall", - "sessionID": 2443, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T11:15", - "endTime": "2017-11-1T12:15", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "AB", "ASP" ], - "tracks": [ "190", "187" ], - "speakerNames": [ "Brian Clark" ], - "speakers": [ "1372" ], - "__v": 0 - }, - { - "_id": "59cbbd40ea15de94182b6272", - "ID": 2731, - "sessioncode": "AI02", - "title": "Deep Dive – Predicting Subsurface Pump Failures", - "abstract": "This session will dive into the technical details (IoT, Machine Learning, AI) of how to actually predict abnormalities and failures in subsurface pumps early enough to prevent catastrophic issues with deep learning. We will begin with a 30,000 foot view of the problem from a use case perspective. We will then move into the architectural and technological component details and finally finish off with the gritty deep learning based machine learning details.", - "eventName": "2017 Fall", - "sessionID": 2731, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "AI", "VS", "Azure" ], - "tracks": [ "193", "186", "191" ], - "speakerNames": [ "David Crook" ], - "speakers": [ "1415" ], - "__v": 0 - }, - { - "_id": "59400f3aecc8333822007fa0", - "ID": 2437, - "sessioncode": "AP07", - "title": "Describing API Functionality using Swagger", - "abstract": "Understanding the capability of an API can be frustrating as a developer. Without good documentation, writing a consuming front-end application amounts to a lot guess work and loss of productive time. Using Swagger (OpenAPI Specification) is a fast way to self document, setup testing harnesses and lead to more productive development for your ASP.NET Web API and Azure Functions consuming apps.", - "eventName": "2017 Fall", - "sessionID": 2437, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T14:30", - "endTime": "2017-10-31T15:30", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Shayne Boyer" ], - "speakers": [ "1210" ], - "__v": 0 - }, - { - "_id": "5940241fecc8333822007fd1", - "ID": 2461, - "sessioncode": "AP18", - "title": "Discover the .NET Core CLI", - "abstract": "Tired of the full IDE Visual Studio Experience with all of the bells and whistles? What if you only had a bash terminal and an editor, could you create a .NET Core application? Come find out how to get this done like war games...\"Want to play a game?\"", - "eventName": "2017 Fall", - "sessionID": 2461, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-2T13:45", - "endTime": "2017-11-2T14:45", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Shayne Boyer" ], - "speakers": [ "1210" ], - "__v": 0 - }, - { - "_id": "59517e576a83e8a414c21b2f", - "ID": 2589, - "sessioncode": "AB14", - "title": "Docker Containers On Azure - let me count the ways", - "abstract": "Docker has made working with containers easy and therein enable many improvements to development workflow and application management. With Docker containers, you can build and test applications with confidence that they will more predictably run, anywhere. Azure provides many interesting options for container deployment including containerized Web Apps, Azure Container Instances, Azure Container Service and Service Fabric. This session will explore each of these options with some practical guidance alongside demos.", - "eventName": "2017 Fall", - "sessionID": 2589, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-2T11:30", - "endTime": "2017-11-2T12:45", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "Azure", "AB", "VS" ], - "tracks": [ "191", "190", "186" ], - "speakerNames": [ "Michele Leroux Bustamante" ], - "speakers": [ "1011" ], - "__v": 1 - }, - { - "_id": "59481f65b6c6abf442787325", - "ID": 2482, - "sessioncode": "VS19", - "title": "Dynamic Dashboards in XAML Applications", - "abstract": "The dynamic, compositional nature of XAML makes it a great platform for interfaces such as dashboards. But most app developers have not needed to use XAML for dynamic, pluggable UI, and don't know how to leverage the platform's capabilities in that area. This session will present a simple architecture for a dashboard that allows pluggable panels, with options for the user to select panels and determine their position. If your business users have been clamoring for a place to put important visual components in a customized arrangement for their jobs, this session can give you a large jumpstart.", - "eventName": "2017 Fall", - "sessionID": 2482, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS" ], - "tracks": [ "186" ], - "speakerNames": [ "Billy Hollis" ], - "speakers": [ "1209" ], - "__v": 0 - }, - { - "_id": "59512dbe6a83e8a414c21ace", - "ID": 2543, - "sessioncode": "AP27", - "title": "Entity Framework Core 2.0 – Data on server, cloud, mobile and more", - "abstract": "Entity Framework (EF) Core is a lightweight, extensible, and cross-platform version of the popular Entity Framework data access technology. In this demo filled session we’ll look at what’s new in EF Core and what the team has planned for upcoming releases.", - "eventName": "2017 Fall", - "sessionID": 2543, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Diego Vega", "Andrew Peters" ], - "speakers": [ "1460", "1461" ], - "__v": 0 - }, - { - "_id": "59401d79ecc8333822007fc0", - "ID": 2453, - "sessioncode": "AP11", - "title": "Exploring the Azure CLI", - "abstract": "Come check out the Azure CLI and see how to quickly get resources created, learn some cool scripting tricks, set defaults, automate deployments and more.", - "eventName": "2017 Fall", - "sessionID": 2453, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T10:15", - "endTime": "2017-10-31T11:30", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Shayne Boyer" ], - "speakers": [ "1210" ], - "__v": 0 - }, - { - "_id": "594c0a3ab6c6abf44278739a", - "ID": 2528, - "sessioncode": "VS29", - "title": "Faster, Smaller, Better - Visual Studio 2017", - "abstract": "Visual Studio 2017 is now available for developers, and it is packed with new features to help you. From improved web tools and new unit testing capabilities, to improved profiling and language features, Scott will show you all of the cool features that make developing with Visual Studio an amazing experience. You’ll learn tips and tricks that will help improve your applications immediately.", - "eventName": "2017 Fall", - "sessionID": 2528, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS", "AB" ], - "tracks": [ "186", "190" ], - "speakerNames": [ "Scott Hunter" ], - "speakers": [ "1248" ], - "__v": 0 - }, - { - "_id": "59765ca49a15452822634a19", - "ID": 2652, - "sessioncode": "VS35", - "title": "Flying High with Xamarin!", - "abstract": "Cross-platform mobile development has been democratized for .NET developers – thanks to Xamarin & Microsoft. Let’s build a cool aviation app together – targeting all platforms from the comforts of Visual Studio on Windows or Mac. Real world apps need cloud data connectivity, navigation, storage, lifecycle management, plugins and polished UI – let’s do all that. Let’s take a look at some must-have tooling for professional Xamarin developers. Let’s dip into device capabilities, reuse libraries and elevate the user experience. Oh, and we will throw in some passion for aviation in the app, like private jets and supersonic possibilities. Loads of fun while learning cutting-edge mobile development – you in?", - "eventName": "2017 Fall", - "sessionID": 2652, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS", "AB" ], - "tracks": [ "186", "190" ], - "speakerNames": [ "Sam Basu" ], - "speakers": [ "1480" ], - "__v": 0 - }, - { - "_id": "594008edecc8333822007f98", - "ID": 2433, - "sessioncode": "AP03", - "title": "Full Stack Development with .NET and NoSQL", - "abstract": "\"What is different about this generation of web applications? A solid development approach must consider latency, throughput, and interactivity demanded by users users across mobile devices, web browsers, and IoT. These applications often use NoSQL to support a flexible data model and easy scalability required for modern development.\n

    \nA full stack application (composed of Couchbase, WebAPI, Angular2, and ASP.NET/ASP.NET Core) will be demonstrated in this session. The individual parts of a stack may vary, but the overall design is the focus.\"", - "eventName": "2017 Fall", - "sessionID": 2433, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T11:45", - "endTime": "2017-10-31T13:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Matthew D. Groves" ], - "speakers": [ "1426" ], - "__v": 0 - }, - { - "_id": "594bddfbb6c6abf44278738c", - "ID": 2522, - "sessioncode": "VS23", - "title": "Functional Techniques for C#", - "abstract": "You are effective with the imperative, object oriented core of Java or .NET but you look longingly at the winsome smile of functional languages. If you play with your language’s functional features, never quite sure you’re getting it right or taking full advantage of them. This talk is for you. You’ll learn which code to attack with functional ideas and how to do it. You’ll look at code similar to what you write every day and see it transform from long difficult to follow code to short code that’s easy to understand, hard to mess up and straightforward to debug. Better yet, functional approaches ensure that patterns like async, logging and exception handling are consistent and transaction usage is clear. Apply these techniques while leveraging delegates, lambda expressions, base classes and generics.", - "eventName": "2017 Fall", - "sessionID": 2522, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T11:15", - "endTime": "2017-11-1T12:15", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS", "AB" ], - "tracks": [ "186", "190" ], - "speakerNames": [ "Kathleen Dollard" ], - "speakers": [ "1007" ], - "__v": 0 - }, - { - "_id": "59400a94ecc8333822007f9c", - "ID": 2435, - "sessioncode": "AP05", - "title": "Fundamentals of Test Driven Design", - "abstract": "In this session, you will learn how to create applications test-first using nUnit.", - "eventName": "2017 Fall", - "sessionID": 2435, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T15:45", - "endTime": "2017-10-31T16:45", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Jesse Liberty" ], - "speakers": [ "1134" ], - "__v": 0 - }, - { - "_id": "59ca447aea15de94182b6240", - "ID": 2726, - "abstract": "How easy is it to get .NET application to run in Azure? Do .NET applications run better in Azure, and how? In this talk we will walk through the unique enhancements we have built in to Azure for giving your .NET applications the best fit in the cloud. We’ll show you a fast path to get existing apps up on Azure. We’ll also show you how to build modern scalable cloud app patterns for Web App and worker microservices using Docker containers. We’ll also show you how to be incredibly productive building, monitoring and debugging your app using Visual Studio.", - "sessioncode": "VS37", - "title": "GETTING STARTED DEVELOPING .NET CLOUD APPLICATIONS ON AZURE USING VISUAL STUDIO", - "eventName": "2017 Fall", - "sessionID": 2726, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS", "Azure" ], - "tracks": [ "186", "191" ], - "speakerNames": [ "Paul Yuknewicz", "Andrew Hall" ], - "speakers": [ "1292", "1502" ], - "__v": 1 - }, - { - "_id": "59cba170ea15de94182b6252", - "ID": 2727, - "title": "GO SERVERLESS WITH AZURE FUNCTIONS", - "abstract": "You’ve heard the “serverless” buzzword, but do you know why it matters? In this session, you’ll learn about Azure Functions and how you can build applications more quickly than ever before. With Functions, you pay per execution, which can substantially lower your costs. The platform automatically scales up and down based on the number of incoming events. Serverless is useful for data transformation, cron processing, IoT, and even integrating with Office 365. In this session, we’ll describe the concepts behind serverless computing and show how easy it is to run Functions on your local machine. Using Visual Studio or Visual Studio Code, you can even debug and trigger on events in Azure. This demo-rich session will teach you how to create your own functions using our best-in-class tooling.", - "sessioncode": "VS38", - "eventName": "2017 Fall", - "sessionID": 2727, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "Azure", "VS" ], - "tracks": [ "191", "186" ], - "speakerNames": [ "Brian Clark" ], - "speakers": [ "1372" ], - "__v": 1 - }, - { - "_id": "594c153bb6c6abf4427873a0", - "ID": 2531, - "title": "Get Started ASP.NET Core 2.0", - "abstract": "Building high-performance cross-platform web applications has never been better than with ASP.NET Core. We will look at some of the new features of ASP.NET Core 2.0 and learn how our applications can benefit. We’ll also look at some performance tips and how you can take advantage of them.", - "sessioncode": "AP24", - "eventName": "2017 Fall", - "sessionID": 2531, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T10:00", - "endTime": "2017-11-1T11:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB", "VS" ], - "tracks": [ "187", "190", "186" ], - "speakerNames": [ "Maria Naggaga" ], - "speakers": [ "1489" ], - "__v": 2 - }, - { - "_id": "59402a62ecc8333822007fdb", - "ID": 2466, - "sessioncode": "VS06", - "title": "Get Started with Git", - "abstract": "Git is a free, open source distributed version control system. It is fast becoming the version control of choice for developers. In this session you will get familiar with Git and see to use it to manage code. You will learn about repos, committing changes, branching and merging, pull requests and more. You will see how to use Git with both GitHub and Visual Studio Team Services and see how to use Git with Visual Studio, as well as with Visual Studio Code and Visual Studio for Mac.", - "eventName": "2017 Fall", - "sessionID": 2466, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS" ], - "tracks": [ "186" ], - "speakerNames": [ "Robert Green" ], - "speakers": [ "1042" ], - "__v": 1 - }, - { - "_id": "59400eaaecc8333822007f9e", - "ID": 2436, - "sessioncode": "AP06", - "title": "Getting Starting with Ionic v3", - "abstract": "\"Ionic lets you build mobile apps using only JavaScript. The Ionic framework is a free and open source library of mobile-optimized HTML, CSS and JS components along with tools for building highly interactive native and progressive web apps. Built with Sass, optimized for AngularJS. \n

    \nIn this session, we'll introduce you to the Ionic Framework. We'll cover what the framework is, how you set up your development environment, what makes up the framework and the pieces of the framework. After this, you'll be well on your way to building your first mobile application with the Ionic Framework.\"", - "eventName": "2017 Fall", - "sessionID": 2436, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T11:45", - "endTime": "2017-10-31T13:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Joe Guadagno" ], - "speakers": [ "1077" ], - "__v": 0 - }, - { - "_id": "59401402ecc8333822007fa8", - "ID": 2441, - "sessioncode": "AB04", - "title": "Going Serverless With React", - "abstract": "In this session, we’ll walk through building a blog with React that is completely serverless. Serverless means that our blog will use hosted services, such as a database and a web application server. Serverless applications are fascinating since most of us have to worry about all the pieces of an application that we build, not just the user interface. Serverless doesn’t mean “no server”; it just means you don’t have to worry about that piece of your application anymore, and we’ll take a look at why that is a beautiful thing.", - "eventName": "2017 Fall", - "sessionID": 2441, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "AB", "ASP" ], - "tracks": [ "190", "187" ], - "speakerNames": [ "Burke Holland" ], - "speakers": [ "1290" ], - "__v": 0 - }, - { - "_id": "59482007b6c6abf442787327", - "ID": 2483, - "sessioncode": "VS20", - "title": "Good and Bad UX - Examples and Analysis", - "abstract": "We are surrounded by user experiences in web apps, native apps, mobile apps, ranging from good to mediocre to bad to rage inducing. In this session, Billy Hollis shows some of his favorite examples of user experiences all over that range, along with analysis of the principles and reasons why a UX works or doesn't. If you create screens for users, this session is a fun way to find out how to do it better and give you some solid ways to avoid bad UX.", - "eventName": "2017 Fall", - "sessionID": 2483, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T11:15", - "endTime": "2017-11-1T12:15", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS", "AB" ], - "tracks": [ "186", "190" ], - "speakerNames": [ "Billy Hollis" ], - "speakers": [ "1209" ], - "__v": 0 - }, - { - "_id": "59402d57ecc8333822007fdf", - "ID": 2468, - "sessioncode": "VS08", - "title": "HACK PROOFING YOUR MODERN WEB APPLICATIONS", - "abstract": "Secure your modern Web apps now. Developers are notoriously lax with including security in their applications. In an age of hacking, this talk aims to arm the developer with an arsenal of protections to use while developing. This presentation explores the most common attacks on Web applications, how they work to exploit your app, and most importantly, how to protect against them.", - "eventName": "2017 Fall", - "sessionID": 2468, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T10:00", - "endTime": "2017-11-1T11:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS" ], - "tracks": [ "186" ], - "speakerNames": [ "Adam Tuliper" ], - "speakers": [ "1179" ], - "__v": 0 - }, - { - "_id": "59cba6a2ea15de94182b6258", - "ID": 2729, - "sessioncode": "VS40", - "title": "HOW TO BUILD A MASSIVELY SCALABLE GLOBALLY DISTRIBUTED APP IN MINUTES WITH AZURE COSMOSDB", - "abstract": "Earlier this year, we announced Azure Cosmos DB - the first and only globally distributed, multi-model database system. In this session, we will show you how you can take advantage of Azure Cosmos DB as your backend database, covering data replication across any number of regions, scaling for any number of reads/writes, and much more.", - "eventName": "2017 Fall", - "sessionID": 2729, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-2T11:30", - "endTime": "2017-11-2T12:45", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "Azure", "VS" ], - "tracks": [ "191", "186" ], - "speakerNames": [ "Kirill Gavrylyuk" ], - "speakers": [ "1503" ], - "__v": 0 - }, - { - "_id": "594030d6ecc8333822007fe5", - "ID": 2471, - "sessioncode": "VS11", - "title": "Hello? Is it me you’re looking for(Face and Voice Recognition)", - "abstract": "Are there things you want to secure? A house, a business, and app? Why not do it with face an voice recognition. In this session, we will be using Azure Cognitive services Face and Voice recognition to authenticate and verify the person trying to gain access. Join the fun and see how you can add this to your own app.", - "eventName": "2017 Fall", - "sessionID": 2471, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-2T10:00", - "endTime": "2017-11-2T11:15", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS" ], - "tracks": [ "186" ], - "speakerNames": [ "Daniel Egan", "Adnan Masood" ], - "speakers": [ "1037", "1504" ], - "__v": 1 - }, - { - "_id": "59cbc896ea15de94182b6296", - "ID": 2732, - "sessioncode": "AI03", - "title": "HoloLens Reality Augmentation Using Image Recognition", - "abstract": "Say hello to the HoloLens! In this session we will explore the intersection of augmented reality on the HoloLens and the Microsoft Computer Vision API. We will begin by sharing our vision for the future, and the role that Microsoft Cognitive Services can play, in the growing area of augmented reality. Then, through a series of demos and shared code, you will see how to build from scratch a HoloLens application that recognizes any number of people, places, and things and superimposes information about them in the user’s field of view. \n

    \nComing out of this session, you will gain a better understanding of how Computer Vision API can enable augmented reality and write your own HoloLens application – no device required, works on the emulator!", - "eventName": "2017 Fall", - "sessionID": 2732, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "AI", "Azure", "VS" ], - "tracks": [ "193", "191", "186" ], - "speakerNames": [ "Robert Alexander", "Mario O. Bourgoin, PhD" ], - "speakers": [ "1505", "1506" ], - "__v": 0 - }, - { - "_id": "594028f1ecc8333822007fd3", - "ID": 2462, - "sessioncode": "VS02", - "title": "How Using DevOps Practices Can Make You a Better Developer", - "abstract": "Improved deployment frequency. Faster time to market. Lower failure rates. Faster fixes and recovery time. These are some of the promises of DevOps. Whether you are an individual developer or working in a team, you can take advantage of DevOps practices. In this session, aimed at developers who are new to DevOps, you'll see how you can leverage the concepts of agile development, continuous integration and continuous delivery to build better software. And you'll see how to do this all from within Visual Studio and Visual Studio Team Services.", - "eventName": "2017 Fall", - "sessionID": 2462, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS" ], - "tracks": [ "186" ], - "speakerNames": [ "Robert Green" ], - "speakers": [ "1042" ], - "__v": 0 - }, - { - "_id": "59669a6ed57919680d73ff8e", - "ID": 2642, - "sessioncode": "VS34", - "title": "Increasing productivity by moving Dev/Test to the Cloud", - "abstract": "Development and Test organizations should be spending their time developing, testing and shipping applications not managing and configuring infrastructure, diagnosis environment differences or waiting for resources to become available. In this session you'll see how Azure Dev/Test Labs provides the ability to quickly provision development and test environments across Linux and Windows, ensure consistency via shared artifacts and templates and minimize waste with quotas and policies.", - "eventName": "2017 Fall", - "sessionID": 2642, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-2T10:00", - "endTime": "2017-11-2T11:15", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS", "ASP", "AB", "Azure" ], - "tracks": [ "186", "187", "190", "191" ], - "speakerNames": [ "Jay Schmelzer" ], - "speakers": [ "1242" ], - "__v": 0 - }, - { - "_id": "594c1232b6c6abf44278739e", - "ID": 2530, - "sessioncode": "AP23", - "title": "Introducing RazorPages for ASP.NET Core 2.0", - "abstract": "ASP.NET Core 2.0 comes with the MVC framework that we are already familiar with, but you can also build your applications quickly and easily with the new RazorPages feature. RazorPages allow you to build your application by focusing on the markup and content, and adding server-side features easily. Join us and learn how to get started building a cross-platform application with RazorPages.", - "eventName": "2017 Fall", - "sessionID": 2530, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Jon Galloway" ], - "speakers": [ "1490" ], - "__v": 2 - }, - { - "_id": "594aca69b6c6abf442787379", - "ID": 2514, - "sessioncode": "AP20", - "title": "Introduction to IdentityServer for ASP.NET Core", - "abstract": "IdentityServer is a popular open source security token service framework written in ASP.NET Core that implements the OpenID Connect and OAuth2 protocols. It is used to authenticate users via single sign-on and to secure web APIs. It is designed for extensibility and customization and allows applications to satisfy their custom security requirements. It can be used stand-alone or in conjunction with other identity providers (such as Google, Facebook, AAD, ADFS, Auth0, and others). Come to this session to be introduced to the basics of using, hosting, and configuring IdentityServer to secure your applications.", - "eventName": "2017 Fall", - "sessionID": 2514, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T16:15", - "endTime": "2017-11-1T17:15", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Brock Allen" ], - "speakers": [ "1267" ], - "__v": 0 - }, - { - "_id": "594045ec672304ec08c13caa", - "ID": 2472, - "sessioncode": "VS12", - "title": "Introduction to the Microsoft CNTK Machine Learning Library", - "abstract": "The Microsoft CNTK machine learning library version 2.0 was released in 2017. CNTK allows developers to create powerful machine learning systems to make predictions. In this lively and informative session, Dr. James McCaffrey from Microsoft Research will explain exactly what the CNTK library is, and what CNTK can, and cannot, do. Topics covered include: installing CNTK v 2.0, creating deep neural network prediction models using CNTK, and integrating CNTK with other systems and applications. Join the artificial intelligence revolution with CNTK!", - "eventName": "2017 Fall", - "sessionID": 2472, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS", "AB", "AI" ], - "tracks": [ "186", "190", "193" ], - "speakerNames": [ "James McCaffrey" ], - "speakers": [ "1025" ], - "__v": 1 - }, - { - "_id": "59402fe3ecc8333822007fe1", - "ID": 2469, - "sessioncode": "VS09", - "title": "LESSONS LEARNED IN PORTING LEGACY ASP.NET APPLICATIONS TO ASP.NET CORE", - "abstract": "Are you looking to migrate any of your legacy ASP.NET applications to ASP.NET Core? Our team at Microsoft worked porting an application that consisted of several frameworks (SignalR, Entity Framework, Nancy, MVC, and custom middleware) to ASP.NET Core. We went in with little expectations and came out with many solid lessons learned. In this session, I’ll walk you through various items we ported and considerations and challenges we hit at each part. While our experience may be different based on the types of applications you are porting, this session should give you immediate insight into porting an application over to ASP.NET Core also running on .NET Core.", - "eventName": "2017 Fall", - "sessionID": 2469, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T11:15", - "endTime": "2017-11-1T12:15", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS" ], - "tracks": [ "186" ], - "speakerNames": [ "Adam Tuliper" ], - "speakers": [ "1179" ], - "__v": 0 - }, - { - "_id": "59404c1a672304ec08c13cb2", - "ID": 2476, - "sessioncode": "VS16", - "title": "Lessons Learned building a Real World Electron Application", - "abstract": "Electron is popular framework for creating cross-platform applications. Microsoft Visual Studio code is a great example of the rich types of applications that can be developed on top of Electron. In this session we’ll review the lessons we learned developing an Electron based application that helps IoT developers configure their Azure IoT Edge gateway solutions graphically. The application was developed with the intent to run on all popular desktop platforms (Windows, Mac and Linux) as well as to configure Azure IoT Edge installations on remote gateway devices. We’ll show you how far we got, what hurdles we encountered and tips and tricks learned in the trenches.", - "eventName": "2017 Fall", - "sessionID": 2476, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-2T13:45", - "endTime": "2017-11-2T14:45", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS" ], - "tracks": [ "186" ], - "speakerNames": [ "Bret Stateham" ], - "speakers": [ "1440" ], - "__v": 0 - }, - { - "_id": "59cd27d4ea15de94182b62b0", - "ID": 2736, - "sessioncode": "AI07", - "title": "Let’s talk about Conversation Design", - "abstract": "Conversational digital affordances are fast becoming a norm for users everywhere – from the office, to the kitchen; the car to the living room – we can type, tap or talk to all manner of devices, apps, bots and agents to do all manner of things. When designed well, conversational experiences are natural, intuitive and efficient. In this session, we’ll provide practical guidance for designing for conversation. We’ll cover best practices for creating a great conversationalist and we’ll put the guidance to work using the Bot Framework SDK, Cognitive Services such as LUIS.ai and QnAMaker.ai, and show you a preview of Bot Framework’s new visual Conversation Designer.", - "eventName": "2017 Fall", - "sessionID": 2736, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-2T10:00", - "endTime": "2017-11-2T11:15", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "AI", "Azure", "VS" ], - "tracks": [ "193", "191", "186" ], - "speakerNames": [ "Vishwac Sena Kannan" ], - "speakers": [ "1511" ], - "__v": 0 - }, - { - "_id": "59402280ecc8333822007fcb", - "ID": 2458, - "sessioncode": "AP15", - "title": "Localizing your ASP.NET Core Applications", - "abstract": "A lot has changed in ASP.NET Core localization as ASP.NET Core has completely overhauled the localization mechanism of classic ASP.NET. There's a brand new localization mechanism based on dependency injection and a convention based localization service that make it easier to add localization to your ASP.NET Core applications. In this session you find out the basic constructs of localization and how localization is managed at a low level in .NET and ASP.NET in general, as well as the native localization features that ASP.NET Core provides to abstract the low level features. We'll look at a number of different approaches you can use to localize your content as well as some useful tooling to help you localize your resources interactively", - "eventName": "2017 Fall", - "sessionID": 2458, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-2T13:45", - "endTime": "2017-11-2T14:45", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Rick Strahl" ], - "speakers": [ "1438" ], - "__v": 0 - }, - { - "_id": "59cba1fdea15de94182b6254", - "ID": 2728, - "sessioncode": "VS39", - "title": "MOVING APPLICATION DEVELOPMENT AND TESTING TO THE CLOUD", - "abstract": "Not every organization and application is ready to move to cloud for production for a variety of reasons. In this session we'll show you how organizations that have on-premise deployments are still able to take advantage of the cloud to create a productive and consistent environment for developing and testing their applications.", - "eventName": "2017 Fall", - "sessionID": 2728, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-2T10:00", - "endTime": "2017-11-2T11:15", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "Azure", "VS" ], - "tracks": [ "191", "186" ], - "speakerNames": [ "Jay Schmelzer", "Luca Bolognese" ], - "speakers": [ "1242", "1485" ], - "__v": 0 - }, - { - "_id": "594019bdecc8333822007fb2", - "ID": 2446, - "title": "Making CSS Fun with SASS", - "sessioncode": "AB09", - "abstract": "After years of back-and-forth debate, one CSS pre-processor has emerged as the clear winner: SASS (or Syntactically Awesome Style Sheets). With SASS, writing and maintaining CSS can actually be FUN, not tedious and error-prone. In this session, you’ll learn the basics of SASS and how it can be immediately applied to your projects for instant productivity and happiness gains. We’ll also take a look at the current state of modern CSS standards aiming to bring the power of SASS and other CSS preprocessors natively to browsers, examining what can and what can’t be used safely today.", - "eventName": "2017 Fall", - "sessionID": 2446, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T11:45", - "endTime": "2017-10-31T13:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "AB", "ASP" ], - "tracks": [ "190", "187" ], - "speakerNames": [ "Todd Anglin" ], - "speakers": [ "1019" ], - "__v": 0 - }, - { - "_id": "59402a27ecc8333822007fd9", - "ID": 2465, - "sessioncode": "VS05", - "title": "Managing Software Projects with Visual Studio Team Services", - "abstract": "Visual Studio Team Services (VSTS) provides tools for you to plan, build and ship software across a variety of platforms. In this session, you will see how to use VSTS to track work and manage your backlog with Agile planning tools. You will see how to use backlogs to keep track of work items, how to use Kanban boards to turn data into visual signboards, how to use scrum boards to help you run effective stand-ups, how all of your code changes are linked to the story, bug or task driving the work. In sum, you will see how to use VSTS to run your agile team.", - "eventName": "2017 Fall", - "sessionID": 2465, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS" ], - "tracks": [ "186" ], - "speakerNames": [ "Microsoft VS Team" ], - "speakers": [ "1243" ], - "__v": 0 - }, - { - "_id": "593710ec6ec71b3813ac45b0", - "ID": 2421, - "sessioncode": "AP01", - "title": "Microservices, Angular, ASP.NET Core and Docker", - "abstract": "Learn about how Microservices can help you build more agile applications that can handle change (in business rules and technologies) more easily.", - "eventName": "2017 Fall", - "sessionID": 2421, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T15:45", - "endTime": "2017-10-31T16:45", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "AB", "ASP" ], - "tracks": [ "190", "187" ], - "speakerNames": [ "Dan Wahlin" ], - "speakers": [ "1022" ], - "__v": 0 - }, - { - "_id": "594aca0ab6c6abf442787377", - "ID": 2513, - "sessioncode": "AP19", - "title": "Modern Security Architecture with OpenID Connect and OAuth2", - "abstract": "Modern applications require modern security and the OpenID Connect and OAuth2 security protocols are designed to meet this need. To achieve a modern security architecture you must use something called a “security token service” that implements these protocols. In this session we will look at how applications are now architected to incorporate and use a token service for authentication thus providing single sign-on. We will also see how this same token service also provides tokens for securing Web APIs. We will be using ASP.NET Core and the popular open source .NET framework “IdentityServer” to illustrate these concepts.", - "eventName": "2017 Fall", - "sessionID": 2513, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T11:15", - "endTime": "2017-11-1T12:15", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Brock Allen" ], - "speakers": [ "1267" ], - "__v": 0 - }, - { - "_id": "594014aaecc8333822007faa", - "ID": 2442, - "title": "React Patterns and Practices", - "sessioncode": "AB05", - "abstract": "Getting started with React doesn't take very long, but there are a variety of other patterns and practices that you, as a developer, will need to understand and tackle.\n

    \nAfter this session you will be exposed to the following concepts that are helpful when creating a large front-end React application:\n

    \n* Knowing the difference between Container and Presentational Components
    \n* Using High Order Components or Function as Children
    \n* Assessing Performance Bottlenecks
    \n* Integrating Immutability into your Application
    \n* Unit Testing your Components
    \n* Creating your own React pattern library
    ", - "eventName": "2017 Fall", - "sessionID": 2442, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T10:00", - "endTime": "2017-11-1T11:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "AB", "ASP" ], - "tracks": [ "190", "187" ], - "speakerNames": [ "Elijah Manor" ], - "speakers": [ "1075" ], - "__v": 0 - }, - { - "_id": "59517ea16a83e8a414c21b31", - "ID": 2590, - "title": "Rock Your Microservices Event Streaming Strategy with Azure Event Hubs", - "abstract": "Microservices are not for everyone, but there are some incredible benefits to employing microservice architecture principles to enable co-evolution of services and features and reduce friction during the DevOps cycle. The growth of moving parts, however, does require tight DevOps procedures, and visibility into system operations including diagnostics, application events and audit trail. Event streaming can enhance your solution enabling async processing and scale, but also enhancing visibility to the solution as a whole. The good news is that if you are already designing a solution based on microservice principles, you are already positioned to incorporate events with less pain. Services that \"fit in your head\" lead to a manageable approach to introducing event-based strategies. In this session you'll learn how to design a microservices solution that relies on event streams to produce workflow state, history and full audit. You'll see patterns for structuring your solutions, managing events and payloads, and producing full history and audit logs for the solution. Event streaming will be implemented with Azure Event Hubs to compliment a microservices solution hosted in Azure Container Service.", - "sessioncode": "AB16", - "eventName": "2017 Fall", - "sessionID": 2590, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T16:15", - "endTime": "2017-11-1T17:15", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "Azure", "AB", "VS" ], - "tracks": [ "191", "190", "186" ], - "speakerNames": [ "Michele Leroux Bustamante" ], - "speakers": [ "1011" ], - "__v": 0 - }, - { - "_id": "59512a436a83e8a414c21ac8", - "ID": 2541, - "sessioncode": "AB12", - "title": "RxJS Observables in Angular", - "abstract": "Client web applications are rich in events. Button clicks, keystrokes, and mouse moves are events. The data returned from an HTTP request arrives as an event. App components can send and receive messages through an event bus. Every page navigation is an event. Animations emit start and stop events. Events are everywhere.\n

    \nRxJS Observables are the preferred way to manage events in Angular applications and many Angular APIs return RxJS Observables. \n

    \nThis session covers the basics of RxJS observables for Angular developers. You'll learn how to work with Angular observable APIs, which RxJS operators you should know, and how to write your own observable APIs.​", - "eventName": "2017 Fall", - "sessionID": 2541, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T11:45", - "endTime": "2017-10-31T13:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "AB", "ASP" ], - "tracks": [ "190", "187" ], - "speakerNames": [ "Ward Bell" ], - "speakers": [ "1107" ], - "__v": 0 - }, - { - "_id": "594cf8c6b6c6abf4427873ac", - "ID": 2536, - "sessioncode": "VS27", - "title": "SQL Server Containers for Developers", - "abstract": "Thanks to Docker and Windows Containers, it's now possible to have a no-fuss, full SQL Server instance on your development, test or QA machine. You can use SQL Server for Linux in a Docker container on any platform that supports a Docker engine or SQL Server in Windows Containers. The containers allow you to instantly spin up one or more SQL Servers as needed and wipe them out then restart a clean instance when the time is right. This makes for a killer developer environment to have the full power of SQL Server without the fuss. It also is a boon for automated test environments where you need to run integration tests against SQL Server. This session will focus on using Docker to get, run and manage SQL Server for Linux instances. You'll also learn about persisting data and how to create and share an image with your own database already on it. Bonus lessons will include using command line SQL and the mssql extension for Visual Studio Code.", - "eventName": "2017 Fall", - "sessionID": 2536, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T15:00", - "endTime": "2017-11-1T16:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS", "ASP", "AB" ], - "tracks": [ "186", "187", "190" ], - "speakerNames": [ "Julie Lerman" ], - "speakers": [ "1045" ], - "__v": 0 - }, - { - "_id": "59401a17ecc8333822007fb4", - "ID": 2447, - "title": "Securing Angular and Node.js Apps in Azure", - "sessioncode": "AB10", - "abstract": "We all agree security is important, but did you know how easy it is to thwart some of the most common attacks? In this session we'll shed light on how secure application development practices can be easily overlooked. We'll learn the simple steps we can take to secure our web applications from the threat of dangerous vulnerabilities using Node.js, Express and Angular running in Azure. The best defense is a good offense. Learn to go on the offensive to protect your web apps in the cloud.", - "eventName": "2017 Fall", - "sessionID": 2447, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-2T13:45", - "endTime": "2017-11-2T14:45", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "AB", "ASP" ], - "tracks": [ "190", "187" ], - "speakerNames": [ "Brian Clark" ], - "speakers": [ "1372" ], - "__v": 0 - }, - { - "_id": "59481d61b6c6abf442787321", - "ID": 2480, - "title": "Software Project Design", - "abstract": "Much as the need to design the system, you must also design the project: from scheduling resources behind the services, the staffing distribution, examining the planned progress and even to validating your plan, and accommodating changes. This requires understanding the inner dependencies between services and activities, the critical path of integration, the available floats, and the risks involved. All of these challenges stem from your design and addressing them properly is a hard core engineering task – designing the project. In this intense session Juval Lowy shares his approach software project design, along with his unique insight for delivering software on schedule and budget. You will also see to deal with common misconceptions and typical roles and responsibilities in the team.", - "sessioncode": "VS17", - "eventName": "2017 Fall", - "sessionID": 2480, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T10:15", - "endTime": "2017-10-31T11:30", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS", "AB" ], - "tracks": [ "186", "190" ], - "speakerNames": [ "Juval Lowy" ], - "speakers": [ "1188" ], - "__v": 0 - }, - { - "_id": "594047fe672304ec08c13cac", - "ID": 2473, - "title": "Spinning Up Node.js for .NET Developers", - "abstract": "Most of us are familiar with .NET, but what’s this Node.js thing? Node.js is taking the world by storm and developers can no longer afford to avoid it entirely. So, maybe it’s time to at least get the concepts in mind and see what sort of value it can bring to your business. Who knows? You may even end up loving Node.js as much as I do.\n

    \nIn this session, I’ll very clearly describe the anatomy of Node.js itself and the anatomy of a Node.js project. I’ll do some concept mapping to .NET so you’ll understand it quickly.\n

    \nBesides sample code, I’ll speak to the massive and growing node community and I’ll show you some fun productivity shortcuts and tooling!\n

    \nIn this session you'll learn…

    \n• Anatomy Node.js and a Node.js project
    \n• When to use it. When not to.
    \n• Installing and using Node.js
    \n• The REPL
    \n• Hello world
    \n• Packages and modules
    \n• Node tooling FTW!
    ", - "sessioncode": "VS13", - "eventName": "2017 Fall", - "sessionID": 2473, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T13:30", - "endTime": "2017-11-1T14:30", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS" ], - "tracks": [ "186" ], - "speakerNames": [ "Jeremy Foster" ], - "speakers": [ "1439" ], - "__v": 0 - }, - { - "_id": "59cbc935ea15de94182b629b", - "ID": 2734, - "sessioncode": "AI05", - "title": "Surveying wildlife using machine learning", - "abstract": "Estimating population trends, detection of rare species, and impact assessment are just few things that are top of mind for biologists across the world. In this talk, an overview of wildlife monitoring projects that a team from Conservation Metrics and Microsoft is working on and what ML approaches they adopt will be discussed. The talk will dive deeper into the kittiwake birds detection task showing how Azure ML Workbench, The Microsoft Cognitive Toolkit and Tensorflow were used to accomplish that.", - "eventName": "2017 Fall", - "sessionID": 2734, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T11:15", - "endTime": "2017-11-1T12:15", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "AI", "Azure" ], - "tracks": [ "193", "191" ], - "speakerNames": [ "Olga Liakhovich" ], - "speakers": [ "1508" ], - "__v": 0 - }, - { - "_id": "5940168eecc8333822007fae", - "ID": 2444, - "sessioncode": "AB07", - "title": "The 7 D's of Development: Deliver with Confidence", - "abstract": "Are you done delivering that code? What is done? Are you confident it till stay up and running? Are you confident that the bug you fixed didn't break something else? Are you confident someone else could pick up your code and run with it? Writing code is the easy part, everything after it is the hard part. Following the 7 D's of development will help you deliver higher quality product and make you feel more confident about saying \"it's done\".", - "eventName": "2017 Fall", - "sessionID": 2444, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T13:30", - "endTime": "2017-11-1T14:30", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "AB", "ASP" ], - "tracks": [ "190", "187" ], - "speakerNames": [ "John Papa" ], - "speakers": [ "1002" ], - "__v": 0 - }, - { - "_id": "59b9714def10d7a0185d1af8", - "ID": 2673, - "abstract": "Join K2's Senior Technical Specialist for a presentation showcasing K2 Software to help you achieve Digital transformation through Hybrid Business Process Automation integrated seamlessly with your SharePoint Online, on premise SharePoint environments, and standalone business apps with data integration to key business systems critical to your company's processes.\n

    \nIn this session, Richard Theodore, walks you through the journey of digital transformation using low-code K2 business apps.\n

    \nGet the tools, insights and inspiration you need to help your organization achieve Business Process Automation and be part of the transformation.", - "title": "The Future Role of AI in Apps for O365", - "sessioncode": "SP25", - "eventName": "2017 Fall", - "sessionID": 2673, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "SP", "VS" ], - "tracks": [ "188", "186" ], - "speakerNames": [ "Richard Theodore" ], - "speakers": [ "1430" ], - "__v": 0 - }, - { - "_id": "59481dc5b6c6abf442787323", - "ID": 2481, - "sessioncode": "VS18", - "title": "The Missing Piece", - "abstract": "Over the past decades, the software development industry has carved out a massive core body of knowledge of software architecture and design patterns. And yet, fundamentally, our industry is not better off because of it, as it falls behind trying to cope quickly with ever changing requirements and increased complexity, coupled with dwindling budgets and outsourcing constraints. A dissonance exists between the ivory tower theoretical world of best practices and the grim reality in the trenches. In this visionary session, Juval Lowy will articulate the root causes of the problem, propose contemporary solution comprising of tools, process and a new profession, literally a missing piece in the puzzle he calls the business architect. Finally, Juval will predicate the impact and infliction adopting his approach will have on the livelihood and prosperity of every software architect and developer.", - "eventName": "2017 Fall", - "sessionID": 2481, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS", "AB" ], - "tracks": [ "186", "190" ], - "speakerNames": [ "Juval Lowy" ], - "speakers": [ "1188" ], - "__v": 0 - }, - { - "_id": "595672756a83e8a414c21b64", - "ID": 2606, - "sessioncode": "VS33", - "title": "The Power of Roslyn: Improving Your Productivity with Live Code Analyzers", - "abstract": "Three years ago we open sourced the C# and Visual Basic compilers and exposed their functionality through APIs as the Roslyn project. The Roslyn analyzer API empowers the developer community to be more productive by lighting up their own features in the editor in real-time—meaning anyone can write a refactoring, code fix, code style rule, or code diagnostic. Come learn more about the Roslyn project and what these live analyzers mean for you and your productivity.", - "eventName": "2017 Fall", - "sessionID": 2606, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS", "AB" ], - "tracks": [ "186", "190" ], - "speakerNames": [ "Kasey Uhlenhuth" ], - "speakers": [ "1470" ], - "__v": 0 - }, - { - "_id": "59401938ecc8333822007fb0", - "ID": 2445, - "sessioncode": "AB08", - "title": "The Rise of JavaScript-Driven Native and NativeScript", - "abstract": "Struggling to create high performance mobile apps with JavaScript? Wish you could use your web development skills to create truly native mobile apps? Struggle and wish no more. A new wave of next generation platforms promises to radically improve the state of the art for web developers trying to build high-quality mobile apps. “JavaScript-driven Native” platforms, like NativeScript, finally combine the skill and code portability of the web with the unlimited power of native platform UI. Put an end to your cross-platform app development woes and join this session to learn about JavaScript-driven Native and the open source platforms like NativeScript leading the way.", - "eventName": "2017 Fall", - "sessionID": 2445, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "AB", "ASP" ], - "tracks": [ "190", "187" ], - "speakerNames": [ "Todd Anglin" ], - "speakers": [ "1019" ], - "__v": 0 - }, - { - "_id": "59a98c14ef10d7a0185d1a8b", - "ID": 2670, - "sessioncode": "VS36", - "title": "Tips to Roll Out Self-Service BI Successfully", - "abstract": "After many years of self-service BI initiatives started by organizations to empower their business users, most still fail user adoption and revert to the traditional BI processes, albeit with new tools. Recent surveys have shown a decline in user adoption even with the new tech available. Why? In this session Bhupesh will discuss the reasons behind the inconsistency in self-service initiatives and their successful adoption. We will uncover the key missing pieces in today’s implementations and what you need to look out for in your initiative to roll out self-service BI for your end users. This session will give you a checklist to guide you through a successful self-service BI roll-out.", - "eventName": "2017 Fall", - "sessionID": 2670, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS", "AB" ], - "tracks": [ "186", "190" ], - "speakerNames": [ "Bhupesh Malhotra" ], - "speakers": [ "1493" ], - "__v": 0 - }, - { - "_id": "59401bdbecc8333822007fba", - "ID": 2450, - "sessioncode": "AP09", - "title": "TypeScript for C# Developers", - "abstract": "C# developers come to TypeScript from a very different perspective than JavaScript developers, In this session we will cover TypeScript as a first class language and show its similarities (and differences) to C#.", - "eventName": "2017 Fall", - "sessionID": 2450, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T11:15", - "endTime": "2017-11-1T12:15", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Jesse Liberty" ], - "speakers": [ "1134" ], - "__v": 1 - }, - { - "_id": "59cbc8edea15de94182b6299", - "ID": 2733, - "sessioncode": "AI04", - "title": "Using Microsoft Visual Studio Code Tools for AI to create data science solutions that scale", - "abstract": "This session will cover the full data science lifecycle, from data acquisition to creating a web-service for scoring new dataset, highlighting some of the new features from Azure Machine Learning like versioning, run history, reproducibility. We will use multiple deep-learning frameworks, like Microsoft CNTK and Google TensorFlow, and machine learning packages to illustrate how to infuse AI and ML into your application.", - "eventName": "2017 Fall", - "sessionID": 2733, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T10:00", - "endTime": "2017-11-1T11:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "AI", "VS" ], - "tracks": [ "193", "186" ], - "speakerNames": [ "Ahmet Gyger" ], - "speakers": [ "1507" ], - "__v": 0 - }, - { - "_id": "59404b6a672304ec08c13cae", - "ID": 2474, - "sessioncode": "VS14", - "title": "Using VS Code Like a Boss!", - "abstract": "VS Code is an amazing IDE. Somehow, Microsoft managed to create a highly capable coding tool that’s not too heavy and not too light.\n

    \nOn the surface, Code appears to be a simple, but there are a lot of hidden and extended features each of which has the potential of carving wasted minutes off of your dev day.\n

    \nIn this session, we’ll look at keyboard shortcuts, extensions, customizations, and other tips and tricks.\n

    \nWhether your editing text files or C++ projects, come learn how to use VS Code like a boss!", - "eventName": "2017 Fall", - "sessionID": 2474, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-10-31T09:00", - "endTime": "2017-10-31T10:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS" ], - "tracks": [ "186" ], - "speakerNames": [ "Jeremy Foster" ], - "speakers": [ "1439" ], - "__v": 0 - }, - { - "_id": "59401d00ecc8333822007fbe", - "ID": 2452, - "sessioncode": "AP10", - "title": "Using npm scripts as your build tool", - "abstract": "If you are building a JavaScript application then chances are you're already using npm to install your dependencies. In this session, we'll take an example project and slowly start to leverage npm scripts to handle all of our various build needs.\n

    \nWe will start by using existing npm scripts, creating our own custom script, having our scripts run in series and in parallel, using various npm script lifecycle hooks, passing arguments from one script to another, piping data from one process to another, and using environment or config variables within our scripts.\n

    \nIn addition we will look at several node packages that enable us to use shorthand and wildcard syntax, that will run scripts when either when the file system changes or when certain git hooks are triggered, and will provide us various ways to easily find and execute the scripts we want.\n

    \nWe will examine several techniques to split out npm scripts to external files once they get large or complicated. And finally we will address the various things you need to consider when trying to run npm scripts across different environments (Mac, Linux, Windows).", - "eventName": "2017 Fall", - "sessionID": 2452, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T15:00", - "endTime": "2017-11-1T16:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Elijah Manor" ], - "speakers": [ "1075" ], - "__v": 0 - }, - { - "_id": "594022cdecc8333822007fcd", - "ID": 2459, - "title": "Vue.js - The Next Big Thing In JavaScript", - "sessioncode": "AP16", - "abstract": "If you feel like modern web development with Angular and React has gotten way too complicated, Vue.js might be the JavaScript framework for you. With over 10K stars on Github, Vue.js has vaulted out of relative obscurity to find companies such as GitLab choosing to use it over React. In this session, we’ll take a look at why Vue.js is so popular, what makes it different from Angular and React and how easy it is to stand up and deploy a simple Vue.js application. Vue.js is a brilliant piece of JavaScript engineering, and it just might make you rethink your next app.", - "eventName": "2017 Fall", - "sessionID": 2459, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-2T10:00", - "endTime": "2017-11-2T11:15", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "ASP", "AB" ], - "tracks": [ "187", "190" ], - "speakerNames": [ "Burke Holland" ], - "speakers": [ "1290" ], - "__v": 0 - }, - { - "_id": "59cd29e2ea15de94182b62b3", - "ID": 2737, - "sessioncode": "AI08", - "title": "What’s New with the Cortana Skills Kit?", - "abstract": "The Cortana Skills Kit helps you easily build intelligent, personalized experiences for millions of users. In this session, you will learn about the Cortana Skills Kit, and how to build skills for Cortana that work across multiple platforms, starting with Windows 10, Android and iOS. You will also learn how the Cortana skills platform works and how to use the new features to build rich, engaging experiences for your users.", - "eventName": "2017 Fall", - "sessionID": 2737, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-2T11:30", - "endTime": "2017-11-2T12:45", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "AI", "Azure", "VS" ], - "tracks": [ "193", "191", "186" ], - "speakerNames": [ "Dorrene Brown" ], - "speakers": [ "1512" ], - "__v": 0 - }, - { - "_id": "59555e336a83e8a414c21b5e", - "ID": 2604, - "sessioncode": "VS31", - "title": "What’s new in C#:", - "abstract": "In this demo-filled talk, Mads goes over what’s new in C# 7.0 and 7.1. Showing tuples, deconstruction, local functions, pattern matching and more, he’ll focus both on the language features and the support for them in Visual Studio. At the end he’ll show a glimpse of what’s being worked on for future versions of C#.", - "eventName": "2017 Fall", - "sessionID": 2604, - "roomID": 110, - "roomName": "TBD", - "timeSlot": 198, - "startTime": "2017-11-1T10:00", - "endTime": "2017-11-1T11:00", - "date": "10/31/2017", - "hidden": false, - "trackNames": [ "VS" ], - "tracks": [ "186" ], - "speakerNames": [ "Mads Torgersen" ], - "speakers": [ "1433" ], - "__v": 0 - } -] \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Import/NDC_London_2019.json b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Import/NDC_London_2019.json deleted file mode 100644 index fea2d895..00000000 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Import/NDC_London_2019.json +++ /dev/null @@ -1,8119 +0,0 @@ -[ - { - "date": "2019-01-30T00:00:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "sessions": [ - { - "id": "69229", - "title": "Keynote: Welcome to the Machine", - "description": "Information is everywhere and for many people, especially in the connected world, it is accessible freely or at a minimal cost. News outlets rely on social media to broadcast breaking news. Social media in turn relies on us to feed it with information, be it of our surroundings or our personal information. It’s become somewhat of a self-sustaining self-serving machine in which we’re all part of. It’s big data and we’re a cog in the wheel. For now of course, because with big data and cheap yet powerful hardware, AI also wants to play the game.\r\n\r\nAnd if information and knowledge is the key to success, surely this means we’re on the right path. The question is, will we notice some of the warning signs before it’s too late…", - "startsAt": "2019-01-30T09:00:00", - "endsAt": "2019-01-30T10:00:00", - "isServiceSession": false, - "isPlenumSession": true, - "speakers": [ - { - "id": "2d146e58-439f-40ec-9d5b-1dbefdeb707a", - "name": "Hadi Hariri" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - { - "id": "66591", - "title": "Much Ado about Nothing: A C# play in two acts - Act 1, starring Mads Torgersen", - "description": "Understand the history and motivation behind introducing nullable types into an existing language.\r\nThis opening act is a deep design dive where you see the twists and turns of designing such a major feature that introduces potentially breaking changes into mountains of existing code. The stage is set for a major strategic shift in how you write C# code.", - "startsAt": "2019-01-30T10:20:00", - "endsAt": "2019-01-30T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "8f64af49-a647-48e7-850b-70505308d948", - "name": "Mads Torgersen" - }, - { - "id": "be2a42b5-fc04-47c8-860b-7c503a8c6854", - "name": "Bill Wagner" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10583, - "name": "Languages" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - { - "id": "66592", - "title": "Much Ado about Nothing: A C# play in two acts. Act 2, starring Bill Wagner", - "description": "Resolve that tension by learning to love that strategic shift and put the new understanding into practice.\r\n\r\nLearn how nullable reference types affects your design decisions and how you express those decisions. Learn how to migrate an existing code base by discovering the original intent and expressing that intent in new syntax. The exciting conclusion to a world without null.", - "startsAt": "2019-01-30T11:40:00", - "endsAt": "2019-01-30T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "be2a42b5-fc04-47c8-860b-7c503a8c6854", - "name": "Bill Wagner" - }, - { - "id": "8f64af49-a647-48e7-850b-70505308d948", - "name": "Mads Torgersen" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10583, - "name": "Languages" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - { - "id": "69301", - "title": "Insecure Transit - Microservice Security", - "description": "A deep dive into some of the technical challenges and solutions to securing a microservice architecture.\r\n\r\nMicroservices are great, and they offer us lots of options for how we can build, scale and evolve our applications. On the face of it, they should also help us create much more secure applications - the ability to protect in depth is a key part of protecting systems, and microservices make this much easier. On the other hand, information that used to flow within single processes, now flows over our networks, giving us a real headache. How do we make sure our shiny new microservices architectures aren’t less secure than their monolithic predecessor.\r\n\r\nIn this talk, I outline some of the key challenges associated with microservice architectures with respect to security, and then looks at approaches to address these issues. From secret stores, time-limited credentials and better backups, to confused deputy problems, JWT tokens and service meshes, this talk looks at the state of the art for building secure microservice architectures.", - "startsAt": "2019-01-30T13:40:00", - "endsAt": "2019-01-30T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "9dac5e37-9ba2-4d4b-90a1-a004f4d51270", - "name": "Sam Newman" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - { - "id": "68804", - "title": "Life Beyond Distributed Transactions: An Apostate's Implementation", - "description": "Over a decade ago, Pat Helland authored his paper, \"Life Beyond Distributed Transactions: An Apostate's Opinion\" describing a means to coordinate activities between entities in databases when a transaction encompassing those entities wasn't feasible or possible. While the paper and subsequent talks provided great insight in the challenges of coordinating activities across entities in a single database, implementations were left as an exercise to the reader!\r\n\r\nFast forward to today, and now we have NoSQL databases, microservices, message queues and brokers, HTTP web services and more that don't (and shouldn't) support any kind of distributed transaction.\r\n\r\nIn this session, we'll look at how to implement coordination between non-transactional resources using Pat's paper as a guide, with examples in Azure Cosmos DB, Azure Service Bus, and Azure SQL Server. We'll look at a real-world example where a codebase assumed everything would be transactional and always succeed, but production proved us wrong! Finally, we'll look at advanced coordination workflows such as Sagas to achieve robust, scalable coordination across the enterprise.", - "startsAt": "2019-01-30T16:20:00", - "endsAt": "2019-01-30T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "f109dd0b-9441-4cbf-8664-19c021a6de4a", - "name": "Jimmy Bogard" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10585, - "name": "Microservices" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - { - "id": "69174", - "title": "Hack to the Future", - "description": "Infosec is a continual game of one-upmanship; we build a defence and someone breaks it so we build another one then they break that and the cycle continues. Because of this, the security controls we have at our disposal are rapidly changing and the ones we used yesterday are very often useless today.\r\n\r\nThis talk focuses on what the threats look like *today*. What are we getting wrong, how do we fix it and how do we stay on top in an environment which will be different again tomorrow to what it is today. It's a real-world look at modern defences that everyone building online applications will want to see.", - "startsAt": "2019-01-30T17:40:00", - "endsAt": "2019-01-30T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "735a4b60-42e8-4452-9480-68197372c206", - "name": "Troy Hunt" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10589, - "name": "Security" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - } - ], - "hasOnlyPlenumSessions": false - }, - { - "id": 2776, - "name": "Room 2", - "sessions": [ - { - "id": "69170", - "title": "What you need to know about ASP.NET Core 2.2", - "description": "Another new version of ASP.NET Core is here and it brings new capabilities, making it easier than ever to build and consume APIs. But there's also some hidden gems in the framework that aren't well known that you should definitely know about! \r\n\r\nDamian and David from the ASP.NET Core team are back to show you the new features plus their favourite, little-known features that don't get enough attention but will make your lives easier.", - "startsAt": "2019-01-30T10:20:00", - "endsAt": "2019-01-30T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "ad079cb0-a1a4-4051-8690-ba4975eb207a", - "name": "Damian Edwards" - }, - { - "id": "f9759467-293f-4805-a4da-c9db9d8310aa", - "name": "David Fowler" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10596, - "name": "Web" - }, - { - "id": 10586, - "name": "Microsoft" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - { - "id": "68938", - "title": "Securing Web Applications and APIs with ASP.NET Core 2.2 and 3.0", - "description": "ASP.NET Core and MVC is a mature and modern platform to build secure web applications and APIs for a while now. Starting with version 2.2, Microsoft makes big investments in the areas of standards-based authentication, single sign-on and API security by including the popular open source project IdentityServer4 in the project templates. This talk gives an overview over the various security features in ASP.NET Core but focuses in particular on the API security scenarios enabled by IdentityServer.", - "startsAt": "2019-01-30T11:40:00", - "endsAt": "2019-01-30T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "2201252d-46ba-4f0e-a519-ac8f6ea1501c", - "name": "Dominick Baier" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10589, - "name": "Security" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - { - "id": "68939", - "title": "Building Clients for OpenID Connect/OAuth 2-based Systems", - "description": "Using protocols like OpenID Connect and OAuth 2 for authentication and API access can on one hand simply your front-ends dramatically since they don’t have to deal with credentials anymore – but on the other hand introduces new challenges like choosing the right protocol flow for the given client, secure token storage as well as token lifetime management. This talk gives an overview over the best practices how to solve the above problems for both native server and client-side applications as well as browser-based applications and SPAs.", - "startsAt": "2019-01-30T13:40:00", - "endsAt": "2019-01-30T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "2201252d-46ba-4f0e-a519-ac8f6ea1501c", - "name": "Dominick Baier" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10589, - "name": "Security" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - { - "id": "66448", - "title": "Designing Nullable Reference Types in F#", - "description": "Together for C#, F# will be incorporating nullability as a concept for .NET reference types. From the F# perspective, this fits with the default non-nullness of other F# types. But compatibility with existing code makes designing this a wild ride indeed! In this talk, we'll briefly explain what nullability means for F#, some existing mitigations for null in the language, and how we must consider compatibility with everything in mind. This deep dive into language design should give you an idea about what it is like designing a nontrivial feature that improves existing code while remaining compatible with it.", - "startsAt": "2019-01-30T15:00:00", - "endsAt": "2019-01-30T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "cdeb4f0a-4f3e-4bd3-be85-b8528a5fdfcb", - "name": "Phillip Carter" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10583, - "name": "Languages" - }, - { - "id": 10580, - "name": "Functional Programming" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - { - "id": "68940", - "title": "Domain-Driven Design: Hidden Lessons from the Big Blue Book", - "description": "We are entering an incredible new era of digital product development where users expect a seamless experience across all of their touchable, wearable, and voice-activated devices. How can we learn to develop software effectively in this new digital-by-default world? \r\n\r\nWhat if the answers are hidden away as secret messages in a 15 year old book? \r\n\r\nAre bounded contexts really used to design loosely coupled code, or are they one of the most powerful organisation design tools used to enable autonomous, self-organising teams? Are core domains just academic jargon that get in the way of shiny technical practices like event sourcing, or is understanding business core domains one of the key differentiators between high-performing delivery teams and the rest of us?\r\n\r\nLet’s go on an adventure and see if the big blue big and can help us in this brave new world.", - "startsAt": "2019-01-30T16:20:00", - "endsAt": "2019-01-30T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "b9d7090c-afe3-4278-ae79-d85987b4aae5", - "name": "Nick Tune" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10566, - "name": "Architecture" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - { - "id": "61516", - "title": "Panel discussion on the future of .NET", - "description": "Panel discussion with four experts in the field on the current state of the art and the where .NET and related technologies are heading.\r\n\r\nWe will discuss cross platform development, new features, performance, versioning issues of .NET Core, what’s going to happen with full framework, Blazor, how .NET stands up against competing technologies and where it is all going. \r\n\r\nYou won't cram more info into a session than this, come spend a great hour with us.", - "startsAt": "2019-01-30T17:40:00", - "endsAt": "2019-01-30T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "de972e57-7765-4c38-9dcd-5981587c1433", - "name": "Bryan Hogan" - }, - { - "id": "70590ad0-b1b3-40b8-b05d-b58722ef9d9d", - "name": "Mark Rendle" - }, - { - "id": "cb70e0f2-0f0b-4b8f-b3f4-a9326309a1b2", - "name": "Tess Ferrandez-Norlander" - }, - { - "id": "8b1783d3-15ce-41dc-b989-386759803d97", - "name": "Oren Novotny" - }, - { - "id": "8f64af49-a647-48e7-850b-70505308d948", - "name": "Mads Torgersen" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10596, - "name": "Web" - }, - { - "id": 10586, - "name": "Microsoft" - }, - { - "id": 10572, - "name": "Cross-Platform" - }, - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - } - ], - "hasOnlyPlenumSessions": false - }, - { - "id": 2777, - "name": "Room 3", - "sessions": [ - { - "id": "68546", - "title": "Observability and the Development Process", - "description": "Historically, monitoring has been thought of as an afterthought of the software development cycle: something owned by the ops side of the room. But instead of trying to predict the various ways something might go sideways right before release and crafting dashboards to prepare, what might it look like to use answers about our system to figure out what to build, and how to build it, and whom for?\r\n\r\nObservability is the practice of understanding the internal state of a system via knowledge of its external outputs -- and is something that should be built into the process of crafting software from the very beginning.\r\n\r\nIn this talk, we'll discuss what this might look like in practice by using Honeycomb as a case study: how we rely on visibility into our system to inform planning during the development process, to observe the impact of new changes during and after release, and, of course, debug. We'll start by describing the problems faced by a SaaS platform like ours, then run through some specific instrumentation practices that we love and have used successfully to gain the visibility we need into our system’s day-to-day operations.", - "startsAt": "2019-01-30T10:20:00", - "endsAt": "2019-01-30T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "e5d55e8e-93d1-4a53-bbec-10e4beaf5fd8", - "name": "Christine Yen" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10592, - "name": "Testing" - }, - { - "id": 10593, - "name": "Tools" - }, - { - "id": 10575, - "name": "DevOps" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - { - "id": "68745", - "title": "Distributed Tracing: How the Pros Debug Concurrent and Distributed Systems", - "description": "As more and more developers move to distributed architectures such as micro services, distributed actor systems, and so forth it becomes increasingly complex to understand, debug, and diagnose.\r\n\r\nIn this talk we're going to introduce the emerging OpenTracing standard and talk about how you can instrument your applications to help visualize every operation, even across process and service boundaries. We'll also introduce Zipkin, one of the most popular implementations of the OpenTracing standard. ", - "startsAt": "2019-01-30T11:40:00", - "endsAt": "2019-01-30T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "5a279f06-e4d2-449c-879d-eedec29cd401", - "name": "Aaron Stannard" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10585, - "name": "Microservices" - }, - { - "id": 10572, - "name": "Cross-Platform" - }, - { - "id": 10575, - "name": "DevOps" - }, - { - "id": 10566, - "name": "Architecture" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - { - "id": "58654", - "title": "Icons and the Web: Symbols of the Modern Age", - "description": "Icons have been a staple of software for decades, and come in as many varieties as the tools used to make them. From humble beginnings as precisely-pixelated pictograms, icons are now entering a renaissance of high-density displays, vector formats, and an almost cult-like following. In this session, you'll learn the inner workings of modern icon design, explore various techniques for adding symbology to your web apps, and discover how to bring your interfaces into the modern age!", - "startsAt": "2019-01-30T13:40:00", - "endsAt": "2019-01-30T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "17a4cdca-0332-4607-9de3-993d25ccc459", - "name": "Tim G. Thomas" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10594, - "name": "UI" - }, - { - "id": 10595, - "name": "UX" - }, - { - "id": 10596, - "name": "Web" - }, - { - "id": 10574, - "name": "Design" - }, - { - "id": 10593, - "name": "Tools" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - { - "id": "68734", - "title": "Infrastructure as TypeScript", - "description": "For almost a decade \"Infrastructure as Code\" has been a DevOps buzzword - but the myriad tools in share a dirty little secret... there's no actual code! Few people like \"programming\" YAML or JSON (even the human-friendly variants!), and even fewer like having to reverse-engineer ways to apply known good development practices to tools which resist it at all cost.\r\n\r\nSo, what if things were different,and programming infrastructure was more like real programming, with real programming languages like TypeScript? What if you defined Lambda functions by actually writing lambdas, created abstractions using complex types, and could take advantage of existing tools for modularity, linting, refactoring and testing?\r\n\r\nEnter Pulumi, an open-source deployment engine which enables all these things using TypeScript, Python or Go!\r\n\r\nIn this talk, we'll look at how you can write TypeScript code using Pulumi to provision traditional cloud infrastructure, manage Kubernetes and build portable \"serverless\" applications - all with minimal YAML in sight! We'll look at deploying to multiple regions of the same cloud, and how to build abstractions allowing multi-cloud to be a reality.", - "startsAt": "2019-01-30T15:00:00", - "endsAt": "2019-01-30T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "82242efa-dc48-4c4b-8e26-6b93bbe5623a", - "name": "James Nugent" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10582, - "name": "JavaScript" - }, - { - "id": 10593, - "name": "Tools" - }, - { - "id": 10590, - "name": "Serverless" - }, - { - "id": 10575, - "name": "DevOps" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - { - "id": "68493", - "title": "The tech future is diverse", - "description": "By 2020, there will be 4 times more devices connected to the Internet around the world. While technology impacts our everyday life in almost every way, the solutions we create fails to reflect our society or the world we live in. Instead, they often reinforce stereotypes, prejudice, and differences. In this talk, we will look into the lack of diversity and how diversity will make us more suited to solve problems and meet the needs of our society. We will address the culture in our communities, the reasons why minorities quit, and the importance of diversity in tech.", - "startsAt": "2019-01-30T16:20:00", - "endsAt": "2019-01-30T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "50fd0b93-cece-43b5-a7f6-f9ccca500f91", - "name": "Tannaz N. Roshandel" - }, - { - "id": "daafd2d6-0eb2-4eb4-834c-76d51734f6f7", - "name": "Line Moseng" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10578, - "name": "Ethics" - }, - { - "id": 10588, - "name": "People" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - { - "id": "62178", - "title": "Patterns for Resilient Architecture", - "description": "We have traditionally built robust software systems by trying to avoid mistakes and by dodging failures when they occur in production or by testing parts of the system in isolation from one another. Modern methods and techniques take a very different approach based on resiliency, which promotes embracing failure instead of trying to avoid it. Resilient architectures enhance observability, leverage well-known patterns such as graceful degradation, timeouts and circuit breakers and embrace chaos engineering, a discipline that promotes breaking things on purpose in order to learn how to build more resilient systems. In this session, will review the most useful patterns for building resilient software systems and I will introduce chaos engineering methodology and especially show the audience how they can benefit from breaking things on purpose.", - "startsAt": "2019-01-30T17:40:00", - "endsAt": "2019-01-30T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "e4fd745a-8a49-43d3-8763-020a4f3512ab", - "name": "Adrian Hornsby" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10585, - "name": "Microservices" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10575, - "name": "DevOps" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - } - ], - "hasOnlyPlenumSessions": false - }, - { - "id": 2778, - "name": "Room 4", - "sessions": [ - { - "id": "66715", - "title": "GraphQL Will Do To REST What JSON Did To XML", - "description": "Why GraphQL will become the new standard for accessing external data in your application. I will show how using GraphQL instead of REST services the development process becomes even more declarative as GraphQL will take away the (imperative) hassle of tying data from multiple endpoints together. This will increase the level of complexity in frontend development, while also increasing the performance of the application.\r\n", - "startsAt": "2019-01-30T11:40:00", - "endsAt": "2019-01-30T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "4bb972aa-3d92-45ff-95b4-68ed3ca86e9e", - "name": "Roy Derks" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10582, - "name": "JavaScript" - }, - { - "id": 10593, - "name": "Tools" - }, - { - "id": 10587, - "name": "Mobile" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - { - "id": "63252", - "title": "Dynamic Runtime Code with Roslyn", - "description": "A possibly overlooked feature of the Roslyn compiler is the ability to generate, compile, and load new types at runtime. Sure, we've always had *some* ability to use dynamic code in .Net, but the existing techniques were either slow (Reflection) or daunting to use (IL generation or Expressions). Now though, we can just use C# in a way that's both more approachable for more developers and lends itself to more ambitious levels of dynamic behavior. In this talk I'll show some of the ways I've been using this technique to create more efficient, low allocation application frameworks. We'll also dive into the Utf8Json library already uses this approach today in its support for very highly efficient Json parsing.", - "startsAt": "2019-01-30T13:40:00", - "endsAt": "2019-01-30T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "cf80d55a-62bf-4be2-a986-27d217129faf", - "name": "Jeremy Miller" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - { - "id": "66433", - "title": "Pragmatic Performance: When to care about perf, and what to do about it.", - "description": "As a developer you often here both that performance is important, but also that you shouldn't worry about performance up front, so when is the right time to think about it? And if the time is right, what are you actually supposed to do?\r\n\r\nIf you're interested to hear about a pragmatic approach to performance, this talk will explain when is the right time to think about benchmarking, but more importantly will run through how to correctly benchmark .NET code so any decisions made will be based on information about your code that is trustworthy.\r\n\r\nAdditionally you'll also find out about some of the common, and some of the unknown, performance pitfalls of the .NET Framework and we'll discuss the true meaning behind the phrase \"premature optimization is the root of all evil\".", - "startsAt": "2019-01-30T15:00:00", - "endsAt": "2019-01-30T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "604507ba-fd96-4c48-a29a-67a95760d888", - "name": "David Wengier" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10593, - "name": "Tools" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - { - "id": "59857", - "title": "CSS Grid - What is this Magic?!", - "description": "We’ve all heard a lot in the last year about a new advancement in the world of CSS, called CSS Grid. Starting off at whispers, we’re now starting to hear it as a deafening roar as more and more developers write about it, talk about it, share it and start using it. In the world of front end, I see it everywhere I turn and am excited as I start to use it in my own projects.\r\n\r\nBut what does this new CSS specification mean for software developers, and why should you care about it? In the world of tech today, we can do so many amazing things and use whatever language we choose across a wide range of devices and platforms. Whether it’s the advent of React and React Native, or frameworks like Electron, it’s easier than ever to build one app that works on multiple platforms with the language we know and work with best. The ability to do this also expands to styling apps on any platform using CSS, and therefore being able to utilise the magical thing that is\r\nCSS Grid.\r\n\r\nThe reason CSS Grid is gaining so much attention, is because it’s a game changer for front end and layouts. With a few simple lines of code, we can now create imaginative, dynamic, responsive layouts (yep, I know that’s a lot of buzz words). While a lot of people are calling this the new ‘table layout’, grid gives us so much more, with the ability to spread cells across columns and rows to whatever size you choose, dictate which direction new items flow, allow cells to move around to fit in place and even tell certain cells exactly where they need to sit.\r\n\r\nWhile there is so much to worry about when developing an app, CSS Grid means that you can worry less about building the layout on the front end, and more about making sure the back end works well. Let me show you how the magic works.", - "startsAt": "2019-01-30T16:20:00", - "endsAt": "2019-01-30T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "d387e75c-ed26-4dc6-8612-0f18abdfd9f5", - "name": "Amy Kapernick" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10596, - "name": "Web" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - { - "id": "68826", - "title": "A lap around Azure Devops", - "description": "Azure DevOps (previously known as Visual Studio Team Services) is a broad product suite with tools that assists small and large software development teams that want to deliver high quality software at a rapid speed. \r\n\r\nIn session we will walk through all major features in Azure DevOps, such as Azure Boards, Azure Pipelines and Azure Repos, and look at how we can continuously deliver value to or end users and implement DevOps practices such as Infrastructure as Code and testing in production using Azure.", - "startsAt": "2019-01-30T17:40:00", - "endsAt": "2019-01-30T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "54973c7d-2fe5-4a49-9a1c-a52afed4d6a4", - "name": "Jakob Ehn" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10571, - "name": "Continuous Delivery" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10564, - "name": "Agile" - }, - { - "id": 10575, - "name": "DevOps" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - } - ], - "hasOnlyPlenumSessions": false - }, - { - "id": 2779, - "name": "Room 5", - "sessions": [ - { - "id": "67422", - "title": "What You Need to Know About Open Source—Trust Me, I'm a Lawyer", - "description": "Open source tools. We all use them. Whether an entire framework, a focused toolkit, or a simple custom component from GitHub, npm, or NuGet, the opportunity to improve our development speed while learning new things from open source projects is enticing.\r\n\r\nBut what does “open source” truly mean? What are our rights and limitations as open source consumers to use, modify, and redistribute these tools in a professional environment? The answer depends upon the OSS author's own decisions regarding project licensing. Come investigate the core principles of open source development and consumption while comparing and contrasting some of the more popular licenses in use today. Learn to make better decisions for your organization by becoming informed of how best to leverage the open source works of others and also how to properly license your own.", - "startsAt": "2019-01-30T10:20:00", - "endsAt": "2019-01-30T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "b3761cce-aaeb-4ca4-a5b3-40f162f6bcf8", - "name": "Jeff Strauss" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10593, - "name": "Tools" - }, - { - "id": 10591, - "name": "Soft Skills" - }, - { - "id": 10588, - "name": "People" - }, - { - "id": 10578, - "name": "Ethics" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - { - "id": "66768", - "title": "Teaching New Tricks – How to enhance the skills of experienced developers", - "description": "It’s easy to forget what it felt like when you were a beginner. This lively dog-based* talk is about the rewards and pitfalls involved in introducing pair programming, TDD and an agile development approach to experienced developers who are used to working in a different way. It includes several practical suggestions of how to help and convince less agile-experienced colleagues.\r\nBased on my experience as a consultant technical lead, the aim is to help you to move your team members to a state of childlike fearlessness where learning is fun; is embedded in everything you do; and applies to all team members regardless of experience. \r\n*It turns out that images of dogs can be used to illustrate an astonishing variety of concepts!", - "startsAt": "2019-01-30T11:40:00", - "endsAt": "2019-01-30T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "403fae21-0856-432a-b35c-0949ebaac53c", - "name": "Clare Sudbery" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10564, - "name": "Agile" - }, - { - "id": 10591, - "name": "Soft Skills" - }, - { - "id": 10588, - "name": "People" - }, - { - "id": 10578, - "name": "Ethics" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - { - "id": "58982", - "title": "Reading other peoples code", - "description": "Someone else's code. Even worse, thousands of lines, maybe hundreds of files of other peoples code. Is there a way to methodically read and understand other peoples work, build their mental models? In this talk I will go through techniques I have developed throughout 18 years of programming. Hopefully you will walk away with a plan on how to approach a new code base. But even more I hope you walk away with a feeling of curiosity, wanting to get to know your fellow programmers through their code.", - "startsAt": "2019-01-30T13:40:00", - "endsAt": "2019-01-30T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "0eaa4bb2-cb2a-4b76-800d-de8b1dfdb50c", - "name": "Patricia Aas" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10572, - "name": "Cross-Platform" - }, - { - "id": 10583, - "name": "Languages" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - { - "id": "69253", - "title": "Power BI for Developers", - "description": "Integrate, Extend, Embed!\r\n\r\nIn this session, you will learn how developers can deliver real-time dashboards, create custom visuals and embed rich interactive analytics in their apps with Power BI. This presentation specifically targets experienced app developers, and also those curious to understand what developers can achieve with Power BI. Numerous demonstrations will put the theory into action.", - "startsAt": "2019-01-30T15:00:00", - "endsAt": "2019-01-30T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "cc7c7f29-87fc-44b2-a62b-a6ea4a332ea9", - "name": "Peter Myers" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10565, - "name": "AI" - }, - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10573, - "name": "Database" - }, - { - "id": 10586, - "name": "Microsoft" - }, - { - "id": 10596, - "name": "Web" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - { - "id": "67909", - "title": "Build vs Buy: Software Systems at Jurassic Park", - "description": "We were so preoccupied with whether we could, we didn’t stop to think if we should. Nowhere at Jurassic Park was this more true than how we developed software. Having the wrong software and support structures was a key factor in the failures of our first park. We were entrepreneurs launching something new and architects integrating an enterprise. And our decisions had lasting consequences. Deciding which problems were worth our time was foundational to our failure.\r\n\r\nJoin us for a retrospective of software systems at Jurassic Park. We’ll dig into case studies and explore our successes and failures. We’ll uncover the options, costs, and risks inherent in deciding what software to build, what to buy, and alternatives in between. We’ll explore the opportunity cost of building systems, the sustainability of open-source, and the risks of vendor lock-in. You’ll leave equipped to make better decisions and avoid the pitfalls we made at Jurassic Park.", - "startsAt": "2019-01-30T17:40:00", - "endsAt": "2019-01-30T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "5f017dbb-6821-480b-a750-82a0f15fa1b2", - "name": "Todd Gardner" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10588, - "name": "People" - }, - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10579, - "name": "Fun" - }, - { - "id": 10591, - "name": "Soft Skills" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - } - ], - "hasOnlyPlenumSessions": false - }, - { - "id": 2780, - "name": "Room 6", - "sessions": [ - { - "id": "67163", - "title": "Workshop: An introduction to Kubernetes on Google Cloud with Docker - Part 1/2", - "description": "Do you want to deploy your own application in the cloud, but don't know where you should start? This workshop is for you!\r\n\r\nIn this workshop you will create your first Kubernetes cluster with Docker images in Google Cloud. By using Docker images, you can build and deploy your application without worrying about the environment on the server. We will create a cluster containing a frontend web application and a backend.\r\n\r\n This workshop does not require knowledge about Docker, Kubernetes or Google Cloud.\r\n\r\nYou will need to bring your own computer to attend the workshop.", - "startsAt": "2019-01-30T10:20:00", - "endsAt": "2019-01-30T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "8c7086a0-fd3b-4c11-b085-1182faa39e7b", - "name": "Ingrid Guren" - }, - { - "id": "daafd2d6-0eb2-4eb4-834c-76d51734f6f7", - "name": "Line Moseng" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10569, - "name": "Cloud" - } - ], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - }, - { - "id": "66459", - "title": "Getting Started with Cosmos DB + EF Core", - "description": "Cosmos DB is great and awesomely fast. Wouldn't be even more amazing if we could use our beloved entity framework to manage it? Let see how we can wire it up and get started", - "startsAt": "2019-01-30T15:00:00", - "endsAt": "2019-01-30T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "c739e2f1-ecf5-43e1-abcf-90cf13dd7b8f", - "name": "Thiago Passos" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10590, - "name": "Serverless" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10573, - "name": "Database" - } - ], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - }, - { - "id": "69255", - "title": "Workshop: Embedding Power BI Analytics - Part 1/2", - "description": "This instructor-led workshop focuses on development practices for embedding Power BI reports, dashboards and the Q&A experience, and working with the Power BI JavaScript API.\r\n\r\nThis workshop is designed for web developers experienced with ASP.NET, Visual C#, HTML and JavaScript. You are required to bring your own PC, with Visual Studio 2015 (or later) with web tools installed.", - "startsAt": "2019-01-30T16:20:00", - "endsAt": "2019-01-30T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "cc7c7f29-87fc-44b2-a62b-a6ea4a332ea9", - "name": "Peter Myers" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10596, - "name": "Web" - }, - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10573, - "name": "Database" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10582, - "name": "JavaScript" - }, - { - "id": 10586, - "name": "Microsoft" - } - ], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - } - ], - "hasOnlyPlenumSessions": false - } - ], - "timeSlots": [ - { - "slotStart": "09:00:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "session": { - "id": "69229", - "title": "Keynote: Welcome to the Machine", - "description": "Information is everywhere and for many people, especially in the connected world, it is accessible freely or at a minimal cost. News outlets rely on social media to broadcast breaking news. Social media in turn relies on us to feed it with information, be it of our surroundings or our personal information. It’s become somewhat of a self-sustaining self-serving machine in which we’re all part of. It’s big data and we’re a cog in the wheel. For now of course, because with big data and cheap yet powerful hardware, AI also wants to play the game.\r\n\r\nAnd if information and knowledge is the key to success, surely this means we’re on the right path. The question is, will we notice some of the warning signs before it’s too late…", - "startsAt": "2019-01-30T09:00:00", - "endsAt": "2019-01-30T10:00:00", - "isServiceSession": false, - "isPlenumSession": true, - "speakers": [ - { - "id": "2d146e58-439f-40ec-9d5b-1dbefdeb707a", - "name": "Hadi Hariri" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - "index": 0 - } - ] - }, - { - "slotStart": "10:20:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "session": { - "id": "66591", - "title": "Much Ado about Nothing: A C# play in two acts - Act 1, starring Mads Torgersen", - "description": "Understand the history and motivation behind introducing nullable types into an existing language.\r\nThis opening act is a deep design dive where you see the twists and turns of designing such a major feature that introduces potentially breaking changes into mountains of existing code. The stage is set for a major strategic shift in how you write C# code.", - "startsAt": "2019-01-30T10:20:00", - "endsAt": "2019-01-30T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "8f64af49-a647-48e7-850b-70505308d948", - "name": "Mads Torgersen" - }, - { - "id": "be2a42b5-fc04-47c8-860b-7c503a8c6854", - "name": "Bill Wagner" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10583, - "name": "Languages" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - "index": 0 - }, - { - "id": 2776, - "name": "Room 2", - "session": { - "id": "69170", - "title": "What you need to know about ASP.NET Core 2.2", - "description": "Another new version of ASP.NET Core is here and it brings new capabilities, making it easier than ever to build and consume APIs. But there's also some hidden gems in the framework that aren't well known that you should definitely know about! \r\n\r\nDamian and David from the ASP.NET Core team are back to show you the new features plus their favourite, little-known features that don't get enough attention but will make your lives easier.", - "startsAt": "2019-01-30T10:20:00", - "endsAt": "2019-01-30T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "ad079cb0-a1a4-4051-8690-ba4975eb207a", - "name": "Damian Edwards" - }, - { - "id": "f9759467-293f-4805-a4da-c9db9d8310aa", - "name": "David Fowler" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10596, - "name": "Web" - }, - { - "id": 10586, - "name": "Microsoft" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - "index": 1 - }, - { - "id": 2777, - "name": "Room 3", - "session": { - "id": "68546", - "title": "Observability and the Development Process", - "description": "Historically, monitoring has been thought of as an afterthought of the software development cycle: something owned by the ops side of the room. But instead of trying to predict the various ways something might go sideways right before release and crafting dashboards to prepare, what might it look like to use answers about our system to figure out what to build, and how to build it, and whom for?\r\n\r\nObservability is the practice of understanding the internal state of a system via knowledge of its external outputs -- and is something that should be built into the process of crafting software from the very beginning.\r\n\r\nIn this talk, we'll discuss what this might look like in practice by using Honeycomb as a case study: how we rely on visibility into our system to inform planning during the development process, to observe the impact of new changes during and after release, and, of course, debug. We'll start by describing the problems faced by a SaaS platform like ours, then run through some specific instrumentation practices that we love and have used successfully to gain the visibility we need into our system’s day-to-day operations.", - "startsAt": "2019-01-30T10:20:00", - "endsAt": "2019-01-30T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "e5d55e8e-93d1-4a53-bbec-10e4beaf5fd8", - "name": "Christine Yen" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10592, - "name": "Testing" - }, - { - "id": 10593, - "name": "Tools" - }, - { - "id": 10575, - "name": "DevOps" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - "index": 2 - }, - { - "id": 2779, - "name": "Room 5", - "session": { - "id": "67422", - "title": "What You Need to Know About Open Source—Trust Me, I'm a Lawyer", - "description": "Open source tools. We all use them. Whether an entire framework, a focused toolkit, or a simple custom component from GitHub, npm, or NuGet, the opportunity to improve our development speed while learning new things from open source projects is enticing.\r\n\r\nBut what does “open source” truly mean? What are our rights and limitations as open source consumers to use, modify, and redistribute these tools in a professional environment? The answer depends upon the OSS author's own decisions regarding project licensing. Come investigate the core principles of open source development and consumption while comparing and contrasting some of the more popular licenses in use today. Learn to make better decisions for your organization by becoming informed of how best to leverage the open source works of others and also how to properly license your own.", - "startsAt": "2019-01-30T10:20:00", - "endsAt": "2019-01-30T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "b3761cce-aaeb-4ca4-a5b3-40f162f6bcf8", - "name": "Jeff Strauss" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10593, - "name": "Tools" - }, - { - "id": 10591, - "name": "Soft Skills" - }, - { - "id": 10588, - "name": "People" - }, - { - "id": 10578, - "name": "Ethics" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - "index": 4 - }, - { - "id": 2780, - "name": "Room 6", - "session": { - "id": "67163", - "title": "Workshop: An introduction to Kubernetes on Google Cloud with Docker - Part 1/2", - "description": "Do you want to deploy your own application in the cloud, but don't know where you should start? This workshop is for you!\r\n\r\nIn this workshop you will create your first Kubernetes cluster with Docker images in Google Cloud. By using Docker images, you can build and deploy your application without worrying about the environment on the server. We will create a cluster containing a frontend web application and a backend.\r\n\r\n This workshop does not require knowledge about Docker, Kubernetes or Google Cloud.\r\n\r\nYou will need to bring your own computer to attend the workshop.", - "startsAt": "2019-01-30T10:20:00", - "endsAt": "2019-01-30T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "8c7086a0-fd3b-4c11-b085-1182faa39e7b", - "name": "Ingrid Guren" - }, - { - "id": "daafd2d6-0eb2-4eb4-834c-76d51734f6f7", - "name": "Line Moseng" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10569, - "name": "Cloud" - } - ], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - }, - "index": 5 - } - ] - }, - { - "slotStart": "11:40:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "session": { - "id": "66592", - "title": "Much Ado about Nothing: A C# play in two acts. Act 2, starring Bill Wagner", - "description": "Resolve that tension by learning to love that strategic shift and put the new understanding into practice.\r\n\r\nLearn how nullable reference types affects your design decisions and how you express those decisions. Learn how to migrate an existing code base by discovering the original intent and expressing that intent in new syntax. The exciting conclusion to a world without null.", - "startsAt": "2019-01-30T11:40:00", - "endsAt": "2019-01-30T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "be2a42b5-fc04-47c8-860b-7c503a8c6854", - "name": "Bill Wagner" - }, - { - "id": "8f64af49-a647-48e7-850b-70505308d948", - "name": "Mads Torgersen" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10583, - "name": "Languages" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - "index": 0 - }, - { - "id": 2776, - "name": "Room 2", - "session": { - "id": "68938", - "title": "Securing Web Applications and APIs with ASP.NET Core 2.2 and 3.0", - "description": "ASP.NET Core and MVC is a mature and modern platform to build secure web applications and APIs for a while now. Starting with version 2.2, Microsoft makes big investments in the areas of standards-based authentication, single sign-on and API security by including the popular open source project IdentityServer4 in the project templates. This talk gives an overview over the various security features in ASP.NET Core but focuses in particular on the API security scenarios enabled by IdentityServer.", - "startsAt": "2019-01-30T11:40:00", - "endsAt": "2019-01-30T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "2201252d-46ba-4f0e-a519-ac8f6ea1501c", - "name": "Dominick Baier" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10589, - "name": "Security" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - "index": 1 - }, - { - "id": 2777, - "name": "Room 3", - "session": { - "id": "68745", - "title": "Distributed Tracing: How the Pros Debug Concurrent and Distributed Systems", - "description": "As more and more developers move to distributed architectures such as micro services, distributed actor systems, and so forth it becomes increasingly complex to understand, debug, and diagnose.\r\n\r\nIn this talk we're going to introduce the emerging OpenTracing standard and talk about how you can instrument your applications to help visualize every operation, even across process and service boundaries. We'll also introduce Zipkin, one of the most popular implementations of the OpenTracing standard. ", - "startsAt": "2019-01-30T11:40:00", - "endsAt": "2019-01-30T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "5a279f06-e4d2-449c-879d-eedec29cd401", - "name": "Aaron Stannard" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10585, - "name": "Microservices" - }, - { - "id": 10572, - "name": "Cross-Platform" - }, - { - "id": 10575, - "name": "DevOps" - }, - { - "id": 10566, - "name": "Architecture" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - "index": 2 - }, - { - "id": 2778, - "name": "Room 4", - "session": { - "id": "66715", - "title": "GraphQL Will Do To REST What JSON Did To XML", - "description": "Why GraphQL will become the new standard for accessing external data in your application. I will show how using GraphQL instead of REST services the development process becomes even more declarative as GraphQL will take away the (imperative) hassle of tying data from multiple endpoints together. This will increase the level of complexity in frontend development, while also increasing the performance of the application.\r\n", - "startsAt": "2019-01-30T11:40:00", - "endsAt": "2019-01-30T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "4bb972aa-3d92-45ff-95b4-68ed3ca86e9e", - "name": "Roy Derks" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10582, - "name": "JavaScript" - }, - { - "id": 10593, - "name": "Tools" - }, - { - "id": 10587, - "name": "Mobile" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - "index": 3 - }, - { - "id": 2779, - "name": "Room 5", - "session": { - "id": "66768", - "title": "Teaching New Tricks – How to enhance the skills of experienced developers", - "description": "It’s easy to forget what it felt like when you were a beginner. This lively dog-based* talk is about the rewards and pitfalls involved in introducing pair programming, TDD and an agile development approach to experienced developers who are used to working in a different way. It includes several practical suggestions of how to help and convince less agile-experienced colleagues.\r\nBased on my experience as a consultant technical lead, the aim is to help you to move your team members to a state of childlike fearlessness where learning is fun; is embedded in everything you do; and applies to all team members regardless of experience. \r\n*It turns out that images of dogs can be used to illustrate an astonishing variety of concepts!", - "startsAt": "2019-01-30T11:40:00", - "endsAt": "2019-01-30T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "403fae21-0856-432a-b35c-0949ebaac53c", - "name": "Clare Sudbery" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10564, - "name": "Agile" - }, - { - "id": 10591, - "name": "Soft Skills" - }, - { - "id": 10588, - "name": "People" - }, - { - "id": 10578, - "name": "Ethics" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - "index": 4 - } - ] - }, - { - "slotStart": "13:40:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "session": { - "id": "69301", - "title": "Insecure Transit - Microservice Security", - "description": "A deep dive into some of the technical challenges and solutions to securing a microservice architecture.\r\n\r\nMicroservices are great, and they offer us lots of options for how we can build, scale and evolve our applications. On the face of it, they should also help us create much more secure applications - the ability to protect in depth is a key part of protecting systems, and microservices make this much easier. On the other hand, information that used to flow within single processes, now flows over our networks, giving us a real headache. How do we make sure our shiny new microservices architectures aren’t less secure than their monolithic predecessor.\r\n\r\nIn this talk, I outline some of the key challenges associated with microservice architectures with respect to security, and then looks at approaches to address these issues. From secret stores, time-limited credentials and better backups, to confused deputy problems, JWT tokens and service meshes, this talk looks at the state of the art for building secure microservice architectures.", - "startsAt": "2019-01-30T13:40:00", - "endsAt": "2019-01-30T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "9dac5e37-9ba2-4d4b-90a1-a004f4d51270", - "name": "Sam Newman" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - "index": 0 - }, - { - "id": 2776, - "name": "Room 2", - "session": { - "id": "68939", - "title": "Building Clients for OpenID Connect/OAuth 2-based Systems", - "description": "Using protocols like OpenID Connect and OAuth 2 for authentication and API access can on one hand simply your front-ends dramatically since they don’t have to deal with credentials anymore – but on the other hand introduces new challenges like choosing the right protocol flow for the given client, secure token storage as well as token lifetime management. This talk gives an overview over the best practices how to solve the above problems for both native server and client-side applications as well as browser-based applications and SPAs.", - "startsAt": "2019-01-30T13:40:00", - "endsAt": "2019-01-30T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "2201252d-46ba-4f0e-a519-ac8f6ea1501c", - "name": "Dominick Baier" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10589, - "name": "Security" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - "index": 1 - }, - { - "id": 2777, - "name": "Room 3", - "session": { - "id": "58654", - "title": "Icons and the Web: Symbols of the Modern Age", - "description": "Icons have been a staple of software for decades, and come in as many varieties as the tools used to make them. From humble beginnings as precisely-pixelated pictograms, icons are now entering a renaissance of high-density displays, vector formats, and an almost cult-like following. In this session, you'll learn the inner workings of modern icon design, explore various techniques for adding symbology to your web apps, and discover how to bring your interfaces into the modern age!", - "startsAt": "2019-01-30T13:40:00", - "endsAt": "2019-01-30T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "17a4cdca-0332-4607-9de3-993d25ccc459", - "name": "Tim G. Thomas" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10594, - "name": "UI" - }, - { - "id": 10595, - "name": "UX" - }, - { - "id": 10596, - "name": "Web" - }, - { - "id": 10574, - "name": "Design" - }, - { - "id": 10593, - "name": "Tools" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - "index": 2 - }, - { - "id": 2778, - "name": "Room 4", - "session": { - "id": "63252", - "title": "Dynamic Runtime Code with Roslyn", - "description": "A possibly overlooked feature of the Roslyn compiler is the ability to generate, compile, and load new types at runtime. Sure, we've always had *some* ability to use dynamic code in .Net, but the existing techniques were either slow (Reflection) or daunting to use (IL generation or Expressions). Now though, we can just use C# in a way that's both more approachable for more developers and lends itself to more ambitious levels of dynamic behavior. In this talk I'll show some of the ways I've been using this technique to create more efficient, low allocation application frameworks. We'll also dive into the Utf8Json library already uses this approach today in its support for very highly efficient Json parsing.", - "startsAt": "2019-01-30T13:40:00", - "endsAt": "2019-01-30T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "cf80d55a-62bf-4be2-a986-27d217129faf", - "name": "Jeremy Miller" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - "index": 3 - }, - { - "id": 2779, - "name": "Room 5", - "session": { - "id": "58982", - "title": "Reading other peoples code", - "description": "Someone else's code. Even worse, thousands of lines, maybe hundreds of files of other peoples code. Is there a way to methodically read and understand other peoples work, build their mental models? In this talk I will go through techniques I have developed throughout 18 years of programming. Hopefully you will walk away with a plan on how to approach a new code base. But even more I hope you walk away with a feeling of curiosity, wanting to get to know your fellow programmers through their code.", - "startsAt": "2019-01-30T13:40:00", - "endsAt": "2019-01-30T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "0eaa4bb2-cb2a-4b76-800d-de8b1dfdb50c", - "name": "Patricia Aas" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10572, - "name": "Cross-Platform" - }, - { - "id": 10583, - "name": "Languages" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - "index": 4 - } - ] - }, - { - "slotStart": "15:00:00", - "rooms": [ - { - "id": 2776, - "name": "Room 2", - "session": { - "id": "66448", - "title": "Designing Nullable Reference Types in F#", - "description": "Together for C#, F# will be incorporating nullability as a concept for .NET reference types. From the F# perspective, this fits with the default non-nullness of other F# types. But compatibility with existing code makes designing this a wild ride indeed! In this talk, we'll briefly explain what nullability means for F#, some existing mitigations for null in the language, and how we must consider compatibility with everything in mind. This deep dive into language design should give you an idea about what it is like designing a nontrivial feature that improves existing code while remaining compatible with it.", - "startsAt": "2019-01-30T15:00:00", - "endsAt": "2019-01-30T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "cdeb4f0a-4f3e-4bd3-be85-b8528a5fdfcb", - "name": "Phillip Carter" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10583, - "name": "Languages" - }, - { - "id": 10580, - "name": "Functional Programming" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - "index": 1 - }, - { - "id": 2777, - "name": "Room 3", - "session": { - "id": "68734", - "title": "Infrastructure as TypeScript", - "description": "For almost a decade \"Infrastructure as Code\" has been a DevOps buzzword - but the myriad tools in share a dirty little secret... there's no actual code! Few people like \"programming\" YAML or JSON (even the human-friendly variants!), and even fewer like having to reverse-engineer ways to apply known good development practices to tools which resist it at all cost.\r\n\r\nSo, what if things were different,and programming infrastructure was more like real programming, with real programming languages like TypeScript? What if you defined Lambda functions by actually writing lambdas, created abstractions using complex types, and could take advantage of existing tools for modularity, linting, refactoring and testing?\r\n\r\nEnter Pulumi, an open-source deployment engine which enables all these things using TypeScript, Python or Go!\r\n\r\nIn this talk, we'll look at how you can write TypeScript code using Pulumi to provision traditional cloud infrastructure, manage Kubernetes and build portable \"serverless\" applications - all with minimal YAML in sight! We'll look at deploying to multiple regions of the same cloud, and how to build abstractions allowing multi-cloud to be a reality.", - "startsAt": "2019-01-30T15:00:00", - "endsAt": "2019-01-30T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "82242efa-dc48-4c4b-8e26-6b93bbe5623a", - "name": "James Nugent" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10582, - "name": "JavaScript" - }, - { - "id": 10593, - "name": "Tools" - }, - { - "id": 10590, - "name": "Serverless" - }, - { - "id": 10575, - "name": "DevOps" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - "index": 2 - }, - { - "id": 2778, - "name": "Room 4", - "session": { - "id": "66433", - "title": "Pragmatic Performance: When to care about perf, and what to do about it.", - "description": "As a developer you often here both that performance is important, but also that you shouldn't worry about performance up front, so when is the right time to think about it? And if the time is right, what are you actually supposed to do?\r\n\r\nIf you're interested to hear about a pragmatic approach to performance, this talk will explain when is the right time to think about benchmarking, but more importantly will run through how to correctly benchmark .NET code so any decisions made will be based on information about your code that is trustworthy.\r\n\r\nAdditionally you'll also find out about some of the common, and some of the unknown, performance pitfalls of the .NET Framework and we'll discuss the true meaning behind the phrase \"premature optimization is the root of all evil\".", - "startsAt": "2019-01-30T15:00:00", - "endsAt": "2019-01-30T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "604507ba-fd96-4c48-a29a-67a95760d888", - "name": "David Wengier" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10593, - "name": "Tools" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - "index": 3 - }, - { - "id": 2779, - "name": "Room 5", - "session": { - "id": "69253", - "title": "Power BI for Developers", - "description": "Integrate, Extend, Embed!\r\n\r\nIn this session, you will learn how developers can deliver real-time dashboards, create custom visuals and embed rich interactive analytics in their apps with Power BI. This presentation specifically targets experienced app developers, and also those curious to understand what developers can achieve with Power BI. Numerous demonstrations will put the theory into action.", - "startsAt": "2019-01-30T15:00:00", - "endsAt": "2019-01-30T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "cc7c7f29-87fc-44b2-a62b-a6ea4a332ea9", - "name": "Peter Myers" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10565, - "name": "AI" - }, - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10573, - "name": "Database" - }, - { - "id": 10586, - "name": "Microsoft" - }, - { - "id": 10596, - "name": "Web" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - "index": 4 - }, - { - "id": 2780, - "name": "Room 6", - "session": { - "id": "66459", - "title": "Getting Started with Cosmos DB + EF Core", - "description": "Cosmos DB is great and awesomely fast. Wouldn't be even more amazing if we could use our beloved entity framework to manage it? Let see how we can wire it up and get started", - "startsAt": "2019-01-30T15:00:00", - "endsAt": "2019-01-30T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "c739e2f1-ecf5-43e1-abcf-90cf13dd7b8f", - "name": "Thiago Passos" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10590, - "name": "Serverless" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10573, - "name": "Database" - } - ], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - }, - "index": 5 - } - ] - }, - { - "slotStart": "16:20:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "session": { - "id": "68804", - "title": "Life Beyond Distributed Transactions: An Apostate's Implementation", - "description": "Over a decade ago, Pat Helland authored his paper, \"Life Beyond Distributed Transactions: An Apostate's Opinion\" describing a means to coordinate activities between entities in databases when a transaction encompassing those entities wasn't feasible or possible. While the paper and subsequent talks provided great insight in the challenges of coordinating activities across entities in a single database, implementations were left as an exercise to the reader!\r\n\r\nFast forward to today, and now we have NoSQL databases, microservices, message queues and brokers, HTTP web services and more that don't (and shouldn't) support any kind of distributed transaction.\r\n\r\nIn this session, we'll look at how to implement coordination between non-transactional resources using Pat's paper as a guide, with examples in Azure Cosmos DB, Azure Service Bus, and Azure SQL Server. We'll look at a real-world example where a codebase assumed everything would be transactional and always succeed, but production proved us wrong! Finally, we'll look at advanced coordination workflows such as Sagas to achieve robust, scalable coordination across the enterprise.", - "startsAt": "2019-01-30T16:20:00", - "endsAt": "2019-01-30T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "f109dd0b-9441-4cbf-8664-19c021a6de4a", - "name": "Jimmy Bogard" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10585, - "name": "Microservices" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - "index": 0 - }, - { - "id": 2776, - "name": "Room 2", - "session": { - "id": "68940", - "title": "Domain-Driven Design: Hidden Lessons from the Big Blue Book", - "description": "We are entering an incredible new era of digital product development where users expect a seamless experience across all of their touchable, wearable, and voice-activated devices. How can we learn to develop software effectively in this new digital-by-default world? \r\n\r\nWhat if the answers are hidden away as secret messages in a 15 year old book? \r\n\r\nAre bounded contexts really used to design loosely coupled code, or are they one of the most powerful organisation design tools used to enable autonomous, self-organising teams? Are core domains just academic jargon that get in the way of shiny technical practices like event sourcing, or is understanding business core domains one of the key differentiators between high-performing delivery teams and the rest of us?\r\n\r\nLet’s go on an adventure and see if the big blue big and can help us in this brave new world.", - "startsAt": "2019-01-30T16:20:00", - "endsAt": "2019-01-30T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "b9d7090c-afe3-4278-ae79-d85987b4aae5", - "name": "Nick Tune" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10566, - "name": "Architecture" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - "index": 1 - }, - { - "id": 2777, - "name": "Room 3", - "session": { - "id": "68493", - "title": "The tech future is diverse", - "description": "By 2020, there will be 4 times more devices connected to the Internet around the world. While technology impacts our everyday life in almost every way, the solutions we create fails to reflect our society or the world we live in. Instead, they often reinforce stereotypes, prejudice, and differences. In this talk, we will look into the lack of diversity and how diversity will make us more suited to solve problems and meet the needs of our society. We will address the culture in our communities, the reasons why minorities quit, and the importance of diversity in tech.", - "startsAt": "2019-01-30T16:20:00", - "endsAt": "2019-01-30T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "50fd0b93-cece-43b5-a7f6-f9ccca500f91", - "name": "Tannaz N. Roshandel" - }, - { - "id": "daafd2d6-0eb2-4eb4-834c-76d51734f6f7", - "name": "Line Moseng" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10578, - "name": "Ethics" - }, - { - "id": 10588, - "name": "People" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - "index": 2 - }, - { - "id": 2778, - "name": "Room 4", - "session": { - "id": "59857", - "title": "CSS Grid - What is this Magic?!", - "description": "We’ve all heard a lot in the last year about a new advancement in the world of CSS, called CSS Grid. Starting off at whispers, we’re now starting to hear it as a deafening roar as more and more developers write about it, talk about it, share it and start using it. In the world of front end, I see it everywhere I turn and am excited as I start to use it in my own projects.\r\n\r\nBut what does this new CSS specification mean for software developers, and why should you care about it? In the world of tech today, we can do so many amazing things and use whatever language we choose across a wide range of devices and platforms. Whether it’s the advent of React and React Native, or frameworks like Electron, it’s easier than ever to build one app that works on multiple platforms with the language we know and work with best. The ability to do this also expands to styling apps on any platform using CSS, and therefore being able to utilise the magical thing that is\r\nCSS Grid.\r\n\r\nThe reason CSS Grid is gaining so much attention, is because it’s a game changer for front end and layouts. With a few simple lines of code, we can now create imaginative, dynamic, responsive layouts (yep, I know that’s a lot of buzz words). While a lot of people are calling this the new ‘table layout’, grid gives us so much more, with the ability to spread cells across columns and rows to whatever size you choose, dictate which direction new items flow, allow cells to move around to fit in place and even tell certain cells exactly where they need to sit.\r\n\r\nWhile there is so much to worry about when developing an app, CSS Grid means that you can worry less about building the layout on the front end, and more about making sure the back end works well. Let me show you how the magic works.", - "startsAt": "2019-01-30T16:20:00", - "endsAt": "2019-01-30T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "d387e75c-ed26-4dc6-8612-0f18abdfd9f5", - "name": "Amy Kapernick" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10596, - "name": "Web" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - "index": 3 - }, - { - "id": 2780, - "name": "Room 6", - "session": { - "id": "69255", - "title": "Workshop: Embedding Power BI Analytics - Part 1/2", - "description": "This instructor-led workshop focuses on development practices for embedding Power BI reports, dashboards and the Q&A experience, and working with the Power BI JavaScript API.\r\n\r\nThis workshop is designed for web developers experienced with ASP.NET, Visual C#, HTML and JavaScript. You are required to bring your own PC, with Visual Studio 2015 (or later) with web tools installed.", - "startsAt": "2019-01-30T16:20:00", - "endsAt": "2019-01-30T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "cc7c7f29-87fc-44b2-a62b-a6ea4a332ea9", - "name": "Peter Myers" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10596, - "name": "Web" - }, - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10573, - "name": "Database" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10582, - "name": "JavaScript" - }, - { - "id": 10586, - "name": "Microsoft" - } - ], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - }, - "index": 5 - } - ] - }, - { - "slotStart": "17:40:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "session": { - "id": "69174", - "title": "Hack to the Future", - "description": "Infosec is a continual game of one-upmanship; we build a defence and someone breaks it so we build another one then they break that and the cycle continues. Because of this, the security controls we have at our disposal are rapidly changing and the ones we used yesterday are very often useless today.\r\n\r\nThis talk focuses on what the threats look like *today*. What are we getting wrong, how do we fix it and how do we stay on top in an environment which will be different again tomorrow to what it is today. It's a real-world look at modern defences that everyone building online applications will want to see.", - "startsAt": "2019-01-30T17:40:00", - "endsAt": "2019-01-30T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "735a4b60-42e8-4452-9480-68197372c206", - "name": "Troy Hunt" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10589, - "name": "Security" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - "index": 0 - }, - { - "id": 2776, - "name": "Room 2", - "session": { - "id": "61516", - "title": "Panel discussion on the future of .NET", - "description": "Panel discussion with four experts in the field on the current state of the art and the where .NET and related technologies are heading.\r\n\r\nWe will discuss cross platform development, new features, performance, versioning issues of .NET Core, what’s going to happen with full framework, Blazor, how .NET stands up against competing technologies and where it is all going. \r\n\r\nYou won't cram more info into a session than this, come spend a great hour with us.", - "startsAt": "2019-01-30T17:40:00", - "endsAt": "2019-01-30T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "de972e57-7765-4c38-9dcd-5981587c1433", - "name": "Bryan Hogan" - }, - { - "id": "70590ad0-b1b3-40b8-b05d-b58722ef9d9d", - "name": "Mark Rendle" - }, - { - "id": "cb70e0f2-0f0b-4b8f-b3f4-a9326309a1b2", - "name": "Tess Ferrandez-Norlander" - }, - { - "id": "8b1783d3-15ce-41dc-b989-386759803d97", - "name": "Oren Novotny" - }, - { - "id": "8f64af49-a647-48e7-850b-70505308d948", - "name": "Mads Torgersen" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10596, - "name": "Web" - }, - { - "id": 10586, - "name": "Microsoft" - }, - { - "id": 10572, - "name": "Cross-Platform" - }, - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - "index": 1 - }, - { - "id": 2777, - "name": "Room 3", - "session": { - "id": "62178", - "title": "Patterns for Resilient Architecture", - "description": "We have traditionally built robust software systems by trying to avoid mistakes and by dodging failures when they occur in production or by testing parts of the system in isolation from one another. Modern methods and techniques take a very different approach based on resiliency, which promotes embracing failure instead of trying to avoid it. Resilient architectures enhance observability, leverage well-known patterns such as graceful degradation, timeouts and circuit breakers and embrace chaos engineering, a discipline that promotes breaking things on purpose in order to learn how to build more resilient systems. In this session, will review the most useful patterns for building resilient software systems and I will introduce chaos engineering methodology and especially show the audience how they can benefit from breaking things on purpose.", - "startsAt": "2019-01-30T17:40:00", - "endsAt": "2019-01-30T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "e4fd745a-8a49-43d3-8763-020a4f3512ab", - "name": "Adrian Hornsby" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10585, - "name": "Microservices" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10575, - "name": "DevOps" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - "index": 2 - }, - { - "id": 2778, - "name": "Room 4", - "session": { - "id": "68826", - "title": "A lap around Azure Devops", - "description": "Azure DevOps (previously known as Visual Studio Team Services) is a broad product suite with tools that assists small and large software development teams that want to deliver high quality software at a rapid speed. \r\n\r\nIn session we will walk through all major features in Azure DevOps, such as Azure Boards, Azure Pipelines and Azure Repos, and look at how we can continuously deliver value to or end users and implement DevOps practices such as Infrastructure as Code and testing in production using Azure.", - "startsAt": "2019-01-30T17:40:00", - "endsAt": "2019-01-30T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "54973c7d-2fe5-4a49-9a1c-a52afed4d6a4", - "name": "Jakob Ehn" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10571, - "name": "Continuous Delivery" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10564, - "name": "Agile" - }, - { - "id": 10575, - "name": "DevOps" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - "index": 3 - }, - { - "id": 2779, - "name": "Room 5", - "session": { - "id": "67909", - "title": "Build vs Buy: Software Systems at Jurassic Park", - "description": "We were so preoccupied with whether we could, we didn’t stop to think if we should. Nowhere at Jurassic Park was this more true than how we developed software. Having the wrong software and support structures was a key factor in the failures of our first park. We were entrepreneurs launching something new and architects integrating an enterprise. And our decisions had lasting consequences. Deciding which problems were worth our time was foundational to our failure.\r\n\r\nJoin us for a retrospective of software systems at Jurassic Park. We’ll dig into case studies and explore our successes and failures. We’ll uncover the options, costs, and risks inherent in deciding what software to build, what to buy, and alternatives in between. We’ll explore the opportunity cost of building systems, the sustainability of open-source, and the risks of vendor lock-in. You’ll leave equipped to make better decisions and avoid the pitfalls we made at Jurassic Park.", - "startsAt": "2019-01-30T17:40:00", - "endsAt": "2019-01-30T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "5f017dbb-6821-480b-a750-82a0f15fa1b2", - "name": "Todd Gardner" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10588, - "name": "People" - }, - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10579, - "name": "Fun" - }, - { - "id": 10591, - "name": "Soft Skills" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - "index": 4 - } - ] - } - ] - }, - { - "date": "2019-01-31T00:00:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "sessions": [ - { - "id": "69333", - "title": "How We Got Here - The History of Web Development", - "description": "The Internet existed before the Web, but the Web redefined the Internet - what started out as a protocol for helping scientists share documents and references has turned into one of the most important forces in the 21st century. But how did we get here?\r\n\r\nJoin Richard Campbell as he tells the story of the World Wide Web and the web development tools and techniques that made it all possible. From the early versions of HTML where you laid out web pages with tables (GeoCities anyone?) and simple scripting languages to CSS, JavaScript and HTML 5, leading to Single Page Applications, Progressive Web Apps and Web Assembly! We've come a long way, and the story is continuing!", - "startsAt": "2019-01-31T09:00:00", - "endsAt": "2019-01-31T10:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "d4d7850a-526e-4959-aab1-36460081fcf5", - "name": "Richard Campbell" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10596, - "name": "Web" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - { - "id": "69344", - "title": "Structure and Interpretation of Test Cases", - "description": "Throw a line of code into many codebases and it's sure to hit one or more testing frameworks. There's no shortage of frameworks for testing, each with their particular spin and set of conventions, but that glut is not always matched by a clear vision of how to structure and use tests — a framework is a vehicle, but you still need to know how to drive.\r\n\r\nThis talk takes a deep dive into testing, with a strong focus on unit testing, looking at examples and counterexamples in different languages and frameworks, from naming to nesting, exploring the benefits of data-driven testing, the trade-offs between example-based and property-based testing, how to get the most out of the common given–when–then refrain and knowing how far to follow it.", - "startsAt": "2019-01-31T10:20:00", - "endsAt": "2019-01-31T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "bc20c5a9-2d7e-4830-827f-8919be0eba88", - "name": "Kevlin Henney" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10574, - "name": "Design" - }, - { - "id": 10564, - "name": "Agile" - }, - { - "id": 10592, - "name": "Testing" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - { - "id": "68994", - "title": "Beyond Developer", - "description": "When I started in IT the roles were clearly separated. Business Analysts wrote requirements, Architects designed them, Programmers wrote the code, Testers tested the software.\r\n\r\nOver the last decade or so we have seen a shift towards “generalising specialists” who can cut code, understand a business domain, design a user interface, participate in and automate some of the testing and deployment activities, and who are sometimes even responsible for the health and wellbeing of their own systems in production.\r\n\r\nTo succeed in this new world requires more than “3 years of Java”. The modern developer needs to be constantly reinventing themselves, learning, and helping others to do the same. In this session, Dan explores some of the skills and characteristics of the modern developer, and suggests some ways you can grow them for yourself.", - "startsAt": "2019-01-31T11:40:00", - "endsAt": "2019-01-31T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "d06cbb07-240c-4dd9-9c3d-4fd585e084fd", - "name": "Dan North" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10588, - "name": "People" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - { - "id": "69052", - "title": "Blazor, a new framework for browser-based .NET apps", - "description": "Today, nearly all browser-based apps are written in JavaScript (or similar languages that transpile to it). That’s fine, but there’s no good reason to limit our industry to basically one language when so many powerful and mature alternate languages and programming platforms exist. Starting now, WebAssembly opens the floodgates to new choices, and one of the first realistic options may be .NET.\r\n \r\nBlazor is a new experimental web UI framework from the ASP.NET team that aims to brings .NET applications into all browsers (including mobile) via WebAssembly. It allows you to build true full-stack .NET applications, sharing code across server and client, with no need for transpilation or plugins.\r\n \r\nIn this talk I’ll demonstrate what you can do with Blazor today and how it works on the underlying WebAssembly runtime behind the scenes. You’ll see its modern, component-based architecture (inspired by modern SPA frameworks) at work as we use it to build a responsive client-side UI. I’ll cover both basic and advanced scenarios using Blazor’s components, router, DI system, JavaScript interop, and more.", - "startsAt": "2019-01-31T13:40:00", - "endsAt": "2019-01-31T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "05fe7f1a-cc5c-4e6e-8422-281c822c82c3", - "name": "Steve Sanderson" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10582, - "name": "JavaScript" - }, - { - "id": 10596, - "name": "Web" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - { - "id": "69345", - "title": "Where is C# headed?", - "description": "C# 8.0 is coming up! Not just nullable reference types and asynchronous streams, which will get much coverage elsewhere in the conference, but also recursive patterns, switch expressions, ranges, default interface member implementations and more. We’ll look at all of those, and also at some of the things being worked on for future versions of the language.", - "startsAt": "2019-01-31T15:00:00", - "endsAt": "2019-01-31T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "8f64af49-a647-48e7-850b-70505308d948", - "name": "Mads Torgersen" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - { - "id": "66795", - "title": "DiagnosticSourcery 101", - "description": ".NET has a new mechanism for generating and storing diagnostic data: DiagnosticSource. This is the cross-platform alternative to ETW. Much of ASP.NET Core and EF Core produce useful metric data using DiagnosticSource, and you can produce your own and stream some or all of the data to the metrics storage of your choice.\r\n\r\nIn this talk I'll run through how DiagnosticSource works, show you how to use it to output your own metrics in any .NET application, and how to pipe those metrics to a Time-Series database and turn them into a lovely Grafana dashboard.\r\n\r\nYou can use DiagnosticSource in anything from an ASP.NET Core cloud-native microservice to a WPF desktop application, and it's a Microsoft package with no 3rd-party dependencies, so this talk should be interesting and useful for any .NET developer.", - "startsAt": "2019-01-31T16:20:00", - "endsAt": "2019-01-31T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "70590ad0-b1b3-40b8-b05d-b58722ef9d9d", - "name": "Mark Rendle" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10572, - "name": "Cross-Platform" - }, - { - "id": 10575, - "name": "DevOps" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - { - "id": "63671", - "title": "Let's Talk HTTP in .NET Core", - "description": "In the world of microservices (yes, there's that buzzword again!) and distributed systems, we often find ourselves communicating over HTTP. What seems like a simple requirement can quickly become complicated! Networks aren't reliable and services fail. Dealing with those inevitable facts and avoiding a cascading failure can be quite a challenge. In this talk, Steve will explore how we can build .NET Core applications that make HTTP requests and rely on downstream services, whilst remaining resilient and fault tolerant.\r\n\r\nThis session will focus on some of the improvements which have been released in .NET Core and ASP.NET Core 2.1, such as IHttpClientFactory and the new, more performant SocketHttpHandler. Steve will identify some HTTP anti-patterns and common mistakes and demonstrate how we can refactor existing code to use the new HttpClientFactory features.\r\n\r\nNext, Steve will demonstrate other HTTP tips and tricking, including Polly; a fantastic resilience and transient fault handling library which can be used to make your applications less prone to failure. When integrated with the Microsoft IHttpClientFactory; wrapping your HTTP calls in retries, timeouts and circuit-breakers has never been easier!\r\n\r\nIf you're building services which make HTTP calls, then this talk is for you!", - "startsAt": "2019-01-31T17:40:00", - "endsAt": "2019-01-31T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "26b7e78d-aa31-4d7f-b2ea-90fef14d1087", - "name": "Steve Gordon" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10586, - "name": "Microsoft" - }, - { - "id": 10585, - "name": "Microservices" - }, - { - "id": 10596, - "name": "Web" - }, - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10569, - "name": "Cloud" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - } - ], - "hasOnlyPlenumSessions": false - }, - { - "id": 2776, - "name": "Room 2", - "sessions": [ - { - "id": "69266", - "title": "CompSci and My Day Job", - "description": "4 years ago I had a vague idea about Big-O notation and absolutely no clue about combinatorial problems. I knew what a SHA256 hash was (sort of) but I didn't know how it was created, nor that it didn't completely protect some of my data. I knew these things were important, but I never understood how they could apply to the types of applications I was building at the time. All of this changed as I put together the first two volumes of The Imposter's Handbook.\r\n\r\nI get to build a lot of fun things in my new position at Microsoft and I've been surprised at how often I use the things I've learned. Avoiding an obvious performance pitfall with Redis, for instance, because I understood the Big-O implications of the data structure I chose. Going back to ensure that a salt was added to a hash which stored sensitive data for an old client and, most importantly, discouraging a friend from trying to solve a problem that was very clearly NP-Complete.\r\n\r\nIn this talk I'll show you some of the fun things I've learned (like mod(%) and remainder being different things) and how I've applied them to the applications I create for my day job. You might know some of these concepts, or maybe you don't - either way: hopefully you'll leave with a few more tools under your belt to help you do your job better.has grown exponentially over the years, in both market size and developer frustration.\r\n \r\nIn this talk I will walk you through my first few months as an Azure Cloud Developer Engineer, tasked with getting to know Azure, from scratch, while building compelling applications with it. My job is two-fold: I get to show you why Azure is interesting and I then get to tell the Azure product team why it's not. This can be stressful. It can also be quite fun. I'll show you what I've come up with and then you get to decide.", - "startsAt": "2019-01-31T09:00:00", - "endsAt": "2019-01-31T10:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "ecb37172-c6af-49d1-bbb7-3e29ee4b300f", - "name": "Rob Conery" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10586, - "name": "Microsoft" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - { - "id": "68440", - "title": "Leadership Guide for the Reluctant Leader", - "description": "Regardless of the technology you know, regardless of the job title you have, you have amazing potential to impact your workplace, community, and beyond.\r\n\r\nIn this talk, I’ll share a few candid stories of my career failures… I mean… learning opportunities. We’ll start by debunking the myth that leadership == management. Next, we’ll talk about some the attributes, behaviors and skills of good leaders. Last, we’ll cover some practical steps and resources to accelerate your journey.\r\n\r\nYou’ll walk away with some essential leadership skills I believe anyone can develop, and a good dose of encouragement to be more awesome!", - "startsAt": "2019-01-31T10:20:00", - "endsAt": "2019-01-31T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "3884cc4d-8364-4316-9b9a-e16561d87af3", - "name": "David Neal" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10588, - "name": "People" - }, - { - "id": 10591, - "name": "Soft Skills" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - { - "id": "63675", - "title": "The State of C# - What Have I Missed?", - "description": "One of the most popular programming language on the market is getting even better. With every iteration of C# we get more and more features that are meant to make our lives as developers a lot easier. Support for writing (hopefully) better and more readable asynchronous code, being able to do pattern matching, tuples, deconstruction and much more. These are just a few of the many additions to C# that we’ve seen lately.\r\n\r\nJoin me in this session to explore what you’ve missed in one of the most fun to work with programming language on the market; C#!", - "startsAt": "2019-01-31T11:40:00", - "endsAt": "2019-01-31T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "1f8704d7-04db-4f09-9c0e-d5abcbc7c9ff", - "name": "Filip Ekberg" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - { - "id": "69240", - "title": "Small Steps, Giant Leaps: Engineering Lessons from Apollo", - "description": "On July 20th, 1969, Neil Armstrong and Buzz Aldrin became the first humans to set foot on another world. Billions of people tuned in live to watch Apollo 11 land on the moon, but behind Armstrong’s ‘one small step’ lay a decade of astonishing innovation. The Apollo programme wasn’t just about aerospace engineering; it was also responsible for revolutionary new approaches in project management and quality control; new ways of thinking about testing strategies and communications - not to mention delivering a completely bespoke set of hardware and software components that would play a vital role at every stage of the programme.\r\n\r\nAs we celebrate the fiftieth anniversary of the moon landings, let’s take a look back at the technology, processes and practises behind the Apollo programme - and how many of those techniques are still relevant today. What is ‘all-up testing’, and how does it apply to modern software development? Who was the CAPCOM - and what can they teach us about product ownership? How do you manage a distributed team of nearly half a million people? How do you manage scope creep when you’re working to a hard deadline with the whole world watching you? And how DO you fly to the moon and back using a computer with less processing power than an Apple II?", - "startsAt": "2019-01-31T13:40:00", - "endsAt": "2019-01-31T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "1d7dcbfc-1de6-4228-8bd6-04f4ba1c4267", - "name": "Dylan Beattie" - }, - { - "id": "bc20c5a9-2d7e-4830-827f-8919be0eba88", - "name": "Kevlin Henney" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10579, - "name": "Fun" - }, - { - "id": 10588, - "name": "People" - }, - { - "id": 10592, - "name": "Testing" - }, - { - "id": 10574, - "name": "Design" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - { - "id": "68814", - "title": "Scaling microservices with Message queues, .NET and Kubernetes", - "description": "When you design and build applications at scale, you deal with two significant challenges: scalability & robustness. You should design your service so that even if it is subject to intermittent heavy loads, it continues to operate reliably. But how do you build such applications? And how do you deploy an application that scales dynamically? Kubernetes has a feature called autoscaler where instances of your applications are increased or decreased automatically based on metrics that you define.\r\n\r\nIn this talk, you’ll learn how to design, package & deploy reliable .NET applications to Kubernetes & decouple several components using a message broker. You will also learn how to set autoscaling rules to cope with an increasing influx of messages in the queue.", - "startsAt": "2019-01-31T15:00:00", - "endsAt": "2019-01-31T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "964af3ac-fd5e-46f6-b582-6c0d2da30db4", - "name": "Lewis Denham-Parry" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10570, - "name": "Concurrency" - }, - { - "id": 10571, - "name": "Continuous Delivery" - }, - { - "id": 10576, - "name": "Docker" - }, - { - "id": 10575, - "name": "DevOps" - }, - { - "id": 10572, - "name": "Cross-Platform" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10586, - "name": "Microsoft" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - { - "id": "68608", - "title": "A practical guide to deep learning", - "description": "Machine Learning is one of the fastest growing areas of computer science, and Deep Learning (neural networks) is growing even faster, with lots of data and computing power at our fingertips. \r\nThis talk is a practical (very little math) guide to computer vision and deep learning.\r\n\r\nWe will look at a deep learning project from start to finish, look at how to program and train a neural network and gradually refine it using some tips and tricks that you can steal for your future deep learning projects.", - "startsAt": "2019-01-31T16:20:00", - "endsAt": "2019-01-31T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "cb70e0f2-0f0b-4b8f-b3f4-a9326309a1b2", - "name": "Tess Ferrandez-Norlander" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10584, - "name": "Machine Learning" - }, - { - "id": 10565, - "name": "AI" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - { - "id": "69332", - "title": ".NET Rocks Live on Software Feature Selection with Christine Yen", - "description": "Join Carl and Richard from .NET Rocks as they chat with Christine Yen from Honeycomb about how you select features to build in your applications.\r\n\r\nAfter the first version of software is out the door, what do you choose nest? Christine has a background in instrumenting applications to understand what people use – is that the best way to pick features? What about the vision of your own designers? What about asking the users? Bring your questions and come to this live recording of .NET Rocks!", - "startsAt": "2019-01-31T17:40:00", - "endsAt": "2019-01-31T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "d4d7850a-526e-4959-aab1-36460081fcf5", - "name": "Richard Campbell" - }, - { - "id": "bf171bb6-4c78-4fe9-ac77-2338d5ec7975", - "name": "Carl Franklin" - }, - { - "id": "e5d55e8e-93d1-4a53-bbec-10e4beaf5fd8", - "name": "Christine Yen" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - } - ], - "hasOnlyPlenumSessions": false - }, - { - "id": 2777, - "name": "Room 3", - "sessions": [ - { - "id": "68887", - "title": "ASP.NET Core: The One Hour Makeover", - "description": "The “out of the box” template has some lowest common denominator / simplicity tradeoffs that make it easy to understand and work with in a variety of scenarios, but there are lots of performance and deployment tweaks that experienced developers should make before deploying. If you had one hour to tweak a new project, what would you do? I'll include some top open source libraries, best practices from ASP.NET Community Standup links, recommendations from the ASP.NET Core team, etc.", - "startsAt": "2019-01-31T09:00:00", - "endsAt": "2019-01-31T10:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "c6f0ebfe-4c60-421c-b791-1aad49a18005", - "name": "Jon Galloway" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10596, - "name": "Web" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - { - "id": "67965", - "title": "Serverless with Knative", - "description": "When you build a serverless app, you either tie yourself to a cloud provider, or you end up building your own serverless stack. Knative provides a better choice. Knative extends Kubernetes to provide a set of middleware components (build, serving, events) for modern, source-centric, and container-based apps that can run anywhere. In this talk, we’ll see how we can use Knative primitives to build a serverless app that utilizes the Machine Learning magic of the cloud. ", - "startsAt": "2019-01-31T10:20:00", - "endsAt": "2019-01-31T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "f79e1173-a28c-4ad1-8885-7c52ba397fe3", - "name": "Mete Atamel" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10584, - "name": "Machine Learning" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10585, - "name": "Microservices" - }, - { - "id": 10590, - "name": "Serverless" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - { - "id": "67996", - "title": "Functional Web Programming in .Net with the SAFE Stack", - "description": "The SAFE stack is an open source stack of libraries and tools which simplify the process of building type safe web applications which run on the cloud almost entirely in F#. \r\n\r\nIn this talk we'll explore the components of the SAFE stack and how they can be used to write web services and web sites in idiomatic F#. We'll see how we can manage this without needing to compromise and use object oriented frameworks whilst also still integrating with the existing ASP.Net, JavaScript and React ecosystems. We'll consider how we can write backend applications using Saturn on top of ASP.Net, we'll look at how to run F# in the web browser with Fable and we'll cover how we can develop interactive web applications leveraging the benefits of functional programming. This talk is aimed at developers who are looking to understand how they can use F# to effectively build full stack web applications.", - "startsAt": "2019-01-31T11:40:00", - "endsAt": "2019-01-31T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "71cb7875-d2d8-45d1-ae12-7687bae03200", - "name": "Anthony Brown" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10580, - "name": "Functional Programming" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - { - "id": "61211", - "title": "Let’s Talk About Mental Health", - "description": "It’s a great time to be in technology. And yet despite the almost constant improvement in our tools, we somehow don’t spend time talking about how to maintain our most important tool - the one between our ears.\r\n\r\nConstantly feeling worn down, experiencing anxiety over making decisions, and burning out are *not* just facts of a developer’s life! They’re challenges that can be dealt with. In this talk we’ll cover the most common mental health challenges facing developers, and then learn about some techniques to supercharge your brain by improving your mental hygiene (whether you have a psychological disorder or not). Most importantly, you’ll learn how to have a conversation with your coworkers (and other people in your life) about supporting each other and finding your best selves.\r\n", - "startsAt": "2019-01-31T13:40:00", - "endsAt": "2019-01-31T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "fdf3c776-f100-41f5-bb22-7a1f16710740", - "name": "Arthur Doler" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10591, - "name": "Soft Skills" - }, - { - "id": 10588, - "name": "People" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - { - "id": "56795", - "title": "Zero to Mobile Hero - Intro to Xamarin and Visual Studio Team Services", - "description": "You can be faced with a nightmare of Xcode, Android Studio, Swift, Objective C, Swift and other options. This means not only learning multiple languages and frameworks but also having to support two different codebases for the same application. But Xamarin Native and Xamarin.Forms offer a powerful, cross-platform development solution for .NET developers looking to target smartphones, tablets, TV’s, computers and IoT devices.\r\n\r\nIn this talk, Luce shares what Xamarin is including Native and Xamarin.Forms for both C# and F#, how to get started creating a simple HelloWorld app from scratch and a more complex example (will involve at least one Azure service including Cognitive Services for facial recognition). Also how to use Visual Studio Team Services for Continuous Integration and some awesome examples of apps written using Xamarin including ones used to save lives!\r\n\r\nLuce will take examples from xamarin.com/customers as well as show this demo about how Xamarin was used alongside other technologies to aid with Skin Cancer prediction.\r\n\r\nThis talk will include slides, demos, code samples, live coding and the audience will walk away feeling like they too can create a mobile app in just a few minutes and carry their work around with them in their pocket or backpack!", - "startsAt": "2019-01-31T15:00:00", - "endsAt": "2019-01-31T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "79741134-06bb-4596-bc44-40edd9e03f6b", - "name": "Luce Carter" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10565, - "name": "AI" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10572, - "name": "Cross-Platform" - }, - { - "id": 10586, - "name": "Microsoft" - }, - { - "id": 10587, - "name": "Mobile" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - { - "id": "57812", - "title": "Build cross-platform mobile apps using Fabulous", - "description": "In recent years there has been a shift in the way websites and mobile apps are being built - moving to architectures with immutable models and virtual UIs - based on the MVU (model-view-update) pattern. This has lead to great new frameworks like ELM and React for web, and ReactNative for mobile.\r\n\r\nNow there is a new MVU framework for building mobile apps - Fabulous. It's a community-driven open source framework, combining the simplicity of an MVU framework, with 100% native API access for both iOS and Android, all built with using an established, world class, battle-hardened functional programming language.\r\n\r\nThis session will start with an overview of MVU, discussing how it works and why it is such a great architecture. It will then move on to building your first Fabulous app that runs on iOS and Android. Next up more features will be added to the app whilst the app is running on a device, showing the hot reload capabilities of Fabulous for both UI and app logic. Finally it will look at the underlying architecture, see how to use all of the iOS and Android APIs, see how to easily use native components such as cocoa pods or jars, and look at the massive range of libraries that this framework as available to it to do all manner of UI and application logic things. We'll even see how to use it on macOS and Windows, including being able to build iOS apps on Windows (with the help of a networked Mac, Apple licensing rules and whatnot).\r\n\r\nWhen looking at naming for this framework, someone suggested Fabulous. By the end of this session you will see why that name stuck.", - "startsAt": "2019-01-31T16:20:00", - "endsAt": "2019-01-31T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "75465aaf-45f4-4d3c-b78a-2e3d5206b57f", - "name": "Jim Bennett" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10587, - "name": "Mobile" - }, - { - "id": 10586, - "name": "Microsoft" - }, - { - "id": 10580, - "name": "Functional Programming" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - { - "id": "69228", - "title": "Dungeons, Dragons and Functions", - "description": "Dungeons & Dragons, or D&D, is the grand-daddy of all role playing games. While playing D&D is great fun, the rules are a bit daunting for the beginner. The basic rulebook, the PHB, clocks in at a solid 300 pages, and can be extended with multiple additional rule sets. This should come as no surprise to software engineers: this is, after all, documentation for a system that models a complex domain, and has been in use for over 40 years now, going through numerous redesigns over time.\r\n\r\nAs such, D&D rules make for a great exercise in domain modelling. In this talk, I will take you along my journey attempting to tame that monster. We will use no magic, but a weapon imbued with great power, F#; practical tips and tricks for the Adventurer on the functional road will be shared. So... roll 20 for initiative, and join us for an epic adventure in domain modeling with F#!", - "startsAt": "2019-01-31T17:40:00", - "endsAt": "2019-01-31T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "14879952-64d2-42b5-8d6f-d1e1a68b39c9", - "name": "Mathias Brandewinder" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - } - ], - "hasOnlyPlenumSessions": false - }, - { - "id": 2778, - "name": "Room 4", - "sessions": [ - { - "id": "66632", - "title": "A Practical Guide to Dashboarding.", - "description": "Monitoring is difficult. First, there is a vast choice of tooling and setup. Then, figuring out what information should be displayed, where and why can be confusing. Finally what should be alerted upon and how to avoid fatigue.\r\n\r\nTogether we will journey through a practical tour of dashboarding. Focusing on metrics, we will cover how to get information out of your applications using telemetry. I will show you how you might set up your monitoring infrastructure with a demo and talk through some hardened baselines. Finally, I’ll talk through a productionised setup including some gotchas to look out for.\r\n\r\nThis will be a whirlwind tour from start to finish of a practical guide to development dashboarding. ", - "startsAt": "2019-01-31T09:00:00", - "endsAt": "2019-01-31T10:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "c3956212-61f8-4098-94ee-35614895d317", - "name": "Jessica White" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10593, - "name": "Tools" - }, - { - "id": 10575, - "name": "DevOps" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - { - "id": "67271", - "title": "Hacking with Go", - "description": "Learning Go programming is easy. Go is popular and becomes even more also in security experts world. Wanted to feel a bit as a hacker? Learn a new language? Or do both at the same time? This session is about it. \r\nSo let's jump into hands-on session and explore how security tools can be written in Go. How to enumerate network resources, extract an information, sniff packets and do port scanning, brute force and more all with Go. \r\nBy the end, you will have more ideas what else can be written or re-written in Go. ", - "startsAt": "2019-01-31T10:20:00", - "endsAt": "2019-01-31T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "4c3efe89-ab58-4b28-a9c3-78251f25ee06", - "name": "Viktorija Almazova" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10589, - "name": "Security" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - { - "id": "57079", - "title": "Augmented Reality - The State of Play", - "description": "Augmented Reality is far more than a Pokémon Go thing now. The hype is real, and many big players (Google, Microsoft, Apple, Facebook, you name it) are pushing AR to become ubiquitous. Hence the abundance of different approaches to AR, a significant need for content creators and creative ways of tackling problems using new techniques.\r\n\r\nIs mobile AR superior to HMDs? What's AR Cloud and why it's important? What are real-world cases solved with AR? Is this all still sci-fi or should you start caring? This session presents the current state of AR, showcases its real capabilities, and demonstrates that we are on the verge of a revolution in how humans interact with digital content.", - "startsAt": "2019-01-31T11:40:00", - "endsAt": "2019-01-31T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "7236f293-a77b-436c-93aa-318f10536a14", - "name": "Rafał Legiędź" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10603, - "name": "VR" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - { - "id": "68736", - "title": "Build Nodejs APIs using Serverless on Azure", - "description": "Serverless lets you focus on coding and testing instead of provisioning infrastructure, configuring web servers, debugging your configuration, managing security settings, and all the drudgery normally associated with getting an app up and running. In this session with, you’ll discover how to migrate an API of an existing app to Azure Functions. You’ll learn how to use Visual Studio Code and the Azure Functions extension to speed up your work. After this session, you’ll join the ranks of serverless developers.", - "startsAt": "2019-01-31T13:40:00", - "endsAt": "2019-01-31T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "047b0c14-4a5f-4f2a-bd84-03b7fef87c4b", - "name": "Simona Cotin" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10582, - "name": "JavaScript" - }, - { - "id": 10590, - "name": "Serverless" - }, - { - "id": 10569, - "name": "Cloud" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - { - "id": "68161", - "title": "ML.NET for developers without any AI experience", - "description": "AI talk is everywhere but where do you start as a .NET developer? During this session, we will explore how you can use AI in the applications your creating today. How to start building & training your ML models with your .NET skills through ML.NET. \r\n\r\nWant to detect laughter in a phone conversation? Detect the mood of Jira tickets or predict if/where your code has bugs. This session will get you started with AI and ML.NET.", - "startsAt": "2019-01-31T15:00:00", - "endsAt": "2019-01-31T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "8061571c-bb36-42a9-b714-4d90c98529fd", - "name": "Lee Mallon" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10565, - "name": "AI" - }, - { - "id": 10584, - "name": "Machine Learning" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - { - "id": "68212", - "title": "Reverse Engineering a Bluetooth Lightbulb", - "description": "I recently made build lights for the company I work for and my home office. They integrate with TeamCity and indicate when a build is running and success/failure of all the tests. In this session, we will reverse engineer a bluetooth light bulb’s protocol, learn how to have an Raspberry Pi communicate with the bulb, and by the end you too will know how to make your own build lights! Please note that this talk will be highly technical. We will be discussing low level details of bluetooth communication, protocol analysis with Wireshark, sniffing bluetooth packets, etc.", - "startsAt": "2019-01-31T16:20:00", - "endsAt": "2019-01-31T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "86d72d85-ef02-405e-b0de-1603dae6b8fb", - "name": "Jesse Phelps" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10606, - "name": "Embedded" - }, - { - "id": 10581, - "name": "IoT" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - { - "id": "64248", - "title": "Data on the Inside, Data on the Outside", - "description": "When we move from a monolith to microservices we abandon integrating via a shared database, as each service must own its own data to allow them it to be autonomous. But now we have a new problem, our data is distributed. What happens if I need one service needs to talk to another about a shared concept such as a product, a hotel room, or an order? Does every service need to have a list of all our users? Who knows what users have permissions to the entities within the micro service? What happens if my REST endpoint needs to include data from a graph that includes other services to make it responsive? And I am not breaking the boundary of my service when all of this data leaves my service boundary in response to a request?\r\n\r\nNaive solutions result in chatty calls as each service engages with multiple other services to fulfil a request, or in large message payloads as services add all the data required to process a message to each message. Neither scale well.\r\n\r\nIn 2005, Pat Helland wrote a paper ‘Data on the Inside vs. Data on the Outside’ which answers the question by distinguishing between data a service owns and reference data that it can use. In this presentation we will explain reference data, how it is classified, and how it should be implemented. We will include a discussion of using reference data from ATOM feeds, discrete messaging and event streams. We’ll provide examples in C#, Python and Go as well as using RMQ and Kafka.", - "startsAt": "2019-01-31T17:40:00", - "endsAt": "2019-01-31T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "84ffe422-5bc6-4075-9903-d9ad3526cf86", - "name": "Ian Cooper" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10585, - "name": "Microservices" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - } - ], - "hasOnlyPlenumSessions": false - }, - { - "id": 2779, - "name": "Room 5", - "sessions": [ - { - "id": "68607", - "title": "Let’s talk patterns", - "description": "At some point in your life, you start realizing that re-inventing the wheel isn't the best way to spend your time. Especially since Bob Wheel Sr. perfected that invention many, many years ago. And it's the same with software. Smart people have already encountered a lot of the problems that we face every day while building software. Some of them have even been nice enough to write down their solutions in so called \"patterns\". So why not stand on the shoulders of...well...maybe not giants...but at least very smart people who were born before you, and build on top of their hard-earned wisdom?\r\nThis session, will walk you through a bunch of really useful patterns, and you'll not only learn their names, but also why they are useful and how to implement them in .NET. And maybe, just maybe, you'll even see that one pattern that solves that problem you are working on at the moment. But even if you don't see that one pattern that you need, you will at least get a few that you can store in your toolbelt for future problems.\r\n", - "startsAt": "2019-01-31T09:00:00", - "endsAt": "2019-01-31T10:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "239cf374-ad4d-4877-a5e5-951cb4cd9291", - "name": "Chris Klug" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - { - "id": "68678", - "title": "Why should you care about edge computing?", - "description": "Recent technologies are enabling a host of new scenarios for doing data collection and analytics much closer to the source, at the \"edge\" so to speak. \r\n\r\nHow can using Artificial Intelligence in a cheap device the size of a matchbox change the way you do things? What kind of scenarios does this open up for business owners, enabling new opportunities for you and your company? What are the actual benefits for connecting the cloud and the edge in this way? \r\n\r\nI'll give you some examples and demonstrate how Edge Computing can enable new scenarios and new business.\r\n", - "startsAt": "2019-01-31T10:20:00", - "endsAt": "2019-01-31T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "fb75b901-4842-4858-ba35-8c370db0af14", - "name": "Glenn F. Henriksen" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10606, - "name": "Embedded" - }, - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10569, - "name": "Cloud" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - { - "id": "67079", - "title": "Keeping it DRYer with Templates", - "description": "One common practice to write maintainable code is to minimise repetition, often referred to as DRY or Don't Repeat Yourself.\r\n\r\nHowever, have you ever considered how much you repeat yourself when you create a new .NET application? \r\n\r\nYou've found your ideal architecture and folder structure and now every time you create a new project you have to create the file structure then add all the different project types you need.\r\n\r\nDon't forget all those NuGet dependencies too and the boilerplate code from other projects you\r\ncontinually copy in. \r\n\r\nIn this talk you'll learn the different ways you can create custom templates for .NET projects using the dotnet CLI, Visual Studio templates and Yeoman, helping to reduce repetition, write better applications, apply incremental improvements, all whilst saving you time and effort. ", - "startsAt": "2019-01-31T11:40:00", - "endsAt": "2019-01-31T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "ac105033-2b20-4b45-8d47-5647d8accf84", - "name": "Layla Porter" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10566, - "name": "Architecture" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - { - "id": "65854", - "title": "Think Like a Trainer: Improving Your Communication Skills", - "description": "Think back to a time when you were in a conversation that could have gone better. Perhaps you said something the wrong way, or you walked away from the conversation not fully knowing if the other person even understood what you were trying to convey.\r\n\r\nTechnical trainers rely on effective communication as the foundation of everything that we do. We help end users to learn how to use software and adjust to new workflows, through the process of constantly adapting to different backgrounds, skill levels, and learning styles.\r\n\r\nIn this session, you’ll learn actionable strategies to begin thinking like a trainer, including:\r\n\r\n- Using active listening techniques to communicate with empathy.\r\n\r\n- Best practices for explaining technical concepts in non-technical terms.\r\n\r\n- Adjusting your communication approach for different communication styles.\r\n\r\n- Using problem solving skills to help you get unstuck during difficult conversations.", - "startsAt": "2019-01-31T13:40:00", - "endsAt": "2019-01-31T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "25cc75bc-df7b-42ad-a3e4-e0bfa8af7f01", - "name": "Olivia Liddell" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10588, - "name": "People" - }, - { - "id": 10591, - "name": "Soft Skills" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - { - "id": "66437", - "title": "(WPF + WinForms) * .NET Core = Modern Desktop", - "description": "Learn how .NET Core 3 brings WPF and Windows Forms into the future with a modern runtime. See what’s new for WPF and Windows Forms, learn how to easily retarget your .NET Framework application over to .NET Core, and how to get these modern desktop apps to your users.\r\n", - "startsAt": "2019-01-31T15:00:00", - "endsAt": "2019-01-31T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "8b1783d3-15ce-41dc-b989-386759803d97", - "name": "Oren Novotny" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10594, - "name": "UI" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - { - "id": "66866", - "title": "An Introduction to WebAssembly", - "description": "Want to write a web application? Better get familiar with JavaScript JavaScript has long been the king of front-end. While there have been various attempts to dethrone it, they have typically involved treating JavaScript as an assembly-language analog that you transpile your code to. This has lead to complex build pipelines that result in JavaScript which the browser has to parse and *you* still have to debug. But what if there were an actual byte-code language you could compile your non-JavaScript code to instead? That is what WebAssembly is.\r\n\r\nI'm going to explain how WebAssembly works and how to use it in this talk. I'll cover what it is, how it fits into your application, and how to build and use your own WebAssembly modules. And, I'll demo how to build and use those modules with both Rust and the WebAssembly Text Format. That's right, I'll be live coding in an assembly language. I'll also go over some online resources for other languages and tools that make use of WebAssembly.\r\n\r\nWhen we're done, you'll have the footing you need to start building applications featuring WebAssembly. So grab a non-JavaScript language, a modern browser, and let's and get started!", - "startsAt": "2019-01-31T16:20:00", - "endsAt": "2019-01-31T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "520bf4ca-b2d3-47c3-8475-c25bb2b257f7", - "name": "Guy Royse" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10596, - "name": "Web" - }, - { - "id": 10582, - "name": "JavaScript" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - { - "id": "68009", - "title": "Scaling Frontend Development", - "description": "Abstract\r\nLarge frontend projects suffer from all of the same problems of other software projects with the same characteristics:\r\nCommunication and coordination overhead\r\nSpeed of delivery\r\nLarge quantum size\r\nLow productivity \r\n\r\nThese factors are growing concerns for companies as productivity and speed of delivery is nowadays crucial for success in this competitive landscape\r\n\r\nA common way of solving many of these issues in software projects is the microservices approach.\r\n\r\nToday a similar approach of applying this same pattern to the frontend is being popularized and is commonly nominated as micro-frontends.\r\n\r\nHowever this approach has many fallacies because of frontend specific characteristics:\r\n- The performance cost of loading many independent applications\r\n- The need for a common visual language and experience\r\n- The browser is a monolithic runtime \r\n\r\nDescription\r\nThis talk will be about the problems of large frontend projects and how to scale them in a way that balances team autonomy with performance and productivity\r\n\r\nI’ll talk about how at farfetch we’re progressively refactoring our frontend to multiple independent applications, and the strategies we’re using to make sure that despite having many applications made by different independent and geographically distributed teams we still can deliver a performant and consistent product to the end user.\r\n", - "startsAt": "2019-01-31T17:40:00", - "endsAt": "2019-01-31T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "f79c1f81-b367-4ce0-9cc0-4263f30a9f7f", - "name": "luis vieira" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10594, - "name": "UI" - }, - { - "id": 10585, - "name": "Microservices" - }, - { - "id": 10582, - "name": "JavaScript" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - } - ], - "hasOnlyPlenumSessions": false - }, - { - "id": 2780, - "name": "Room 6", - "sessions": [ - { - "id": "69354", - "title": "Deep Learning with PyTorch", - "description": "Deep Learning is fast becoming an indispensable approach to getting the most from your data. In this session attendees will learn both how Deep Learning fits into the Artificial Intelligence landscape as well as how to get started using PyTorch. The session will start with the basic intuitions behind the problem setup, models, and optimization methods used to solve computer vision problems.\r\n\r\nAttendees should come away with a strong foundation of how to both create deep learning models as well as how to consume them in their applications. Prior exposure to PyTorch is definitely not expected.", - "startsAt": "2019-01-31T10:20:00", - "endsAt": "2019-01-31T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "1825cfcf-5ad4-4ab2-94cb-1de5735cac83", - "name": "Seth Juarez" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - }, - { - "id": "59563", - "title": "Skip the first three months of development for your next app", - "description": "Five amazing ways using the emerging cloud ecosystem can save you time. The true power of serverless comes from using not just the execution service, but the whole platform around it. This talk/demo shows how teams can use AWS Lambda with Cognito, IOT, Kinesis and S3 to achieve in a few hours what usually takes the the first three months of application development.", - "startsAt": "2019-01-31T11:40:00", - "endsAt": "2019-01-31T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "1eb07015-2101-4cf7-91b9-f255752af538", - "name": "Gojko Adzic" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10593, - "name": "Tools" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10571, - "name": "Continuous Delivery" - }, - { - "id": 10590, - "name": "Serverless" - }, - { - "id": 10585, - "name": "Microservices" - }, - { - "id": 10581, - "name": "IoT" - }, - { - "id": 10575, - "name": "DevOps" - } - ], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - }, - { - "id": "66322", - "title": "Accessible App Design", - "description": "Want to start building apps for people with disabilities but doesn’t no where to start? In this session we cover everything to start right now! There are many people with learning disabilities around the world. There are also people with autism, psychological disabilities… Many of them are also entering the era of mobile and internet. We talk about design guidelines that can reach them. \r\n\r\nWe talk about apps, but do not focus on a specific technology in this talk. Which apps are needed? Which steps of design helps them to catch the frontiers of mobile and internet right now? Microsoft and other big tech companies are working more and more about inclusive design and digital inclusion for people with disabilities. ", - "startsAt": "2019-01-31T15:00:00", - "endsAt": "2019-01-31T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "67a075a3-a111-4116-bd44-a25a01485959", - "name": "Dennie Declercq" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10591, - "name": "Soft Skills" - }, - { - "id": 10594, - "name": "UI" - }, - { - "id": 10595, - "name": "UX" - } - ], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - }, - { - "id": "58551", - "title": "System Stable : Robust connected applications with Polly, the .NET Resilience Framework", - "description": "Short Description\r\n\r\nJoin me for this session and I will show you how with just a few lines of code, you can make your applications much more resilient and reliable. With Polly, the .NET resilience framework, your application can easily tolerate transient faults and longer outages in remote systems or infrastructure. \r\n\r\nAt the end of this hour you will know how to use all the features of Polly to make your application a rock solid piece of work. We’ll cover the reactive and proactive resilience strategies, starting with simple but very powerful retries and finishing with bulkhead isolation.\r\nOh, and did I mention Polly is a .NET Standard library so it will work on any application you can think of! Join me for an hour, and your applications will never be the same.\r\n\r\n----------------------------------------------------------------------------------------------------------------------------------\r\n\r\nFull Description\r\n\r\nJoin me for this session and I will show you how with just a few lines of code, you can make your applications much more resilient and reliable. Let me tell you more… \r\n\r\nAlmost all applications now depend on connectivity, but what do you do when the infrastructure is unreliable or the remote system is down or returns an error? Does your application grind to a halt or just drop that single request? What if you could recover from these kinds of error, maybe even so quickly it won’t be noticed? \r\n \r\nWith Polly your application can easily tolerate transient faults and longer outages in remote systems or infrastructure. \r\n\r\nAt the end of this hour you will know how to use all the features of Polly to make your application a rock solid piece of work. \r\n\r\nWe’ll start with the simple but very powerful Retry Policy which lets you retry a failed request. If simple retries are not good enough for you, there is a Wait and Retry policy which introduces a delay between retries, giving the remote service time to recover before being hit again. Then I show you how to use the circuit breaker for when things have really gone wrong and a remote system is struggling under too much load or has failed. If all these attempts are unsuccessful and you are still not getting through to the remote system, you can return a default response or execute arbitrary code to call for human help (or restart the cloud) with the fallback policy. \r\n\r\nThat takes care of what you can do when things go wrong, but Polly also lets you take proactive steps to keep your application and the services it depends on healthy. \r\n\r\nTo get you started with proactive strategies, you will learn how caching can be used to store and return responses from an in-memory or distributed cache without having to hit the remote server every time. Or you can use bulkhead isolation to marshal resources within your application so that no one struggling part can take down the whole. Finally, I’ll show you how to fail quickly when your application is in danger of being overloaded or the remote systems is not responding in a timely fashion, this is done with the bulkhead isolation and the timeout polices. \r\n\r\nOh, and did I mention Polly is a .NET Standard library so it will work on any application you can think of! Join me for an hour, and your applications will never be the same. ", - "startsAt": "2019-01-31T16:20:00", - "endsAt": "2019-01-31T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "de972e57-7765-4c38-9dcd-5981587c1433", - "name": "Bryan Hogan" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10596, - "name": "Web" - }, - { - "id": 10587, - "name": "Mobile" - }, - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - }, - { - "id": "68611", - "title": "Clean Architecture with ASP.NET Core 2.2", - "description": "The explosive growth of web frameworks and the demands of users have changed the approach to building web applications. Many challenges exist, and getting started can be a daunting prospect. Let's change that now.\r\n\r\nThis talk provides practical guidance and recommendations. We will cover architecture, technologies, tools, and frameworks. We will examine strategies for organizing your projects, folders and files. We will design a system that is simple to build and maintain - all the way from development to production. You leave this talk inspired and prepared to take your enterprise application development to the next level.", - "startsAt": "2019-01-31T17:40:00", - "endsAt": "2019-01-31T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "3a5abb12-c9e2-4641-8ace-a4c067ad8e8d", - "name": "Jason Taylor" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - } - ], - "hasOnlyPlenumSessions": false - } - ], - "timeSlots": [ - { - "slotStart": "09:00:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "session": { - "id": "69333", - "title": "How We Got Here - The History of Web Development", - "description": "The Internet existed before the Web, but the Web redefined the Internet - what started out as a protocol for helping scientists share documents and references has turned into one of the most important forces in the 21st century. But how did we get here?\r\n\r\nJoin Richard Campbell as he tells the story of the World Wide Web and the web development tools and techniques that made it all possible. From the early versions of HTML where you laid out web pages with tables (GeoCities anyone?) and simple scripting languages to CSS, JavaScript and HTML 5, leading to Single Page Applications, Progressive Web Apps and Web Assembly! We've come a long way, and the story is continuing!", - "startsAt": "2019-01-31T09:00:00", - "endsAt": "2019-01-31T10:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "d4d7850a-526e-4959-aab1-36460081fcf5", - "name": "Richard Campbell" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10596, - "name": "Web" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - "index": 0 - }, - { - "id": 2776, - "name": "Room 2", - "session": { - "id": "69266", - "title": "CompSci and My Day Job", - "description": "4 years ago I had a vague idea about Big-O notation and absolutely no clue about combinatorial problems. I knew what a SHA256 hash was (sort of) but I didn't know how it was created, nor that it didn't completely protect some of my data. I knew these things were important, but I never understood how they could apply to the types of applications I was building at the time. All of this changed as I put together the first two volumes of The Imposter's Handbook.\r\n\r\nI get to build a lot of fun things in my new position at Microsoft and I've been surprised at how often I use the things I've learned. Avoiding an obvious performance pitfall with Redis, for instance, because I understood the Big-O implications of the data structure I chose. Going back to ensure that a salt was added to a hash which stored sensitive data for an old client and, most importantly, discouraging a friend from trying to solve a problem that was very clearly NP-Complete.\r\n\r\nIn this talk I'll show you some of the fun things I've learned (like mod(%) and remainder being different things) and how I've applied them to the applications I create for my day job. You might know some of these concepts, or maybe you don't - either way: hopefully you'll leave with a few more tools under your belt to help you do your job better.has grown exponentially over the years, in both market size and developer frustration.\r\n \r\nIn this talk I will walk you through my first few months as an Azure Cloud Developer Engineer, tasked with getting to know Azure, from scratch, while building compelling applications with it. My job is two-fold: I get to show you why Azure is interesting and I then get to tell the Azure product team why it's not. This can be stressful. It can also be quite fun. I'll show you what I've come up with and then you get to decide.", - "startsAt": "2019-01-31T09:00:00", - "endsAt": "2019-01-31T10:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "ecb37172-c6af-49d1-bbb7-3e29ee4b300f", - "name": "Rob Conery" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10586, - "name": "Microsoft" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - "index": 1 - }, - { - "id": 2777, - "name": "Room 3", - "session": { - "id": "68887", - "title": "ASP.NET Core: The One Hour Makeover", - "description": "The “out of the box” template has some lowest common denominator / simplicity tradeoffs that make it easy to understand and work with in a variety of scenarios, but there are lots of performance and deployment tweaks that experienced developers should make before deploying. If you had one hour to tweak a new project, what would you do? I'll include some top open source libraries, best practices from ASP.NET Community Standup links, recommendations from the ASP.NET Core team, etc.", - "startsAt": "2019-01-31T09:00:00", - "endsAt": "2019-01-31T10:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "c6f0ebfe-4c60-421c-b791-1aad49a18005", - "name": "Jon Galloway" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10596, - "name": "Web" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - "index": 2 - }, - { - "id": 2778, - "name": "Room 4", - "session": { - "id": "66632", - "title": "A Practical Guide to Dashboarding.", - "description": "Monitoring is difficult. First, there is a vast choice of tooling and setup. Then, figuring out what information should be displayed, where and why can be confusing. Finally what should be alerted upon and how to avoid fatigue.\r\n\r\nTogether we will journey through a practical tour of dashboarding. Focusing on metrics, we will cover how to get information out of your applications using telemetry. I will show you how you might set up your monitoring infrastructure with a demo and talk through some hardened baselines. Finally, I’ll talk through a productionised setup including some gotchas to look out for.\r\n\r\nThis will be a whirlwind tour from start to finish of a practical guide to development dashboarding. ", - "startsAt": "2019-01-31T09:00:00", - "endsAt": "2019-01-31T10:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "c3956212-61f8-4098-94ee-35614895d317", - "name": "Jessica White" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10593, - "name": "Tools" - }, - { - "id": 10575, - "name": "DevOps" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - "index": 3 - }, - { - "id": 2779, - "name": "Room 5", - "session": { - "id": "68607", - "title": "Let’s talk patterns", - "description": "At some point in your life, you start realizing that re-inventing the wheel isn't the best way to spend your time. Especially since Bob Wheel Sr. perfected that invention many, many years ago. And it's the same with software. Smart people have already encountered a lot of the problems that we face every day while building software. Some of them have even been nice enough to write down their solutions in so called \"patterns\". So why not stand on the shoulders of...well...maybe not giants...but at least very smart people who were born before you, and build on top of their hard-earned wisdom?\r\nThis session, will walk you through a bunch of really useful patterns, and you'll not only learn their names, but also why they are useful and how to implement them in .NET. And maybe, just maybe, you'll even see that one pattern that solves that problem you are working on at the moment. But even if you don't see that one pattern that you need, you will at least get a few that you can store in your toolbelt for future problems.\r\n", - "startsAt": "2019-01-31T09:00:00", - "endsAt": "2019-01-31T10:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "239cf374-ad4d-4877-a5e5-951cb4cd9291", - "name": "Chris Klug" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - "index": 4 - } - ] - }, - { - "slotStart": "10:20:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "session": { - "id": "69344", - "title": "Structure and Interpretation of Test Cases", - "description": "Throw a line of code into many codebases and it's sure to hit one or more testing frameworks. There's no shortage of frameworks for testing, each with their particular spin and set of conventions, but that glut is not always matched by a clear vision of how to structure and use tests — a framework is a vehicle, but you still need to know how to drive.\r\n\r\nThis talk takes a deep dive into testing, with a strong focus on unit testing, looking at examples and counterexamples in different languages and frameworks, from naming to nesting, exploring the benefits of data-driven testing, the trade-offs between example-based and property-based testing, how to get the most out of the common given–when–then refrain and knowing how far to follow it.", - "startsAt": "2019-01-31T10:20:00", - "endsAt": "2019-01-31T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "bc20c5a9-2d7e-4830-827f-8919be0eba88", - "name": "Kevlin Henney" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10574, - "name": "Design" - }, - { - "id": 10564, - "name": "Agile" - }, - { - "id": 10592, - "name": "Testing" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - "index": 0 - }, - { - "id": 2776, - "name": "Room 2", - "session": { - "id": "68440", - "title": "Leadership Guide for the Reluctant Leader", - "description": "Regardless of the technology you know, regardless of the job title you have, you have amazing potential to impact your workplace, community, and beyond.\r\n\r\nIn this talk, I’ll share a few candid stories of my career failures… I mean… learning opportunities. We’ll start by debunking the myth that leadership == management. Next, we’ll talk about some the attributes, behaviors and skills of good leaders. Last, we’ll cover some practical steps and resources to accelerate your journey.\r\n\r\nYou’ll walk away with some essential leadership skills I believe anyone can develop, and a good dose of encouragement to be more awesome!", - "startsAt": "2019-01-31T10:20:00", - "endsAt": "2019-01-31T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "3884cc4d-8364-4316-9b9a-e16561d87af3", - "name": "David Neal" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10588, - "name": "People" - }, - { - "id": 10591, - "name": "Soft Skills" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - "index": 1 - }, - { - "id": 2777, - "name": "Room 3", - "session": { - "id": "67965", - "title": "Serverless with Knative", - "description": "When you build a serverless app, you either tie yourself to a cloud provider, or you end up building your own serverless stack. Knative provides a better choice. Knative extends Kubernetes to provide a set of middleware components (build, serving, events) for modern, source-centric, and container-based apps that can run anywhere. In this talk, we’ll see how we can use Knative primitives to build a serverless app that utilizes the Machine Learning magic of the cloud. ", - "startsAt": "2019-01-31T10:20:00", - "endsAt": "2019-01-31T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "f79e1173-a28c-4ad1-8885-7c52ba397fe3", - "name": "Mete Atamel" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10584, - "name": "Machine Learning" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10585, - "name": "Microservices" - }, - { - "id": 10590, - "name": "Serverless" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - "index": 2 - }, - { - "id": 2778, - "name": "Room 4", - "session": { - "id": "67271", - "title": "Hacking with Go", - "description": "Learning Go programming is easy. Go is popular and becomes even more also in security experts world. Wanted to feel a bit as a hacker? Learn a new language? Or do both at the same time? This session is about it. \r\nSo let's jump into hands-on session and explore how security tools can be written in Go. How to enumerate network resources, extract an information, sniff packets and do port scanning, brute force and more all with Go. \r\nBy the end, you will have more ideas what else can be written or re-written in Go. ", - "startsAt": "2019-01-31T10:20:00", - "endsAt": "2019-01-31T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "4c3efe89-ab58-4b28-a9c3-78251f25ee06", - "name": "Viktorija Almazova" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10589, - "name": "Security" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - "index": 3 - }, - { - "id": 2779, - "name": "Room 5", - "session": { - "id": "68678", - "title": "Why should you care about edge computing?", - "description": "Recent technologies are enabling a host of new scenarios for doing data collection and analytics much closer to the source, at the \"edge\" so to speak. \r\n\r\nHow can using Artificial Intelligence in a cheap device the size of a matchbox change the way you do things? What kind of scenarios does this open up for business owners, enabling new opportunities for you and your company? What are the actual benefits for connecting the cloud and the edge in this way? \r\n\r\nI'll give you some examples and demonstrate how Edge Computing can enable new scenarios and new business.\r\n", - "startsAt": "2019-01-31T10:20:00", - "endsAt": "2019-01-31T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "fb75b901-4842-4858-ba35-8c370db0af14", - "name": "Glenn F. Henriksen" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10606, - "name": "Embedded" - }, - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10569, - "name": "Cloud" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - "index": 4 - }, - { - "id": 2780, - "name": "Room 6", - "session": { - "id": "69354", - "title": "Deep Learning with PyTorch", - "description": "Deep Learning is fast becoming an indispensable approach to getting the most from your data. In this session attendees will learn both how Deep Learning fits into the Artificial Intelligence landscape as well as how to get started using PyTorch. The session will start with the basic intuitions behind the problem setup, models, and optimization methods used to solve computer vision problems.\r\n\r\nAttendees should come away with a strong foundation of how to both create deep learning models as well as how to consume them in their applications. Prior exposure to PyTorch is definitely not expected.", - "startsAt": "2019-01-31T10:20:00", - "endsAt": "2019-01-31T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "1825cfcf-5ad4-4ab2-94cb-1de5735cac83", - "name": "Seth Juarez" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - }, - "index": 5 - } - ] - }, - { - "slotStart": "11:40:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "session": { - "id": "68994", - "title": "Beyond Developer", - "description": "When I started in IT the roles were clearly separated. Business Analysts wrote requirements, Architects designed them, Programmers wrote the code, Testers tested the software.\r\n\r\nOver the last decade or so we have seen a shift towards “generalising specialists” who can cut code, understand a business domain, design a user interface, participate in and automate some of the testing and deployment activities, and who are sometimes even responsible for the health and wellbeing of their own systems in production.\r\n\r\nTo succeed in this new world requires more than “3 years of Java”. The modern developer needs to be constantly reinventing themselves, learning, and helping others to do the same. In this session, Dan explores some of the skills and characteristics of the modern developer, and suggests some ways you can grow them for yourself.", - "startsAt": "2019-01-31T11:40:00", - "endsAt": "2019-01-31T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "d06cbb07-240c-4dd9-9c3d-4fd585e084fd", - "name": "Dan North" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10588, - "name": "People" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - "index": 0 - }, - { - "id": 2776, - "name": "Room 2", - "session": { - "id": "63675", - "title": "The State of C# - What Have I Missed?", - "description": "One of the most popular programming language on the market is getting even better. With every iteration of C# we get more and more features that are meant to make our lives as developers a lot easier. Support for writing (hopefully) better and more readable asynchronous code, being able to do pattern matching, tuples, deconstruction and much more. These are just a few of the many additions to C# that we’ve seen lately.\r\n\r\nJoin me in this session to explore what you’ve missed in one of the most fun to work with programming language on the market; C#!", - "startsAt": "2019-01-31T11:40:00", - "endsAt": "2019-01-31T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "1f8704d7-04db-4f09-9c0e-d5abcbc7c9ff", - "name": "Filip Ekberg" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - "index": 1 - }, - { - "id": 2777, - "name": "Room 3", - "session": { - "id": "67996", - "title": "Functional Web Programming in .Net with the SAFE Stack", - "description": "The SAFE stack is an open source stack of libraries and tools which simplify the process of building type safe web applications which run on the cloud almost entirely in F#. \r\n\r\nIn this talk we'll explore the components of the SAFE stack and how they can be used to write web services and web sites in idiomatic F#. We'll see how we can manage this without needing to compromise and use object oriented frameworks whilst also still integrating with the existing ASP.Net, JavaScript and React ecosystems. We'll consider how we can write backend applications using Saturn on top of ASP.Net, we'll look at how to run F# in the web browser with Fable and we'll cover how we can develop interactive web applications leveraging the benefits of functional programming. This talk is aimed at developers who are looking to understand how they can use F# to effectively build full stack web applications.", - "startsAt": "2019-01-31T11:40:00", - "endsAt": "2019-01-31T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "71cb7875-d2d8-45d1-ae12-7687bae03200", - "name": "Anthony Brown" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10580, - "name": "Functional Programming" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - "index": 2 - }, - { - "id": 2778, - "name": "Room 4", - "session": { - "id": "57079", - "title": "Augmented Reality - The State of Play", - "description": "Augmented Reality is far more than a Pokémon Go thing now. The hype is real, and many big players (Google, Microsoft, Apple, Facebook, you name it) are pushing AR to become ubiquitous. Hence the abundance of different approaches to AR, a significant need for content creators and creative ways of tackling problems using new techniques.\r\n\r\nIs mobile AR superior to HMDs? What's AR Cloud and why it's important? What are real-world cases solved with AR? Is this all still sci-fi or should you start caring? This session presents the current state of AR, showcases its real capabilities, and demonstrates that we are on the verge of a revolution in how humans interact with digital content.", - "startsAt": "2019-01-31T11:40:00", - "endsAt": "2019-01-31T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "7236f293-a77b-436c-93aa-318f10536a14", - "name": "Rafał Legiędź" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10603, - "name": "VR" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - "index": 3 - }, - { - "id": 2779, - "name": "Room 5", - "session": { - "id": "67079", - "title": "Keeping it DRYer with Templates", - "description": "One common practice to write maintainable code is to minimise repetition, often referred to as DRY or Don't Repeat Yourself.\r\n\r\nHowever, have you ever considered how much you repeat yourself when you create a new .NET application? \r\n\r\nYou've found your ideal architecture and folder structure and now every time you create a new project you have to create the file structure then add all the different project types you need.\r\n\r\nDon't forget all those NuGet dependencies too and the boilerplate code from other projects you\r\ncontinually copy in. \r\n\r\nIn this talk you'll learn the different ways you can create custom templates for .NET projects using the dotnet CLI, Visual Studio templates and Yeoman, helping to reduce repetition, write better applications, apply incremental improvements, all whilst saving you time and effort. ", - "startsAt": "2019-01-31T11:40:00", - "endsAt": "2019-01-31T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "ac105033-2b20-4b45-8d47-5647d8accf84", - "name": "Layla Porter" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10566, - "name": "Architecture" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - "index": 4 - }, - { - "id": 2780, - "name": "Room 6", - "session": { - "id": "59563", - "title": "Skip the first three months of development for your next app", - "description": "Five amazing ways using the emerging cloud ecosystem can save you time. The true power of serverless comes from using not just the execution service, but the whole platform around it. This talk/demo shows how teams can use AWS Lambda with Cognito, IOT, Kinesis and S3 to achieve in a few hours what usually takes the the first three months of application development.", - "startsAt": "2019-01-31T11:40:00", - "endsAt": "2019-01-31T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "1eb07015-2101-4cf7-91b9-f255752af538", - "name": "Gojko Adzic" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10593, - "name": "Tools" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10571, - "name": "Continuous Delivery" - }, - { - "id": 10590, - "name": "Serverless" - }, - { - "id": 10585, - "name": "Microservices" - }, - { - "id": 10581, - "name": "IoT" - }, - { - "id": 10575, - "name": "DevOps" - } - ], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - }, - "index": 5 - } - ] - }, - { - "slotStart": "13:40:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "session": { - "id": "69052", - "title": "Blazor, a new framework for browser-based .NET apps", - "description": "Today, nearly all browser-based apps are written in JavaScript (or similar languages that transpile to it). That’s fine, but there’s no good reason to limit our industry to basically one language when so many powerful and mature alternate languages and programming platforms exist. Starting now, WebAssembly opens the floodgates to new choices, and one of the first realistic options may be .NET.\r\n \r\nBlazor is a new experimental web UI framework from the ASP.NET team that aims to brings .NET applications into all browsers (including mobile) via WebAssembly. It allows you to build true full-stack .NET applications, sharing code across server and client, with no need for transpilation or plugins.\r\n \r\nIn this talk I’ll demonstrate what you can do with Blazor today and how it works on the underlying WebAssembly runtime behind the scenes. You’ll see its modern, component-based architecture (inspired by modern SPA frameworks) at work as we use it to build a responsive client-side UI. I’ll cover both basic and advanced scenarios using Blazor’s components, router, DI system, JavaScript interop, and more.", - "startsAt": "2019-01-31T13:40:00", - "endsAt": "2019-01-31T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "05fe7f1a-cc5c-4e6e-8422-281c822c82c3", - "name": "Steve Sanderson" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10582, - "name": "JavaScript" - }, - { - "id": 10596, - "name": "Web" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - "index": 0 - }, - { - "id": 2776, - "name": "Room 2", - "session": { - "id": "69240", - "title": "Small Steps, Giant Leaps: Engineering Lessons from Apollo", - "description": "On July 20th, 1969, Neil Armstrong and Buzz Aldrin became the first humans to set foot on another world. Billions of people tuned in live to watch Apollo 11 land on the moon, but behind Armstrong’s ‘one small step’ lay a decade of astonishing innovation. The Apollo programme wasn’t just about aerospace engineering; it was also responsible for revolutionary new approaches in project management and quality control; new ways of thinking about testing strategies and communications - not to mention delivering a completely bespoke set of hardware and software components that would play a vital role at every stage of the programme.\r\n\r\nAs we celebrate the fiftieth anniversary of the moon landings, let’s take a look back at the technology, processes and practises behind the Apollo programme - and how many of those techniques are still relevant today. What is ‘all-up testing’, and how does it apply to modern software development? Who was the CAPCOM - and what can they teach us about product ownership? How do you manage a distributed team of nearly half a million people? How do you manage scope creep when you’re working to a hard deadline with the whole world watching you? And how DO you fly to the moon and back using a computer with less processing power than an Apple II?", - "startsAt": "2019-01-31T13:40:00", - "endsAt": "2019-01-31T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "1d7dcbfc-1de6-4228-8bd6-04f4ba1c4267", - "name": "Dylan Beattie" - }, - { - "id": "bc20c5a9-2d7e-4830-827f-8919be0eba88", - "name": "Kevlin Henney" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10579, - "name": "Fun" - }, - { - "id": 10588, - "name": "People" - }, - { - "id": 10592, - "name": "Testing" - }, - { - "id": 10574, - "name": "Design" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - "index": 1 - }, - { - "id": 2777, - "name": "Room 3", - "session": { - "id": "61211", - "title": "Let’s Talk About Mental Health", - "description": "It’s a great time to be in technology. And yet despite the almost constant improvement in our tools, we somehow don’t spend time talking about how to maintain our most important tool - the one between our ears.\r\n\r\nConstantly feeling worn down, experiencing anxiety over making decisions, and burning out are *not* just facts of a developer’s life! They’re challenges that can be dealt with. In this talk we’ll cover the most common mental health challenges facing developers, and then learn about some techniques to supercharge your brain by improving your mental hygiene (whether you have a psychological disorder or not). Most importantly, you’ll learn how to have a conversation with your coworkers (and other people in your life) about supporting each other and finding your best selves.\r\n", - "startsAt": "2019-01-31T13:40:00", - "endsAt": "2019-01-31T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "fdf3c776-f100-41f5-bb22-7a1f16710740", - "name": "Arthur Doler" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10591, - "name": "Soft Skills" - }, - { - "id": 10588, - "name": "People" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - "index": 2 - }, - { - "id": 2778, - "name": "Room 4", - "session": { - "id": "68736", - "title": "Build Nodejs APIs using Serverless on Azure", - "description": "Serverless lets you focus on coding and testing instead of provisioning infrastructure, configuring web servers, debugging your configuration, managing security settings, and all the drudgery normally associated with getting an app up and running. In this session with, you’ll discover how to migrate an API of an existing app to Azure Functions. You’ll learn how to use Visual Studio Code and the Azure Functions extension to speed up your work. After this session, you’ll join the ranks of serverless developers.", - "startsAt": "2019-01-31T13:40:00", - "endsAt": "2019-01-31T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "047b0c14-4a5f-4f2a-bd84-03b7fef87c4b", - "name": "Simona Cotin" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10582, - "name": "JavaScript" - }, - { - "id": 10590, - "name": "Serverless" - }, - { - "id": 10569, - "name": "Cloud" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - "index": 3 - }, - { - "id": 2779, - "name": "Room 5", - "session": { - "id": "65854", - "title": "Think Like a Trainer: Improving Your Communication Skills", - "description": "Think back to a time when you were in a conversation that could have gone better. Perhaps you said something the wrong way, or you walked away from the conversation not fully knowing if the other person even understood what you were trying to convey.\r\n\r\nTechnical trainers rely on effective communication as the foundation of everything that we do. We help end users to learn how to use software and adjust to new workflows, through the process of constantly adapting to different backgrounds, skill levels, and learning styles.\r\n\r\nIn this session, you’ll learn actionable strategies to begin thinking like a trainer, including:\r\n\r\n- Using active listening techniques to communicate with empathy.\r\n\r\n- Best practices for explaining technical concepts in non-technical terms.\r\n\r\n- Adjusting your communication approach for different communication styles.\r\n\r\n- Using problem solving skills to help you get unstuck during difficult conversations.", - "startsAt": "2019-01-31T13:40:00", - "endsAt": "2019-01-31T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "25cc75bc-df7b-42ad-a3e4-e0bfa8af7f01", - "name": "Olivia Liddell" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10588, - "name": "People" - }, - { - "id": 10591, - "name": "Soft Skills" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - "index": 4 - } - ] - }, - { - "slotStart": "15:00:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "session": { - "id": "69345", - "title": "Where is C# headed?", - "description": "C# 8.0 is coming up! Not just nullable reference types and asynchronous streams, which will get much coverage elsewhere in the conference, but also recursive patterns, switch expressions, ranges, default interface member implementations and more. We’ll look at all of those, and also at some of the things being worked on for future versions of the language.", - "startsAt": "2019-01-31T15:00:00", - "endsAt": "2019-01-31T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "8f64af49-a647-48e7-850b-70505308d948", - "name": "Mads Torgersen" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - "index": 0 - }, - { - "id": 2776, - "name": "Room 2", - "session": { - "id": "68814", - "title": "Scaling microservices with Message queues, .NET and Kubernetes", - "description": "When you design and build applications at scale, you deal with two significant challenges: scalability & robustness. You should design your service so that even if it is subject to intermittent heavy loads, it continues to operate reliably. But how do you build such applications? And how do you deploy an application that scales dynamically? Kubernetes has a feature called autoscaler where instances of your applications are increased or decreased automatically based on metrics that you define.\r\n\r\nIn this talk, you’ll learn how to design, package & deploy reliable .NET applications to Kubernetes & decouple several components using a message broker. You will also learn how to set autoscaling rules to cope with an increasing influx of messages in the queue.", - "startsAt": "2019-01-31T15:00:00", - "endsAt": "2019-01-31T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "964af3ac-fd5e-46f6-b582-6c0d2da30db4", - "name": "Lewis Denham-Parry" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10570, - "name": "Concurrency" - }, - { - "id": 10571, - "name": "Continuous Delivery" - }, - { - "id": 10576, - "name": "Docker" - }, - { - "id": 10575, - "name": "DevOps" - }, - { - "id": 10572, - "name": "Cross-Platform" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10586, - "name": "Microsoft" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - "index": 1 - }, - { - "id": 2777, - "name": "Room 3", - "session": { - "id": "56795", - "title": "Zero to Mobile Hero - Intro to Xamarin and Visual Studio Team Services", - "description": "You can be faced with a nightmare of Xcode, Android Studio, Swift, Objective C, Swift and other options. This means not only learning multiple languages and frameworks but also having to support two different codebases for the same application. But Xamarin Native and Xamarin.Forms offer a powerful, cross-platform development solution for .NET developers looking to target smartphones, tablets, TV’s, computers and IoT devices.\r\n\r\nIn this talk, Luce shares what Xamarin is including Native and Xamarin.Forms for both C# and F#, how to get started creating a simple HelloWorld app from scratch and a more complex example (will involve at least one Azure service including Cognitive Services for facial recognition). Also how to use Visual Studio Team Services for Continuous Integration and some awesome examples of apps written using Xamarin including ones used to save lives!\r\n\r\nLuce will take examples from xamarin.com/customers as well as show this demo about how Xamarin was used alongside other technologies to aid with Skin Cancer prediction.\r\n\r\nThis talk will include slides, demos, code samples, live coding and the audience will walk away feeling like they too can create a mobile app in just a few minutes and carry their work around with them in their pocket or backpack!", - "startsAt": "2019-01-31T15:00:00", - "endsAt": "2019-01-31T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "79741134-06bb-4596-bc44-40edd9e03f6b", - "name": "Luce Carter" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10565, - "name": "AI" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10572, - "name": "Cross-Platform" - }, - { - "id": 10586, - "name": "Microsoft" - }, - { - "id": 10587, - "name": "Mobile" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - "index": 2 - }, - { - "id": 2778, - "name": "Room 4", - "session": { - "id": "68161", - "title": "ML.NET for developers without any AI experience", - "description": "AI talk is everywhere but where do you start as a .NET developer? During this session, we will explore how you can use AI in the applications your creating today. How to start building & training your ML models with your .NET skills through ML.NET. \r\n\r\nWant to detect laughter in a phone conversation? Detect the mood of Jira tickets or predict if/where your code has bugs. This session will get you started with AI and ML.NET.", - "startsAt": "2019-01-31T15:00:00", - "endsAt": "2019-01-31T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "8061571c-bb36-42a9-b714-4d90c98529fd", - "name": "Lee Mallon" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10565, - "name": "AI" - }, - { - "id": 10584, - "name": "Machine Learning" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - "index": 3 - }, - { - "id": 2779, - "name": "Room 5", - "session": { - "id": "66437", - "title": "(WPF + WinForms) * .NET Core = Modern Desktop", - "description": "Learn how .NET Core 3 brings WPF and Windows Forms into the future with a modern runtime. See what’s new for WPF and Windows Forms, learn how to easily retarget your .NET Framework application over to .NET Core, and how to get these modern desktop apps to your users.\r\n", - "startsAt": "2019-01-31T15:00:00", - "endsAt": "2019-01-31T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "8b1783d3-15ce-41dc-b989-386759803d97", - "name": "Oren Novotny" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10594, - "name": "UI" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - "index": 4 - }, - { - "id": 2780, - "name": "Room 6", - "session": { - "id": "66322", - "title": "Accessible App Design", - "description": "Want to start building apps for people with disabilities but doesn’t no where to start? In this session we cover everything to start right now! There are many people with learning disabilities around the world. There are also people with autism, psychological disabilities… Many of them are also entering the era of mobile and internet. We talk about design guidelines that can reach them. \r\n\r\nWe talk about apps, but do not focus on a specific technology in this talk. Which apps are needed? Which steps of design helps them to catch the frontiers of mobile and internet right now? Microsoft and other big tech companies are working more and more about inclusive design and digital inclusion for people with disabilities. ", - "startsAt": "2019-01-31T15:00:00", - "endsAt": "2019-01-31T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "67a075a3-a111-4116-bd44-a25a01485959", - "name": "Dennie Declercq" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10591, - "name": "Soft Skills" - }, - { - "id": 10594, - "name": "UI" - }, - { - "id": 10595, - "name": "UX" - } - ], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - }, - "index": 5 - } - ] - }, - { - "slotStart": "16:20:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "session": { - "id": "66795", - "title": "DiagnosticSourcery 101", - "description": ".NET has a new mechanism for generating and storing diagnostic data: DiagnosticSource. This is the cross-platform alternative to ETW. Much of ASP.NET Core and EF Core produce useful metric data using DiagnosticSource, and you can produce your own and stream some or all of the data to the metrics storage of your choice.\r\n\r\nIn this talk I'll run through how DiagnosticSource works, show you how to use it to output your own metrics in any .NET application, and how to pipe those metrics to a Time-Series database and turn them into a lovely Grafana dashboard.\r\n\r\nYou can use DiagnosticSource in anything from an ASP.NET Core cloud-native microservice to a WPF desktop application, and it's a Microsoft package with no 3rd-party dependencies, so this talk should be interesting and useful for any .NET developer.", - "startsAt": "2019-01-31T16:20:00", - "endsAt": "2019-01-31T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "70590ad0-b1b3-40b8-b05d-b58722ef9d9d", - "name": "Mark Rendle" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10572, - "name": "Cross-Platform" - }, - { - "id": 10575, - "name": "DevOps" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - "index": 0 - }, - { - "id": 2776, - "name": "Room 2", - "session": { - "id": "68608", - "title": "A practical guide to deep learning", - "description": "Machine Learning is one of the fastest growing areas of computer science, and Deep Learning (neural networks) is growing even faster, with lots of data and computing power at our fingertips. \r\nThis talk is a practical (very little math) guide to computer vision and deep learning.\r\n\r\nWe will look at a deep learning project from start to finish, look at how to program and train a neural network and gradually refine it using some tips and tricks that you can steal for your future deep learning projects.", - "startsAt": "2019-01-31T16:20:00", - "endsAt": "2019-01-31T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "cb70e0f2-0f0b-4b8f-b3f4-a9326309a1b2", - "name": "Tess Ferrandez-Norlander" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10584, - "name": "Machine Learning" - }, - { - "id": 10565, - "name": "AI" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - "index": 1 - }, - { - "id": 2777, - "name": "Room 3", - "session": { - "id": "57812", - "title": "Build cross-platform mobile apps using Fabulous", - "description": "In recent years there has been a shift in the way websites and mobile apps are being built - moving to architectures with immutable models and virtual UIs - based on the MVU (model-view-update) pattern. This has lead to great new frameworks like ELM and React for web, and ReactNative for mobile.\r\n\r\nNow there is a new MVU framework for building mobile apps - Fabulous. It's a community-driven open source framework, combining the simplicity of an MVU framework, with 100% native API access for both iOS and Android, all built with using an established, world class, battle-hardened functional programming language.\r\n\r\nThis session will start with an overview of MVU, discussing how it works and why it is such a great architecture. It will then move on to building your first Fabulous app that runs on iOS and Android. Next up more features will be added to the app whilst the app is running on a device, showing the hot reload capabilities of Fabulous for both UI and app logic. Finally it will look at the underlying architecture, see how to use all of the iOS and Android APIs, see how to easily use native components such as cocoa pods or jars, and look at the massive range of libraries that this framework as available to it to do all manner of UI and application logic things. We'll even see how to use it on macOS and Windows, including being able to build iOS apps on Windows (with the help of a networked Mac, Apple licensing rules and whatnot).\r\n\r\nWhen looking at naming for this framework, someone suggested Fabulous. By the end of this session you will see why that name stuck.", - "startsAt": "2019-01-31T16:20:00", - "endsAt": "2019-01-31T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "75465aaf-45f4-4d3c-b78a-2e3d5206b57f", - "name": "Jim Bennett" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10587, - "name": "Mobile" - }, - { - "id": 10586, - "name": "Microsoft" - }, - { - "id": 10580, - "name": "Functional Programming" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - "index": 2 - }, - { - "id": 2778, - "name": "Room 4", - "session": { - "id": "68212", - "title": "Reverse Engineering a Bluetooth Lightbulb", - "description": "I recently made build lights for the company I work for and my home office. They integrate with TeamCity and indicate when a build is running and success/failure of all the tests. In this session, we will reverse engineer a bluetooth light bulb’s protocol, learn how to have an Raspberry Pi communicate with the bulb, and by the end you too will know how to make your own build lights! Please note that this talk will be highly technical. We will be discussing low level details of bluetooth communication, protocol analysis with Wireshark, sniffing bluetooth packets, etc.", - "startsAt": "2019-01-31T16:20:00", - "endsAt": "2019-01-31T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "86d72d85-ef02-405e-b0de-1603dae6b8fb", - "name": "Jesse Phelps" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10606, - "name": "Embedded" - }, - { - "id": 10581, - "name": "IoT" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - "index": 3 - }, - { - "id": 2779, - "name": "Room 5", - "session": { - "id": "66866", - "title": "An Introduction to WebAssembly", - "description": "Want to write a web application? Better get familiar with JavaScript JavaScript has long been the king of front-end. While there have been various attempts to dethrone it, they have typically involved treating JavaScript as an assembly-language analog that you transpile your code to. This has lead to complex build pipelines that result in JavaScript which the browser has to parse and *you* still have to debug. But what if there were an actual byte-code language you could compile your non-JavaScript code to instead? That is what WebAssembly is.\r\n\r\nI'm going to explain how WebAssembly works and how to use it in this talk. I'll cover what it is, how it fits into your application, and how to build and use your own WebAssembly modules. And, I'll demo how to build and use those modules with both Rust and the WebAssembly Text Format. That's right, I'll be live coding in an assembly language. I'll also go over some online resources for other languages and tools that make use of WebAssembly.\r\n\r\nWhen we're done, you'll have the footing you need to start building applications featuring WebAssembly. So grab a non-JavaScript language, a modern browser, and let's and get started!", - "startsAt": "2019-01-31T16:20:00", - "endsAt": "2019-01-31T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "520bf4ca-b2d3-47c3-8475-c25bb2b257f7", - "name": "Guy Royse" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10596, - "name": "Web" - }, - { - "id": 10582, - "name": "JavaScript" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - "index": 4 - }, - { - "id": 2780, - "name": "Room 6", - "session": { - "id": "58551", - "title": "System Stable : Robust connected applications with Polly, the .NET Resilience Framework", - "description": "Short Description\r\n\r\nJoin me for this session and I will show you how with just a few lines of code, you can make your applications much more resilient and reliable. With Polly, the .NET resilience framework, your application can easily tolerate transient faults and longer outages in remote systems or infrastructure. \r\n\r\nAt the end of this hour you will know how to use all the features of Polly to make your application a rock solid piece of work. We’ll cover the reactive and proactive resilience strategies, starting with simple but very powerful retries and finishing with bulkhead isolation.\r\nOh, and did I mention Polly is a .NET Standard library so it will work on any application you can think of! Join me for an hour, and your applications will never be the same.\r\n\r\n----------------------------------------------------------------------------------------------------------------------------------\r\n\r\nFull Description\r\n\r\nJoin me for this session and I will show you how with just a few lines of code, you can make your applications much more resilient and reliable. Let me tell you more… \r\n\r\nAlmost all applications now depend on connectivity, but what do you do when the infrastructure is unreliable or the remote system is down or returns an error? Does your application grind to a halt or just drop that single request? What if you could recover from these kinds of error, maybe even so quickly it won’t be noticed? \r\n \r\nWith Polly your application can easily tolerate transient faults and longer outages in remote systems or infrastructure. \r\n\r\nAt the end of this hour you will know how to use all the features of Polly to make your application a rock solid piece of work. \r\n\r\nWe’ll start with the simple but very powerful Retry Policy which lets you retry a failed request. If simple retries are not good enough for you, there is a Wait and Retry policy which introduces a delay between retries, giving the remote service time to recover before being hit again. Then I show you how to use the circuit breaker for when things have really gone wrong and a remote system is struggling under too much load or has failed. If all these attempts are unsuccessful and you are still not getting through to the remote system, you can return a default response or execute arbitrary code to call for human help (or restart the cloud) with the fallback policy. \r\n\r\nThat takes care of what you can do when things go wrong, but Polly also lets you take proactive steps to keep your application and the services it depends on healthy. \r\n\r\nTo get you started with proactive strategies, you will learn how caching can be used to store and return responses from an in-memory or distributed cache without having to hit the remote server every time. Or you can use bulkhead isolation to marshal resources within your application so that no one struggling part can take down the whole. Finally, I’ll show you how to fail quickly when your application is in danger of being overloaded or the remote systems is not responding in a timely fashion, this is done with the bulkhead isolation and the timeout polices. \r\n\r\nOh, and did I mention Polly is a .NET Standard library so it will work on any application you can think of! Join me for an hour, and your applications will never be the same. ", - "startsAt": "2019-01-31T16:20:00", - "endsAt": "2019-01-31T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "de972e57-7765-4c38-9dcd-5981587c1433", - "name": "Bryan Hogan" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10596, - "name": "Web" - }, - { - "id": 10587, - "name": "Mobile" - }, - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - }, - "index": 5 - } - ] - }, - { - "slotStart": "17:40:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "session": { - "id": "63671", - "title": "Let's Talk HTTP in .NET Core", - "description": "In the world of microservices (yes, there's that buzzword again!) and distributed systems, we often find ourselves communicating over HTTP. What seems like a simple requirement can quickly become complicated! Networks aren't reliable and services fail. Dealing with those inevitable facts and avoiding a cascading failure can be quite a challenge. In this talk, Steve will explore how we can build .NET Core applications that make HTTP requests and rely on downstream services, whilst remaining resilient and fault tolerant.\r\n\r\nThis session will focus on some of the improvements which have been released in .NET Core and ASP.NET Core 2.1, such as IHttpClientFactory and the new, more performant SocketHttpHandler. Steve will identify some HTTP anti-patterns and common mistakes and demonstrate how we can refactor existing code to use the new HttpClientFactory features.\r\n\r\nNext, Steve will demonstrate other HTTP tips and tricking, including Polly; a fantastic resilience and transient fault handling library which can be used to make your applications less prone to failure. When integrated with the Microsoft IHttpClientFactory; wrapping your HTTP calls in retries, timeouts and circuit-breakers has never been easier!\r\n\r\nIf you're building services which make HTTP calls, then this talk is for you!", - "startsAt": "2019-01-31T17:40:00", - "endsAt": "2019-01-31T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "26b7e78d-aa31-4d7f-b2ea-90fef14d1087", - "name": "Steve Gordon" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10586, - "name": "Microsoft" - }, - { - "id": 10585, - "name": "Microservices" - }, - { - "id": 10596, - "name": "Web" - }, - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10569, - "name": "Cloud" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - "index": 0 - }, - { - "id": 2776, - "name": "Room 2", - "session": { - "id": "69332", - "title": ".NET Rocks Live on Software Feature Selection with Christine Yen", - "description": "Join Carl and Richard from .NET Rocks as they chat with Christine Yen from Honeycomb about how you select features to build in your applications.\r\n\r\nAfter the first version of software is out the door, what do you choose nest? Christine has a background in instrumenting applications to understand what people use – is that the best way to pick features? What about the vision of your own designers? What about asking the users? Bring your questions and come to this live recording of .NET Rocks!", - "startsAt": "2019-01-31T17:40:00", - "endsAt": "2019-01-31T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "d4d7850a-526e-4959-aab1-36460081fcf5", - "name": "Richard Campbell" - }, - { - "id": "bf171bb6-4c78-4fe9-ac77-2338d5ec7975", - "name": "Carl Franklin" - }, - { - "id": "e5d55e8e-93d1-4a53-bbec-10e4beaf5fd8", - "name": "Christine Yen" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - "index": 1 - }, - { - "id": 2777, - "name": "Room 3", - "session": { - "id": "69228", - "title": "Dungeons, Dragons and Functions", - "description": "Dungeons & Dragons, or D&D, is the grand-daddy of all role playing games. While playing D&D is great fun, the rules are a bit daunting for the beginner. The basic rulebook, the PHB, clocks in at a solid 300 pages, and can be extended with multiple additional rule sets. This should come as no surprise to software engineers: this is, after all, documentation for a system that models a complex domain, and has been in use for over 40 years now, going through numerous redesigns over time.\r\n\r\nAs such, D&D rules make for a great exercise in domain modelling. In this talk, I will take you along my journey attempting to tame that monster. We will use no magic, but a weapon imbued with great power, F#; practical tips and tricks for the Adventurer on the functional road will be shared. So... roll 20 for initiative, and join us for an epic adventure in domain modeling with F#!", - "startsAt": "2019-01-31T17:40:00", - "endsAt": "2019-01-31T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "14879952-64d2-42b5-8d6f-d1e1a68b39c9", - "name": "Mathias Brandewinder" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - "index": 2 - }, - { - "id": 2778, - "name": "Room 4", - "session": { - "id": "64248", - "title": "Data on the Inside, Data on the Outside", - "description": "When we move from a monolith to microservices we abandon integrating via a shared database, as each service must own its own data to allow them it to be autonomous. But now we have a new problem, our data is distributed. What happens if I need one service needs to talk to another about a shared concept such as a product, a hotel room, or an order? Does every service need to have a list of all our users? Who knows what users have permissions to the entities within the micro service? What happens if my REST endpoint needs to include data from a graph that includes other services to make it responsive? And I am not breaking the boundary of my service when all of this data leaves my service boundary in response to a request?\r\n\r\nNaive solutions result in chatty calls as each service engages with multiple other services to fulfil a request, or in large message payloads as services add all the data required to process a message to each message. Neither scale well.\r\n\r\nIn 2005, Pat Helland wrote a paper ‘Data on the Inside vs. Data on the Outside’ which answers the question by distinguishing between data a service owns and reference data that it can use. In this presentation we will explain reference data, how it is classified, and how it should be implemented. We will include a discussion of using reference data from ATOM feeds, discrete messaging and event streams. We’ll provide examples in C#, Python and Go as well as using RMQ and Kafka.", - "startsAt": "2019-01-31T17:40:00", - "endsAt": "2019-01-31T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "84ffe422-5bc6-4075-9903-d9ad3526cf86", - "name": "Ian Cooper" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10585, - "name": "Microservices" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - "index": 3 - }, - { - "id": 2779, - "name": "Room 5", - "session": { - "id": "68009", - "title": "Scaling Frontend Development", - "description": "Abstract\r\nLarge frontend projects suffer from all of the same problems of other software projects with the same characteristics:\r\nCommunication and coordination overhead\r\nSpeed of delivery\r\nLarge quantum size\r\nLow productivity \r\n\r\nThese factors are growing concerns for companies as productivity and speed of delivery is nowadays crucial for success in this competitive landscape\r\n\r\nA common way of solving many of these issues in software projects is the microservices approach.\r\n\r\nToday a similar approach of applying this same pattern to the frontend is being popularized and is commonly nominated as micro-frontends.\r\n\r\nHowever this approach has many fallacies because of frontend specific characteristics:\r\n- The performance cost of loading many independent applications\r\n- The need for a common visual language and experience\r\n- The browser is a monolithic runtime \r\n\r\nDescription\r\nThis talk will be about the problems of large frontend projects and how to scale them in a way that balances team autonomy with performance and productivity\r\n\r\nI’ll talk about how at farfetch we’re progressively refactoring our frontend to multiple independent applications, and the strategies we’re using to make sure that despite having many applications made by different independent and geographically distributed teams we still can deliver a performant and consistent product to the end user.\r\n", - "startsAt": "2019-01-31T17:40:00", - "endsAt": "2019-01-31T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "f79c1f81-b367-4ce0-9cc0-4263f30a9f7f", - "name": "luis vieira" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10594, - "name": "UI" - }, - { - "id": 10585, - "name": "Microservices" - }, - { - "id": 10582, - "name": "JavaScript" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - "index": 4 - }, - { - "id": 2780, - "name": "Room 6", - "session": { - "id": "68611", - "title": "Clean Architecture with ASP.NET Core 2.2", - "description": "The explosive growth of web frameworks and the demands of users have changed the approach to building web applications. Many challenges exist, and getting started can be a daunting prospect. Let's change that now.\r\n\r\nThis talk provides practical guidance and recommendations. We will cover architecture, technologies, tools, and frameworks. We will examine strategies for organizing your projects, folders and files. We will design a system that is simple to build and maintain - all the way from development to production. You leave this talk inspired and prepared to take your enterprise application development to the next level.", - "startsAt": "2019-01-31T17:40:00", - "endsAt": "2019-01-31T18:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "3a5abb12-c9e2-4641-8ace-a4c067ad8e8d", - "name": "Jason Taylor" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - }, - "index": 5 - } - ] - } - ] - }, - { - "date": "2019-02-01T00:00:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "sessions": [ - { - "id": "69232", - "title": "Keynote: The Microsoft Open Source Cinematic Universe - Phase 2", - "description": "Phase 1 is nearly complete with open source .NET Core. What does Microsoft's Open Source plan look like for the next 10 years?\r\n\r\nJoin Scott Hanselman as he compares the MCU (Marvel Cinematic Universe) to the MSFTOSSCU and talks about what a next phase MIGHT look like.", - "startsAt": "2019-02-01T09:00:00", - "endsAt": "2019-02-01T10:00:00", - "isServiceSession": false, - "isPlenumSession": true, - "speakers": [ - { - "id": "142dd289-d6c7-4385-9f36-05b816ceea2c", - "name": "Scott Hanselman" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - { - "id": "69004", - "title": "Async injection", - "description": "This talk attempts to answer a pair of frequently asked questions, the first one of which is: how do I combine dependency injection with async and await in C# without leaky abstractions?\r\n\r\nIt turns out that the answer to that question can be found by answering another frequently asked question: how do I get the value out of my monad?\r\n\r\nDuring the talk, you’ll get a quick and easy-to-understand explanation of monads.\r\n\r\nAll code examples will be in C#.", - "startsAt": "2019-02-01T10:20:00", - "endsAt": "2019-02-01T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "84f7d361-4388-44ad-bc48-31695762bc6d", - "name": "Mark Seemann" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10580, - "name": "Functional Programming" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - { - "id": "68521", - "title": "From 'dotnet run' to 'Hello World!'", - "description": "Have you ever stopped to think about all the things that happen when you execute a simple .NET program?\r\n\r\nThis talk will delve into the internals of the recently open-sourced .NET Core runtime, looking at what happens, when it happens and why. \r\n\r\nMaking use of freely available tools such as 'PerfView', we'll examine the Execution Engine, Type Loader, Just-in-Time (JIT) Compiler and the CLR Hosting API to see how all these components play a part in making 'Hello World' possible.", - "startsAt": "2019-02-01T11:40:00", - "endsAt": "2019-02-01T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "fb89e2c6-39b1-4ef8-8932-609504cf4901", - "name": "Matt Warren" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10593, - "name": "Tools" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - { - "id": "69233", - "title": "Solving Diabetes with an Open Source Artificial Pancreas", - "description": "Scott has been a Type 1 diabetic for over 20 years. When he first became diabetic he did what every engineer would do...he wrote an app to solve his problem. Fast forward to 2018 and Scott lives 24 hours a day connected to an open source artificial pancreas. After years of waiting, the diabetes community online creating solutions.\r\n\r\nScott will go through the history of diabetes online, the components (both hardware and software) needed for an artificial pancreas, and discuss the architectural design of two popular systems (LoopKit and OpenAPS). Plus, you'll see Scott *not die* live on stage as he's been \"looping\" for over a year!", - "startsAt": "2019-02-01T13:40:00", - "endsAt": "2019-02-01T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "142dd289-d6c7-4385-9f36-05b816ceea2c", - "name": "Scott Hanselman" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - { - "id": "69010", - "title": "Crash, Burn, Report", - "description": "With the launch of the Reporting API any browser that visits your site can automatically detect and alert you to a whole heap of problems with your application. DNS not resolving? Serving an invalid certificate? Got a redirect loop, using a soon to be deprecated API or any one of countless other problems, they can all be detected and reported with no user action, no agents, no code to deploy. You have one of the most extensive and powerful monitoring platforms in existence at your disposal, millions of browsers. Let's look at how to use them.\r\n\r\nIn this talk we'll look at how to configure the browser to send you reports when things go wrong. These are brand new capabilities the likes of which we've haven't seen before and they're already supported in the world's most popular browser, Google Chrome. We'll look at how to receive reports and how to make use of them after having the browser do the hard work.", - "startsAt": "2019-02-01T15:00:00", - "endsAt": "2019-02-01T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "e9c64362-6194-409c-85da-45c8fd40abd6", - "name": "Scott Helme" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - { - "id": "66952", - "title": "Futurology for Dummies - the Next 30 Years in Tech", - "description": "2019 is the 30th anniversary of my first job in tech. On my first day I was given a Wyse 60 terminal attached via RS232 cables to a Tandon 286, and told to learn C from a dead tree so I could write text applications for an 80x24 character screen. Fast-forward to now: my phone is about a million times more powerful than that Tandon; screens are 3840x2160 pixels; every computer in the world is attached to every other thing with no cables; and we code using, well, still basically C.\r\n\r\nHaving lived through all those changes in realtime, and as an incurable neophile, I think I can make an educated guess as to what the next 30 years are going to be like, and what we're all going to be doing by 2049. If anything, I'm going to underestimate it, but hopefully you'll be inspired, invigorated and maybe even informed about the future of your career in tech.", - "startsAt": "2019-02-01T16:20:00", - "endsAt": "2019-02-01T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "70590ad0-b1b3-40b8-b05d-b58722ef9d9d", - "name": "Mark Rendle" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10579, - "name": "Fun" - }, - { - "id": 10584, - "name": "Machine Learning" - }, - { - "id": 10581, - "name": "IoT" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10565, - "name": "AI" - }, - { - "id": 10593, - "name": "Tools" - }, - { - "id": 10594, - "name": "UI" - }, - { - "id": 10595, - "name": "UX" - }, - { - "id": 10596, - "name": "Web" - }, - { - "id": 10574, - "name": "Design" - }, - { - "id": 10587, - "name": "Mobile" - }, - { - "id": 10604, - "name": "3D Modeling" - }, - { - "id": 10603, - "name": "VR" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - } - ], - "hasOnlyPlenumSessions": false - }, - { - "id": 2776, - "name": "Room 2", - "sessions": [ - { - "id": "69239", - "title": "Ctrl-Alt-Del: Learning to Love Legacy Code", - "description": "The world runs on legacy code. For every greenfield progressive web app with 100% test coverage, there are literally hundreds of archaic line-of-business applications running in production - systems with no tests, no documentation, built using out-of-date tools, languages and platforms. It’s the code developers love to hate: it’s not exciting, it’s not shiny, and it won’t look good on your CV - but the world runs on legacy code, and, as developers, if we’re going to work on anything that actually matters, we’re going to end up dealing with legacy. To work effectively with this kind of system, we need to answer some fundamental questions: why was it built this way in the first place? What's happened over the years it's been running in production? And, most importantly, how can we develop our understanding of legacy codebases to the point where we're confident that we can add features, fix bugs and improve performance without making things worse?\r\n\r\nDylan worked on the web application stack at Spotlight (www.spotlight.com) from 2000 until 2018 - first as a supplier, then as webmaster, then as systems architect. Working on the same codebase for nearly two decades has given him an unusual perspective on how applications go from being cutting-edge to being 'legacy'. In this talk, he'll share tips, patterns and techniques that he's learned from helping new developers work with a large and unfamiliar codebase. We'll talk about virtualisation, refactoring tools, and how to bring legacy code under control using continuous integration and managed deployments. We'll explore creative ways to use common technologies like DNS to create more productive development environments. We'll talk about how to bridge the gap between automated testing and systems monitoring, how to improve visibility and transparency of your production systems - and why good old Ctrl-Alt-Del might be the secret to unlocking the potential of your legacy codebase.", - "startsAt": "2019-02-01T10:20:00", - "endsAt": "2019-02-01T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "1d7dcbfc-1de6-4228-8bd6-04f4ba1c4267", - "name": "Dylan Beattie" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10571, - "name": "Continuous Delivery" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - { - "id": "67993", - "title": "The Functional Programmer's Toolkit", - "description": "The functional programming community has a number of patterns with strange names such as monads, monoids, functors, and catamorphisms.\r\n \r\nIn this beginner-friendly talk, we'll demystify these techniques and see how they all fit together into a small but versatile \"tool kit\". \r\n\r\nWe'll then see how the tools in this tool kit can be applied to a wide variety of programming problems, such as handling missing data, working with lists, and implementing the functional equivalent of dependency injection. ", - "startsAt": "2019-02-01T11:40:00", - "endsAt": "2019-02-01T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "89335661-3092-4afa-b53f-3d203cafa2a1", - "name": "Scott Wlaschin" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10580, - "name": "Functional Programming" - }, - { - "id": 10574, - "name": "Design" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - { - "id": "69230", - "title": "Society (n+1).0: smashing the patriarchy and other ways of changing the world", - "description": "Software engineers are fond of casually mentioning how their work changes the world. But have you thought about what you want the world to look like after you've changed it? Do you want to smash the patriarchy [1]? Save the planet? Make Furbies cool again? Is technology really the only tool at your disposal?\r\nThis session is a call to both discovery and action. You already care about Furbies, but what do you not know you don't know about them? Have you looked at Furbies from someone else's perspective? Once your eyes are wide open, what's the next step? How would a Furby smash the patriarchy? Let's learn to be better together, and make a difference in the world today.\r\n\r\nFootnote 1: Our system of society norms which puts everyone in boxes that are hard to escape [2]. The boxes surrounding straight white men can be extremely comfortable ones, but more limiting than you might realize.\r\n\r\nFootnote 2: Furbies are pretty easy to get out of boxes; humans, not so much.", - "startsAt": "2019-02-01T13:40:00", - "endsAt": "2019-02-01T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "1176547b-89c5-40ee-b7d7-bf0eb5ca0aef", - "name": "Jon Skeet" - }, - { - "id": "e5b9e6c6-1477-4b19-8347-06683a7417de", - "name": "Jennifer Wadella" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - { - "id": "69307", - "title": "Tabs, spaces and salaries: a data science detective story", - "description": "In data science, sometimes you stumble across an intriguing property in the data. I will tell you a story of a mysterious correlation - from the StackOverflow developer survey it seems that developers who use spaces have higher salaries than those who use tabs. Correlation doesn't mean causation: using spaces won't suddenly increase your salary. But what does it all mean? Follow me into a detective investigation that will show you how to approach complex data science problems. I will show you some of the perils of correlation, model fitting and biases - how they can be dangerous and how to avoid these traps. And you'll also find how profitable your indentation style really is.", - "startsAt": "2019-02-01T15:00:00", - "endsAt": "2019-02-01T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "14fdabdd-3814-4f84-868e-a8178a25c5f8", - "name": "Evelina Gabasova" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10584, - "name": "Machine Learning" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - { - "id": "67994", - "title": "Four Languages from Forty Years Ago", - "description": "The 1970's were a golden age for new programming languages, but do they have any relevance to programming today? Can we still learn from them?\r\n\r\nIn this talk, we'll look at four languages designed over forty years ago -- SQL, Prolog, ML, and Smalltalk -- and discuss their philosophy and approach to programming, which is very different from most popular languages today.\r\n\r\nWe'll come away with some practical principles that are still very applicable to modern development. And you might discover your new favorite programming paradigm!\r\n", - "startsAt": "2019-02-01T16:20:00", - "endsAt": "2019-02-01T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "89335661-3092-4afa-b53f-3d203cafa2a1", - "name": "Scott Wlaschin" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10583, - "name": "Languages" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - } - ], - "hasOnlyPlenumSessions": false - }, - { - "id": 2777, - "name": "Room 3", - "sessions": [ - { - "id": "69231", - "title": "C# 8", - "description": "It's nearly here! The Visual Studio 2019 Preview is already available, so if you haven't looked into what's coming in C# 8, now is the perfect time to do so.\r\nThe most important feature of C# 8 is undoubtedly nullable reference types, but there's plenty more to look forward to as well.\r\n\r\nWhile I'll make this talk as easy to understand as I can, there's a huge amount to cover. Expect a fast pace, with lots of code.", - "startsAt": "2019-02-01T10:20:00", - "endsAt": "2019-02-01T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "1176547b-89c5-40ee-b7d7-bf0eb5ca0aef", - "name": "Jon Skeet" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - { - "id": "67078", - "title": "APIs Exposed!", - "description": "More and more developers are building APIs, whether that be for consumption by client-side applications, exposing endpoints directly to customers so they can use an alternative front-end or wrapping up services in containers.\r\n\r\nNow that we have all these exposed endpoints, what are we doing to secure them? Previously, our monolith was self-contained with limited points of access making authentication and authorisation more straightforward - that’s no longer the case.\r\n\r\nWe’ll cover the potential risks we may face such as cross-site scripting and BruteForce attacks as well as a look at the possible options for securing API endpoints including OAuth, Access Tokens, JSON web tokens, IP whitelisting, rate limiting to name but a few.\r\n\r\n", - "startsAt": "2019-02-01T11:40:00", - "endsAt": "2019-02-01T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "ac105033-2b20-4b45-8d47-5647d8accf84", - "name": "Layla Porter" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10589, - "name": "Security" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - { - "id": "69366", - "title": "Architectural patterns for the cloud", - "description": "As more and more people are starting to deploy their application to the cloud, new architectural patterns have emerged, and some old ones have resurfaced or become more prominent.\r\n\r\nIn this session, Mahesh Krishnan, will run through a large catalogue of cloud patterns that will cover categories such as availability, resiliency, data management, performance, scalability, design and implementation. You will learn about what problem each and every pattern addresses, how to implement them and what considerations you need to take into account while implementing them.", - "startsAt": "2019-02-01T13:40:00", - "endsAt": "2019-02-01T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "648e2e9d-28cc-47ef-828c-75a7d599d48d", - "name": "Mahesh Krishnan" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10569, - "name": "Cloud" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - { - "id": "66814", - "title": "Unity 101 for C# Developers", - "description": "If you are interested in mixed or virtual reality development then Unity is a tool you’ll want to learn. Go to Microsoft’s [Hololens development page](https://developer.microsoft.com/en-us/windows/mixed-reality/install_the_tools) and you’ll find the installation of Unity recommended in the first paragraph.\r\n\r\nOne surprise to developers getting started with Unity is the level of integration with Visual Studio and how easy it is to add C# to manipulate your 3D world.\r\n\r\nIn this demo led session we’ll go back to basics with Unity, easily creating a simple 3D experience with realistic physics. We’ll look at the fantastic Visual Studio integration and how easily the two editors work together.\r\n\r\nFinally we’ll look at the ways in which we can give our 3D experience some polish by adding textures, animations and some explosions!\r\n\r\nKeeping the best news for last: Unity is royalty free until you’re earning $100,000 – so if you like the idea of becoming wildly rich from making immersive 3D experiences this is the talk for you.", - "startsAt": "2019-02-01T15:00:00", - "endsAt": "2019-02-01T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "ef4df68d-9bdc-471d-aff0-075c77c4a424", - "name": "Andy Clarke" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10603, - "name": "VR" - }, - { - "id": 10604, - "name": "3D Modeling" - }, - { - "id": 10602, - "name": "Gaming" - }, - { - "id": 10579, - "name": "Fun" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - { - "id": "67138", - "title": "Deep Learning in the world of little ponies", - "description": "In this talk, we will discuss computer vision, one of the most common real-world applications of machine learning. We will deep dive into various state-of-the-art concepts around building custom image classifiers - application of deep neural networks, specifically convolutional neural networks and transfer learning. We will demonstrate how those approaches could be used to create your own image classifier to recognise the characters of \"My Little Pony\" TV Series [or Pokemon, or Superheroes, or your custom images].", - "startsAt": "2019-02-01T16:20:00", - "endsAt": "2019-02-01T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "b4c506ac-9757-4ac6-8b7c-3d6696b113e4", - "name": "Galiya Warrier" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10584, - "name": "Machine Learning" - }, - { - "id": 10579, - "name": "Fun" - }, - { - "id": 10565, - "name": "AI" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - } - ], - "hasOnlyPlenumSessions": false - }, - { - "id": 2778, - "name": "Room 4", - "sessions": [ - { - "id": "58161", - "title": "Making Accessibility Testing Suck Less: An Intro to Pa11y.", - "description": "Often the hardest part of any problem is simply how to get started. On the ever-evolving web accessibility is a matter of ongoing importance: the brilliance of your code or sleekness of your UI is inconsequential if your app or website is unusable to some of your users. With a million other issues already on your plate how do you find a way to get started on accessibility testing? Pa11y to the rescue! Pa11y is a lightweight command-line accessibility testing tool with enough flexibility to integrate results into your current testing process. This talk will explain what pa11y does and does not cover, review examples of both command line and scripted usage, dive into the pa11y web service and show how to modify output to work in your current testing setup. Bonus content: how to convince the rest of your team and business why accessibility is worth prioritizing and how getting started with low-hanging fruit can vastly improve your product.", - "startsAt": "2019-02-01T10:20:00", - "endsAt": "2019-02-01T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "e5b9e6c6-1477-4b19-8347-06683a7417de", - "name": "Jennifer Wadella" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10592, - "name": "Testing" - }, - { - "id": 10582, - "name": "JavaScript" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - { - "id": "62532", - "title": "A Developer's Guide to Advertising", - "description": "Love it or hate it, advertising is currently a main source of revenue for many websites. But digital advertising is a complicated space that not many developers understand. If you'd like to understand the ad code on your site better, if your ad ops team has been talking about header bidding, or if you're just curious about how ads work, this is the talk for you. I'll give an overview of how programmatic advertising works, what header bidding is, explain some common tools and libraries, and address some common misconceptions and complaints about ads.", - "startsAt": "2019-02-01T11:40:00", - "endsAt": "2019-02-01T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "b8f3c690-5950-4279-9ee7-9291d1439dd2", - "name": "Krista LaFentres" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10596, - "name": "Web" - }, - { - "id": 10582, - "name": "JavaScript" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - { - "id": "68894", - "title": "\"Hey Mycroft\": Getting Started with the OSS Home Assistant", - "description": "Home virtual assistants, like Alexa, Google Now, Siri, and Cortana, are gaining a lot of popularity. They’re now incorporated into our phones, our laptops, and even available as separate devices in our homes. Some people haven’t adopted them out of privacy concerns. A new system called Mycroft has come onto the scene, and it’s built on open source hardware and software. You can install it on a Raspberry Pi, an old Linux box, or buy their own Mycroft device.\r\n\r\nIn this session, we’ll go over the basics of what Mycroft is, and how you can quickly install it yourself. From there, we’ll talk about some of the underlying software and see a short demo. Finally, we’ll see how to build a new skill into it and contribute it back to the community. You’ll leave with your own virtual assistant and the knowledge on how make it do what you want but keep your privacy in check.", - "startsAt": "2019-02-01T13:40:00", - "endsAt": "2019-02-01T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "97e1c796-8bf6-468b-b246-0efc6979b9e7", - "name": "Sarah Withee" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10581, - "name": "IoT" - }, - { - "id": 10565, - "name": "AI" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - { - "id": "68882", - "title": "Megahertz, Gigahertz, Registers and Instructions: How does a CPU actually work?", - "description": "For decades, we’ve been creating ever higher abstractions between ourselves and the computing hardware we’re programming, but in the end whether you’re writing JavaScript, Haskell, or Python it all comes down to 1’s and 0’s running through hardware patterns that were well understood twenty years ago.\r\n\r\nWe’ll walk through the fundamentals of how CPU’s “think” in an accessible way (no engineering degree required!) so you can appreciate the marvel that is the modern CPU be it in a server data center or your fridge at home. You’ll learn how a CPU turns the code we feed it into actions, what’s the big difference between an ARM and an Intel processor, how CPU’s constantly optimize work for us, and where is it all going for the next few years.\r\n\r\nFinally, we'll show how Meltdown and Spectre take advantage of CPU internals to expose data and why this class of security problems are going to be a challenge to the next generation of CPU's.\r\n", - "startsAt": "2019-02-01T15:00:00", - "endsAt": "2019-02-01T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "fe60954c-9d1a-4167-9faa-77027c8d446b", - "name": "Kendall Miller" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - { - "id": "67872", - "title": "Distributed Tracing and Monitoring with OpenCensus", - "description": "OpenCensus is an emerging standard for tracing and metrics of cloud services. You can use it to gain observability into applications that span multiple clouds and technological stacks.\r\nIn this talk, we will use open source and vendor agnostic client libraries for OpenCensus and export telemetry to common distributed tracing systems such as Zipkin and others.\r\nAlong the way. we will discuss core concepts such as tags, metrics, exporters, zPages and trace context propagation. ", - "startsAt": "2019-02-01T16:20:00", - "endsAt": "2019-02-01T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "9aa1b581-80ab-4510-bb28-d5cede7e6460", - "name": "Simon Zeltser" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10585, - "name": "Microservices" - }, - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10575, - "name": "DevOps" - }, - { - "id": 10572, - "name": "Cross-Platform" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - } - ], - "hasOnlyPlenumSessions": false - }, - { - "id": 2779, - "name": "Room 5", - "sessions": [ - { - "id": "67087", - "title": "Fallacies of Doom - Lessons learned from porting Doom 3 to Java", - "description": "\r\nWhile Java has grown enormously over the years, the fundamentals have stagnated.\r\n\r\nThe motivation for this talk and underlying project, was the following question: why is Java, with it’s 20 years of age, and (at least)6 billion running JVM’s not a major player in the video-game development universe?\r\n\r\n#####TL;DR;\r\nSo everybody knows the Doom games, right? Every new installment brought brand new ideas, and groundbreaking graphics. But more importantly, they brought the source code of the prior installment to the public eye.\r\n\r\nNaturally people have played and hacked the code to oblivion, as much as they played the games themselves. And I have the honor to be one of those people.\r\n\r\nI (naively) endeavored to port the Doom 3 C++ code to the fantabulous Java. In doing so, I hoped to learn, among other things, more about 3D graphics.\r\n...what I didn't expect though, was for djoom3(cool name huh!) to teach me more about Java!?\r\n\r\nAside from the basic game development intro, this talk focuses on the following:\r\n- Some areas where Java should learn from it's nemesis, C++\r\n- Other areas where the student(Java) becomes the master(C++)\r\n- And some promises that were made, but never keptWhile Ja", - "startsAt": "2019-02-01T10:20:00", - "endsAt": "2019-02-01T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "981b5372-9139-4fca-90ee-020fba2dafdc", - "name": "Mahmoud Abdelghany" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10568, - "name": "C++" - }, - { - "id": 10579, - "name": "Fun" - }, - { - "id": 10583, - "name": "Languages" - }, - { - "id": 10602, - "name": "Gaming" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - { - "id": "68282", - "title": "Just what is a \"service mesh\", and if I get one will it make everything OK?", - "description": "Communication is the backbone of distributed applications. Imagine you could control that backbone independently of all the components, so your application code just makes simple calls to other services, and your communication backbone does all the complex non-functional work. Load balancing, traffic management, fault tolerance, end-to-end monitoring, dynamic routing and secure communication could all be applied and controlled centrally. That's a service mesh.\r\n\r\nIn this session I'll cover the major features of a service mesh using Istio - which is the most popular technology in this space. I'll show you what you can do with a service mesh, how it simplifies application design and also where it adds complexity. My examples will range from new microservices designs to legacy monoliths, and you'll see what a service mesh can bring to different types of application.", - "startsAt": "2019-02-01T11:40:00", - "endsAt": "2019-02-01T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "e48f1ee5-93ea-4113-a4ca-5de7b129c3ae", - "name": "Elton Stoneman" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10585, - "name": "Microservices" - }, - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10576, - "name": "Docker" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - { - "id": "58138", - "title": "Kubernetes - going beyond the basics", - "description": "In this talk and with demos we'll cover some more advanced topics within Kubernetes such as:-\r\nInfluencing the scheduling of pods\r\nControlling applications being scheduled using admission controllers\r\nAuto-scaling of applications and clusters\r\nOptions for extending/customising Kubernetes using Custom Resources\r\nAdding a service mesh to improve traffic shaping\r\n \r\nAfter this talk attendees should have a much clearer understanding of the additional capability in Kubernetes and associated platforms that they can to use to improve their application platform.\r\n \r\nAttendees should have a good understanding of the basic Kubernetes concepts and constructs.", - "startsAt": "2019-02-01T13:40:00", - "endsAt": "2019-02-01T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "fb14f65c-538d-4980-9010-8ffbd2d8d4b5", - "name": "Shahid Iqbal" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10575, - "name": "DevOps" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - { - "id": "67372", - "title": "3D printed Bionic Hand a little IOT and a Xamarin Mobile App", - "description": "Kayden a local 13yr Old was born with no left forearm and hand, being continually let down by very poor and expensive NHS prosthetics. Being a close friend of the family, I started looking around the web after seeing news reports of home-made devices. I stumbled across the OpenBionics team and the great work they do and set to building a version for Kayden. \r\nAfter 3D printing the parts I moved onto the electronics but this requires building a bespoke board that often needs software changes to set-up and configure. So my version uses off the shelf IOT parts and connects via Bluetooth to a Xamarin .Net application for changing the settings and configuring on Kayden’s phone. Still a work in progress but I will talk about the process used to get this far and how I have hopefully reduced the costs even more from a few hundred to around £80 for future hands and plan to give back to the opensource project.", - "startsAt": "2019-02-01T15:00:00", - "endsAt": "2019-02-01T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "3a76506a-5c6c-4118-937b-6f7b6eefa975", - "name": "Clifford Agius" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10604, - "name": "3D Modeling" - }, - { - "id": 10606, - "name": "Embedded" - }, - { - "id": 10579, - "name": "Fun" - }, - { - "id": 10588, - "name": "People" - }, - { - "id": 10587, - "name": "Mobile" - }, - { - "id": 10581, - "name": "IoT" - }, - { - "id": 10574, - "name": "Design" - }, - { - "id": 10572, - "name": "Cross-Platform" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - { - "id": "66791", - "title": "Kotlin for C# Developers", - "description": "Dive into the latest craze in languages and platforms - Kotlin. This time we will be looking at it from the perspective of a .NET C# developer, draw comparisons between the languages, and bridge the gap between these 2 amazing languages.\r\n\r\nWe'll look at:\r\n- Kotlin as a language\r\n- Platforms Kotlin is great for\r\n- Object Oriented Implementations in Kotlin\r\n- Extended Features\r\n- Features Kotlin has that C# doesn't\r\n- A demo Android application in Kotlin vs a Xamarin.Android app in C#\r\n\r\nIn the end you will leave with a foundational knowledge of Kotlin and its capabilities to build awesome apps with less code. You should feel comfortable comparing C# applications to Kotlin applications and know where to find resources to learn even more!", - "startsAt": "2019-02-01T16:20:00", - "endsAt": "2019-02-01T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "42b758e4-1a7c-434d-9951-ddff53503d1f", - "name": "Alex Dunn" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10583, - "name": "Languages" - }, - { - "id": 10587, - "name": "Mobile" - }, - { - "id": 10580, - "name": "Functional Programming" - }, - { - "id": 10593, - "name": "Tools" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - } - ], - "hasOnlyPlenumSessions": false - }, - { - "id": 2780, - "name": "Room 6", - "sessions": [ - { - "id": "76427", - "title": "Lessons learned building ASP.NET Core MVC", - "description": "Join Ryan Nowak from the ASP.NET Core team as he shares learnings from building the framework, improving performance, and helping customers. We’ll talk about design details of Razor Pages and Controllers for Web and APIs, as well as hidden gems and power user features. Come learn how MVC works and get some useful tips from one of the core developers.", - "startsAt": "2019-02-01T10:20:00", - "endsAt": "2019-02-01T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "cdbc7319-2548-46b7-9ba8-e8c1e299465e", - "name": "Ryan Nowak" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - }, - { - "id": "69938", - "title": "The promise of an async future awaits", - "description": "The prominent trends in software a distributed programs powered by cooperating microservices, each operating independently. These distributed systems are asynchronous by their very nature. You will use asynchronous programming paradigms to build these systesms.\r\n\r\nIn this session, you'll see the most common mistakes developers make using async and await in C#. You'll see the practices you should use instead. This session also provides a deep dive into async streams, a new feature introduced in C# 8.\r\n\r\nYou're building asynchronous programs now. Make sure you're building them for the future.", - "startsAt": "2019-02-01T15:00:00", - "endsAt": "2019-02-01T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "be2a42b5-fc04-47c8-860b-7c503a8c6854", - "name": "Bill Wagner" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - }, - { - "id": "68532", - "title": "A Piece of Git", - "description": "You use Git, and maybe you even know the internals: all those blobs, trees, commits and refs make it look like Git is sane, well-designed and organized system. But is it, really?\r\n\r\nAfter all, why are there three different kinds of rebase? What makes merge recursive? And what's the deal with line ending normalization? Edward Thomson shows off some of the weirder idiosyncrasies in Git and why it works the way it does.", - "startsAt": "2019-02-01T16:20:00", - "endsAt": "2019-02-01T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "fee375b8-047c-4ea2-ab43-9837f2420b19", - "name": "Edward Thomson" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10593, - "name": "Tools" - }, - { - "id": 10575, - "name": "DevOps" - } - ], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - } - ], - "hasOnlyPlenumSessions": false - } - ], - "timeSlots": [ - { - "slotStart": "09:00:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "session": { - "id": "69232", - "title": "Keynote: The Microsoft Open Source Cinematic Universe - Phase 2", - "description": "Phase 1 is nearly complete with open source .NET Core. What does Microsoft's Open Source plan look like for the next 10 years?\r\n\r\nJoin Scott Hanselman as he compares the MCU (Marvel Cinematic Universe) to the MSFTOSSCU and talks about what a next phase MIGHT look like.", - "startsAt": "2019-02-01T09:00:00", - "endsAt": "2019-02-01T10:00:00", - "isServiceSession": false, - "isPlenumSession": true, - "speakers": [ - { - "id": "142dd289-d6c7-4385-9f36-05b816ceea2c", - "name": "Scott Hanselman" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - "index": 0 - } - ] - }, - { - "slotStart": "10:20:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "session": { - "id": "69004", - "title": "Async injection", - "description": "This talk attempts to answer a pair of frequently asked questions, the first one of which is: how do I combine dependency injection with async and await in C# without leaky abstractions?\r\n\r\nIt turns out that the answer to that question can be found by answering another frequently asked question: how do I get the value out of my monad?\r\n\r\nDuring the talk, you’ll get a quick and easy-to-understand explanation of monads.\r\n\r\nAll code examples will be in C#.", - "startsAt": "2019-02-01T10:20:00", - "endsAt": "2019-02-01T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "84f7d361-4388-44ad-bc48-31695762bc6d", - "name": "Mark Seemann" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10580, - "name": "Functional Programming" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - "index": 0 - }, - { - "id": 2776, - "name": "Room 2", - "session": { - "id": "69239", - "title": "Ctrl-Alt-Del: Learning to Love Legacy Code", - "description": "The world runs on legacy code. For every greenfield progressive web app with 100% test coverage, there are literally hundreds of archaic line-of-business applications running in production - systems with no tests, no documentation, built using out-of-date tools, languages and platforms. It’s the code developers love to hate: it’s not exciting, it’s not shiny, and it won’t look good on your CV - but the world runs on legacy code, and, as developers, if we’re going to work on anything that actually matters, we’re going to end up dealing with legacy. To work effectively with this kind of system, we need to answer some fundamental questions: why was it built this way in the first place? What's happened over the years it's been running in production? And, most importantly, how can we develop our understanding of legacy codebases to the point where we're confident that we can add features, fix bugs and improve performance without making things worse?\r\n\r\nDylan worked on the web application stack at Spotlight (www.spotlight.com) from 2000 until 2018 - first as a supplier, then as webmaster, then as systems architect. Working on the same codebase for nearly two decades has given him an unusual perspective on how applications go from being cutting-edge to being 'legacy'. In this talk, he'll share tips, patterns and techniques that he's learned from helping new developers work with a large and unfamiliar codebase. We'll talk about virtualisation, refactoring tools, and how to bring legacy code under control using continuous integration and managed deployments. We'll explore creative ways to use common technologies like DNS to create more productive development environments. We'll talk about how to bridge the gap between automated testing and systems monitoring, how to improve visibility and transparency of your production systems - and why good old Ctrl-Alt-Del might be the secret to unlocking the potential of your legacy codebase.", - "startsAt": "2019-02-01T10:20:00", - "endsAt": "2019-02-01T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "1d7dcbfc-1de6-4228-8bd6-04f4ba1c4267", - "name": "Dylan Beattie" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10571, - "name": "Continuous Delivery" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - "index": 1 - }, - { - "id": 2777, - "name": "Room 3", - "session": { - "id": "69231", - "title": "C# 8", - "description": "It's nearly here! The Visual Studio 2019 Preview is already available, so if you haven't looked into what's coming in C# 8, now is the perfect time to do so.\r\nThe most important feature of C# 8 is undoubtedly nullable reference types, but there's plenty more to look forward to as well.\r\n\r\nWhile I'll make this talk as easy to understand as I can, there's a huge amount to cover. Expect a fast pace, with lots of code.", - "startsAt": "2019-02-01T10:20:00", - "endsAt": "2019-02-01T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "1176547b-89c5-40ee-b7d7-bf0eb5ca0aef", - "name": "Jon Skeet" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - "index": 2 - }, - { - "id": 2778, - "name": "Room 4", - "session": { - "id": "58161", - "title": "Making Accessibility Testing Suck Less: An Intro to Pa11y.", - "description": "Often the hardest part of any problem is simply how to get started. On the ever-evolving web accessibility is a matter of ongoing importance: the brilliance of your code or sleekness of your UI is inconsequential if your app or website is unusable to some of your users. With a million other issues already on your plate how do you find a way to get started on accessibility testing? Pa11y to the rescue! Pa11y is a lightweight command-line accessibility testing tool with enough flexibility to integrate results into your current testing process. This talk will explain what pa11y does and does not cover, review examples of both command line and scripted usage, dive into the pa11y web service and show how to modify output to work in your current testing setup. Bonus content: how to convince the rest of your team and business why accessibility is worth prioritizing and how getting started with low-hanging fruit can vastly improve your product.", - "startsAt": "2019-02-01T10:20:00", - "endsAt": "2019-02-01T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "e5b9e6c6-1477-4b19-8347-06683a7417de", - "name": "Jennifer Wadella" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10592, - "name": "Testing" - }, - { - "id": 10582, - "name": "JavaScript" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - "index": 3 - }, - { - "id": 2779, - "name": "Room 5", - "session": { - "id": "67087", - "title": "Fallacies of Doom - Lessons learned from porting Doom 3 to Java", - "description": "\r\nWhile Java has grown enormously over the years, the fundamentals have stagnated.\r\n\r\nThe motivation for this talk and underlying project, was the following question: why is Java, with it’s 20 years of age, and (at least)6 billion running JVM’s not a major player in the video-game development universe?\r\n\r\n#####TL;DR;\r\nSo everybody knows the Doom games, right? Every new installment brought brand new ideas, and groundbreaking graphics. But more importantly, they brought the source code of the prior installment to the public eye.\r\n\r\nNaturally people have played and hacked the code to oblivion, as much as they played the games themselves. And I have the honor to be one of those people.\r\n\r\nI (naively) endeavored to port the Doom 3 C++ code to the fantabulous Java. In doing so, I hoped to learn, among other things, more about 3D graphics.\r\n...what I didn't expect though, was for djoom3(cool name huh!) to teach me more about Java!?\r\n\r\nAside from the basic game development intro, this talk focuses on the following:\r\n- Some areas where Java should learn from it's nemesis, C++\r\n- Other areas where the student(Java) becomes the master(C++)\r\n- And some promises that were made, but never keptWhile Ja", - "startsAt": "2019-02-01T10:20:00", - "endsAt": "2019-02-01T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "981b5372-9139-4fca-90ee-020fba2dafdc", - "name": "Mahmoud Abdelghany" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10568, - "name": "C++" - }, - { - "id": 10579, - "name": "Fun" - }, - { - "id": 10583, - "name": "Languages" - }, - { - "id": 10602, - "name": "Gaming" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - "index": 4 - }, - { - "id": 2780, - "name": "Room 6", - "session": { - "id": "76427", - "title": "Lessons learned building ASP.NET Core MVC", - "description": "Join Ryan Nowak from the ASP.NET Core team as he shares learnings from building the framework, improving performance, and helping customers. We’ll talk about design details of Razor Pages and Controllers for Web and APIs, as well as hidden gems and power user features. Come learn how MVC works and get some useful tips from one of the core developers.", - "startsAt": "2019-02-01T10:20:00", - "endsAt": "2019-02-01T11:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "cdbc7319-2548-46b7-9ba8-e8c1e299465e", - "name": "Ryan Nowak" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - }, - "index": 5 - } - ] - }, - { - "slotStart": "11:40:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "session": { - "id": "68521", - "title": "From 'dotnet run' to 'Hello World!'", - "description": "Have you ever stopped to think about all the things that happen when you execute a simple .NET program?\r\n\r\nThis talk will delve into the internals of the recently open-sourced .NET Core runtime, looking at what happens, when it happens and why. \r\n\r\nMaking use of freely available tools such as 'PerfView', we'll examine the Execution Engine, Type Loader, Just-in-Time (JIT) Compiler and the CLR Hosting API to see how all these components play a part in making 'Hello World' possible.", - "startsAt": "2019-02-01T11:40:00", - "endsAt": "2019-02-01T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "fb89e2c6-39b1-4ef8-8932-609504cf4901", - "name": "Matt Warren" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10593, - "name": "Tools" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - "index": 0 - }, - { - "id": 2776, - "name": "Room 2", - "session": { - "id": "67993", - "title": "The Functional Programmer's Toolkit", - "description": "The functional programming community has a number of patterns with strange names such as monads, monoids, functors, and catamorphisms.\r\n \r\nIn this beginner-friendly talk, we'll demystify these techniques and see how they all fit together into a small but versatile \"tool kit\". \r\n\r\nWe'll then see how the tools in this tool kit can be applied to a wide variety of programming problems, such as handling missing data, working with lists, and implementing the functional equivalent of dependency injection. ", - "startsAt": "2019-02-01T11:40:00", - "endsAt": "2019-02-01T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "89335661-3092-4afa-b53f-3d203cafa2a1", - "name": "Scott Wlaschin" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10580, - "name": "Functional Programming" - }, - { - "id": 10574, - "name": "Design" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - "index": 1 - }, - { - "id": 2777, - "name": "Room 3", - "session": { - "id": "67078", - "title": "APIs Exposed!", - "description": "More and more developers are building APIs, whether that be for consumption by client-side applications, exposing endpoints directly to customers so they can use an alternative front-end or wrapping up services in containers.\r\n\r\nNow that we have all these exposed endpoints, what are we doing to secure them? Previously, our monolith was self-contained with limited points of access making authentication and authorisation more straightforward - that’s no longer the case.\r\n\r\nWe’ll cover the potential risks we may face such as cross-site scripting and BruteForce attacks as well as a look at the possible options for securing API endpoints including OAuth, Access Tokens, JSON web tokens, IP whitelisting, rate limiting to name but a few.\r\n\r\n", - "startsAt": "2019-02-01T11:40:00", - "endsAt": "2019-02-01T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "ac105033-2b20-4b45-8d47-5647d8accf84", - "name": "Layla Porter" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10589, - "name": "Security" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - "index": 2 - }, - { - "id": 2778, - "name": "Room 4", - "session": { - "id": "62532", - "title": "A Developer's Guide to Advertising", - "description": "Love it or hate it, advertising is currently a main source of revenue for many websites. But digital advertising is a complicated space that not many developers understand. If you'd like to understand the ad code on your site better, if your ad ops team has been talking about header bidding, or if you're just curious about how ads work, this is the talk for you. I'll give an overview of how programmatic advertising works, what header bidding is, explain some common tools and libraries, and address some common misconceptions and complaints about ads.", - "startsAt": "2019-02-01T11:40:00", - "endsAt": "2019-02-01T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "b8f3c690-5950-4279-9ee7-9291d1439dd2", - "name": "Krista LaFentres" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10596, - "name": "Web" - }, - { - "id": 10582, - "name": "JavaScript" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - "index": 3 - }, - { - "id": 2779, - "name": "Room 5", - "session": { - "id": "68282", - "title": "Just what is a \"service mesh\", and if I get one will it make everything OK?", - "description": "Communication is the backbone of distributed applications. Imagine you could control that backbone independently of all the components, so your application code just makes simple calls to other services, and your communication backbone does all the complex non-functional work. Load balancing, traffic management, fault tolerance, end-to-end monitoring, dynamic routing and secure communication could all be applied and controlled centrally. That's a service mesh.\r\n\r\nIn this session I'll cover the major features of a service mesh using Istio - which is the most popular technology in this space. I'll show you what you can do with a service mesh, how it simplifies application design and also where it adds complexity. My examples will range from new microservices designs to legacy monoliths, and you'll see what a service mesh can bring to different types of application.", - "startsAt": "2019-02-01T11:40:00", - "endsAt": "2019-02-01T12:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "e48f1ee5-93ea-4113-a4ca-5de7b129c3ae", - "name": "Elton Stoneman" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10585, - "name": "Microservices" - }, - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10576, - "name": "Docker" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - "index": 4 - } - ] - }, - { - "slotStart": "13:40:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "session": { - "id": "69233", - "title": "Solving Diabetes with an Open Source Artificial Pancreas", - "description": "Scott has been a Type 1 diabetic for over 20 years. When he first became diabetic he did what every engineer would do...he wrote an app to solve his problem. Fast forward to 2018 and Scott lives 24 hours a day connected to an open source artificial pancreas. After years of waiting, the diabetes community online creating solutions.\r\n\r\nScott will go through the history of diabetes online, the components (both hardware and software) needed for an artificial pancreas, and discuss the architectural design of two popular systems (LoopKit and OpenAPS). Plus, you'll see Scott *not die* live on stage as he's been \"looping\" for over a year!", - "startsAt": "2019-02-01T13:40:00", - "endsAt": "2019-02-01T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "142dd289-d6c7-4385-9f36-05b816ceea2c", - "name": "Scott Hanselman" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - "index": 0 - }, - { - "id": 2776, - "name": "Room 2", - "session": { - "id": "69230", - "title": "Society (n+1).0: smashing the patriarchy and other ways of changing the world", - "description": "Software engineers are fond of casually mentioning how their work changes the world. But have you thought about what you want the world to look like after you've changed it? Do you want to smash the patriarchy [1]? Save the planet? Make Furbies cool again? Is technology really the only tool at your disposal?\r\nThis session is a call to both discovery and action. You already care about Furbies, but what do you not know you don't know about them? Have you looked at Furbies from someone else's perspective? Once your eyes are wide open, what's the next step? How would a Furby smash the patriarchy? Let's learn to be better together, and make a difference in the world today.\r\n\r\nFootnote 1: Our system of society norms which puts everyone in boxes that are hard to escape [2]. The boxes surrounding straight white men can be extremely comfortable ones, but more limiting than you might realize.\r\n\r\nFootnote 2: Furbies are pretty easy to get out of boxes; humans, not so much.", - "startsAt": "2019-02-01T13:40:00", - "endsAt": "2019-02-01T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "1176547b-89c5-40ee-b7d7-bf0eb5ca0aef", - "name": "Jon Skeet" - }, - { - "id": "e5b9e6c6-1477-4b19-8347-06683a7417de", - "name": "Jennifer Wadella" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - "index": 1 - }, - { - "id": 2777, - "name": "Room 3", - "session": { - "id": "69366", - "title": "Architectural patterns for the cloud", - "description": "As more and more people are starting to deploy their application to the cloud, new architectural patterns have emerged, and some old ones have resurfaced or become more prominent.\r\n\r\nIn this session, Mahesh Krishnan, will run through a large catalogue of cloud patterns that will cover categories such as availability, resiliency, data management, performance, scalability, design and implementation. You will learn about what problem each and every pattern addresses, how to implement them and what considerations you need to take into account while implementing them.", - "startsAt": "2019-02-01T13:40:00", - "endsAt": "2019-02-01T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "648e2e9d-28cc-47ef-828c-75a7d599d48d", - "name": "Mahesh Krishnan" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10569, - "name": "Cloud" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - "index": 2 - }, - { - "id": 2778, - "name": "Room 4", - "session": { - "id": "68894", - "title": "\"Hey Mycroft\": Getting Started with the OSS Home Assistant", - "description": "Home virtual assistants, like Alexa, Google Now, Siri, and Cortana, are gaining a lot of popularity. They’re now incorporated into our phones, our laptops, and even available as separate devices in our homes. Some people haven’t adopted them out of privacy concerns. A new system called Mycroft has come onto the scene, and it’s built on open source hardware and software. You can install it on a Raspberry Pi, an old Linux box, or buy their own Mycroft device.\r\n\r\nIn this session, we’ll go over the basics of what Mycroft is, and how you can quickly install it yourself. From there, we’ll talk about some of the underlying software and see a short demo. Finally, we’ll see how to build a new skill into it and contribute it back to the community. You’ll leave with your own virtual assistant and the knowledge on how make it do what you want but keep your privacy in check.", - "startsAt": "2019-02-01T13:40:00", - "endsAt": "2019-02-01T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "97e1c796-8bf6-468b-b246-0efc6979b9e7", - "name": "Sarah Withee" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10581, - "name": "IoT" - }, - { - "id": 10565, - "name": "AI" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - "index": 3 - }, - { - "id": 2779, - "name": "Room 5", - "session": { - "id": "58138", - "title": "Kubernetes - going beyond the basics", - "description": "In this talk and with demos we'll cover some more advanced topics within Kubernetes such as:-\r\nInfluencing the scheduling of pods\r\nControlling applications being scheduled using admission controllers\r\nAuto-scaling of applications and clusters\r\nOptions for extending/customising Kubernetes using Custom Resources\r\nAdding a service mesh to improve traffic shaping\r\n \r\nAfter this talk attendees should have a much clearer understanding of the additional capability in Kubernetes and associated platforms that they can to use to improve their application platform.\r\n \r\nAttendees should have a good understanding of the basic Kubernetes concepts and constructs.", - "startsAt": "2019-02-01T13:40:00", - "endsAt": "2019-02-01T14:40:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "fb14f65c-538d-4980-9010-8ffbd2d8d4b5", - "name": "Shahid Iqbal" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10575, - "name": "DevOps" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - "index": 4 - } - ] - }, - { - "slotStart": "15:00:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "session": { - "id": "69010", - "title": "Crash, Burn, Report", - "description": "With the launch of the Reporting API any browser that visits your site can automatically detect and alert you to a whole heap of problems with your application. DNS not resolving? Serving an invalid certificate? Got a redirect loop, using a soon to be deprecated API or any one of countless other problems, they can all be detected and reported with no user action, no agents, no code to deploy. You have one of the most extensive and powerful monitoring platforms in existence at your disposal, millions of browsers. Let's look at how to use them.\r\n\r\nIn this talk we'll look at how to configure the browser to send you reports when things go wrong. These are brand new capabilities the likes of which we've haven't seen before and they're already supported in the world's most popular browser, Google Chrome. We'll look at how to receive reports and how to make use of them after having the browser do the hard work.", - "startsAt": "2019-02-01T15:00:00", - "endsAt": "2019-02-01T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "e9c64362-6194-409c-85da-45c8fd40abd6", - "name": "Scott Helme" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - "index": 0 - }, - { - "id": 2776, - "name": "Room 2", - "session": { - "id": "69307", - "title": "Tabs, spaces and salaries: a data science detective story", - "description": "In data science, sometimes you stumble across an intriguing property in the data. I will tell you a story of a mysterious correlation - from the StackOverflow developer survey it seems that developers who use spaces have higher salaries than those who use tabs. Correlation doesn't mean causation: using spaces won't suddenly increase your salary. But what does it all mean? Follow me into a detective investigation that will show you how to approach complex data science problems. I will show you some of the perils of correlation, model fitting and biases - how they can be dangerous and how to avoid these traps. And you'll also find how profitable your indentation style really is.", - "startsAt": "2019-02-01T15:00:00", - "endsAt": "2019-02-01T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "14fdabdd-3814-4f84-868e-a8178a25c5f8", - "name": "Evelina Gabasova" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10584, - "name": "Machine Learning" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - "index": 1 - }, - { - "id": 2777, - "name": "Room 3", - "session": { - "id": "66814", - "title": "Unity 101 for C# Developers", - "description": "If you are interested in mixed or virtual reality development then Unity is a tool you’ll want to learn. Go to Microsoft’s [Hololens development page](https://developer.microsoft.com/en-us/windows/mixed-reality/install_the_tools) and you’ll find the installation of Unity recommended in the first paragraph.\r\n\r\nOne surprise to developers getting started with Unity is the level of integration with Visual Studio and how easy it is to add C# to manipulate your 3D world.\r\n\r\nIn this demo led session we’ll go back to basics with Unity, easily creating a simple 3D experience with realistic physics. We’ll look at the fantastic Visual Studio integration and how easily the two editors work together.\r\n\r\nFinally we’ll look at the ways in which we can give our 3D experience some polish by adding textures, animations and some explosions!\r\n\r\nKeeping the best news for last: Unity is royalty free until you’re earning $100,000 – so if you like the idea of becoming wildly rich from making immersive 3D experiences this is the talk for you.", - "startsAt": "2019-02-01T15:00:00", - "endsAt": "2019-02-01T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "ef4df68d-9bdc-471d-aff0-075c77c4a424", - "name": "Andy Clarke" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10603, - "name": "VR" - }, - { - "id": 10604, - "name": "3D Modeling" - }, - { - "id": 10602, - "name": "Gaming" - }, - { - "id": 10579, - "name": "Fun" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - "index": 2 - }, - { - "id": 2778, - "name": "Room 4", - "session": { - "id": "68882", - "title": "Megahertz, Gigahertz, Registers and Instructions: How does a CPU actually work?", - "description": "For decades, we’ve been creating ever higher abstractions between ourselves and the computing hardware we’re programming, but in the end whether you’re writing JavaScript, Haskell, or Python it all comes down to 1’s and 0’s running through hardware patterns that were well understood twenty years ago.\r\n\r\nWe’ll walk through the fundamentals of how CPU’s “think” in an accessible way (no engineering degree required!) so you can appreciate the marvel that is the modern CPU be it in a server data center or your fridge at home. You’ll learn how a CPU turns the code we feed it into actions, what’s the big difference between an ARM and an Intel processor, how CPU’s constantly optimize work for us, and where is it all going for the next few years.\r\n\r\nFinally, we'll show how Meltdown and Spectre take advantage of CPU internals to expose data and why this class of security problems are going to be a challenge to the next generation of CPU's.\r\n", - "startsAt": "2019-02-01T15:00:00", - "endsAt": "2019-02-01T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "fe60954c-9d1a-4167-9faa-77027c8d446b", - "name": "Kendall Miller" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - "index": 3 - }, - { - "id": 2779, - "name": "Room 5", - "session": { - "id": "67372", - "title": "3D printed Bionic Hand a little IOT and a Xamarin Mobile App", - "description": "Kayden a local 13yr Old was born with no left forearm and hand, being continually let down by very poor and expensive NHS prosthetics. Being a close friend of the family, I started looking around the web after seeing news reports of home-made devices. I stumbled across the OpenBionics team and the great work they do and set to building a version for Kayden. \r\nAfter 3D printing the parts I moved onto the electronics but this requires building a bespoke board that often needs software changes to set-up and configure. So my version uses off the shelf IOT parts and connects via Bluetooth to a Xamarin .Net application for changing the settings and configuring on Kayden’s phone. Still a work in progress but I will talk about the process used to get this far and how I have hopefully reduced the costs even more from a few hundred to around £80 for future hands and plan to give back to the opensource project.", - "startsAt": "2019-02-01T15:00:00", - "endsAt": "2019-02-01T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "3a76506a-5c6c-4118-937b-6f7b6eefa975", - "name": "Clifford Agius" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10604, - "name": "3D Modeling" - }, - { - "id": 10606, - "name": "Embedded" - }, - { - "id": 10579, - "name": "Fun" - }, - { - "id": 10588, - "name": "People" - }, - { - "id": 10587, - "name": "Mobile" - }, - { - "id": 10581, - "name": "IoT" - }, - { - "id": 10574, - "name": "Design" - }, - { - "id": 10572, - "name": "Cross-Platform" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - "index": 4 - }, - { - "id": 2780, - "name": "Room 6", - "session": { - "id": "69938", - "title": "The promise of an async future awaits", - "description": "The prominent trends in software a distributed programs powered by cooperating microservices, each operating independently. These distributed systems are asynchronous by their very nature. You will use asynchronous programming paradigms to build these systesms.\r\n\r\nIn this session, you'll see the most common mistakes developers make using async and await in C#. You'll see the practices you should use instead. This session also provides a deep dive into async streams, a new feature introduced in C# 8.\r\n\r\nYou're building asynchronous programs now. Make sure you're building them for the future.", - "startsAt": "2019-02-01T15:00:00", - "endsAt": "2019-02-01T16:00:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "be2a42b5-fc04-47c8-860b-7c503a8c6854", - "name": "Bill Wagner" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - }, - "index": 5 - } - ] - }, - { - "slotStart": "16:20:00", - "rooms": [ - { - "id": 2775, - "name": "Room 1", - "session": { - "id": "66952", - "title": "Futurology for Dummies - the Next 30 Years in Tech", - "description": "2019 is the 30th anniversary of my first job in tech. On my first day I was given a Wyse 60 terminal attached via RS232 cables to a Tandon 286, and told to learn C from a dead tree so I could write text applications for an 80x24 character screen. Fast-forward to now: my phone is about a million times more powerful than that Tandon; screens are 3840x2160 pixels; every computer in the world is attached to every other thing with no cables; and we code using, well, still basically C.\r\n\r\nHaving lived through all those changes in realtime, and as an incurable neophile, I think I can make an educated guess as to what the next 30 years are going to be like, and what we're all going to be doing by 2049. If anything, I'm going to underestimate it, but hopefully you'll be inspired, invigorated and maybe even informed about the future of your career in tech.", - "startsAt": "2019-02-01T16:20:00", - "endsAt": "2019-02-01T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "70590ad0-b1b3-40b8-b05d-b58722ef9d9d", - "name": "Mark Rendle" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10579, - "name": "Fun" - }, - { - "id": 10584, - "name": "Machine Learning" - }, - { - "id": 10581, - "name": "IoT" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10565, - "name": "AI" - }, - { - "id": 10593, - "name": "Tools" - }, - { - "id": 10594, - "name": "UI" - }, - { - "id": 10595, - "name": "UX" - }, - { - "id": 10596, - "name": "Web" - }, - { - "id": 10574, - "name": "Design" - }, - { - "id": 10587, - "name": "Mobile" - }, - { - "id": 10604, - "name": "3D Modeling" - }, - { - "id": 10603, - "name": "VR" - } - ], - "sort": 4 - } - ], - "roomId": 2775, - "room": "Room 1" - }, - "index": 0 - }, - { - "id": 2776, - "name": "Room 2", - "session": { - "id": "67994", - "title": "Four Languages from Forty Years Ago", - "description": "The 1970's were a golden age for new programming languages, but do they have any relevance to programming today? Can we still learn from them?\r\n\r\nIn this talk, we'll look at four languages designed over forty years ago -- SQL, Prolog, ML, and Smalltalk -- and discuss their philosophy and approach to programming, which is very different from most popular languages today.\r\n\r\nWe'll come away with some practical principles that are still very applicable to modern development. And you might discover your new favorite programming paradigm!\r\n", - "startsAt": "2019-02-01T16:20:00", - "endsAt": "2019-02-01T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "89335661-3092-4afa-b53f-3d203cafa2a1", - "name": "Scott Wlaschin" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10583, - "name": "Languages" - } - ], - "sort": 4 - } - ], - "roomId": 2776, - "room": "Room 2" - }, - "index": 1 - }, - { - "id": 2777, - "name": "Room 3", - "session": { - "id": "67138", - "title": "Deep Learning in the world of little ponies", - "description": "In this talk, we will discuss computer vision, one of the most common real-world applications of machine learning. We will deep dive into various state-of-the-art concepts around building custom image classifiers - application of deep neural networks, specifically convolutional neural networks and transfer learning. We will demonstrate how those approaches could be used to create your own image classifier to recognise the characters of \"My Little Pony\" TV Series [or Pokemon, or Superheroes, or your custom images].", - "startsAt": "2019-02-01T16:20:00", - "endsAt": "2019-02-01T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "b4c506ac-9757-4ac6-8b7c-3d6696b113e4", - "name": "Galiya Warrier" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10584, - "name": "Machine Learning" - }, - { - "id": 10579, - "name": "Fun" - }, - { - "id": 10565, - "name": "AI" - } - ], - "sort": 4 - } - ], - "roomId": 2777, - "room": "Room 3" - }, - "index": 2 - }, - { - "id": 2778, - "name": "Room 4", - "session": { - "id": "67872", - "title": "Distributed Tracing and Monitoring with OpenCensus", - "description": "OpenCensus is an emerging standard for tracing and metrics of cloud services. You can use it to gain observability into applications that span multiple clouds and technological stacks.\r\nIn this talk, we will use open source and vendor agnostic client libraries for OpenCensus and export telemetry to common distributed tracing systems such as Zipkin and others.\r\nAlong the way. we will discuss core concepts such as tags, metrics, exporters, zPages and trace context propagation. ", - "startsAt": "2019-02-01T16:20:00", - "endsAt": "2019-02-01T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "9aa1b581-80ab-4510-bb28-d5cede7e6460", - "name": "Simon Zeltser" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10585, - "name": "Microservices" - }, - { - "id": 10566, - "name": "Architecture" - }, - { - "id": 10575, - "name": "DevOps" - }, - { - "id": 10572, - "name": "Cross-Platform" - }, - { - "id": 10569, - "name": "Cloud" - }, - { - "id": 10563, - "name": ".NET" - } - ], - "sort": 4 - } - ], - "roomId": 2778, - "room": "Room 4" - }, - "index": 3 - }, - { - "id": 2779, - "name": "Room 5", - "session": { - "id": "66791", - "title": "Kotlin for C# Developers", - "description": "Dive into the latest craze in languages and platforms - Kotlin. This time we will be looking at it from the perspective of a .NET C# developer, draw comparisons between the languages, and bridge the gap between these 2 amazing languages.\r\n\r\nWe'll look at:\r\n- Kotlin as a language\r\n- Platforms Kotlin is great for\r\n- Object Oriented Implementations in Kotlin\r\n- Extended Features\r\n- Features Kotlin has that C# doesn't\r\n- A demo Android application in Kotlin vs a Xamarin.Android app in C#\r\n\r\nIn the end you will leave with a foundational knowledge of Kotlin and its capabilities to build awesome apps with less code. You should feel comfortable comparing C# applications to Kotlin applications and know where to find resources to learn even more!", - "startsAt": "2019-02-01T16:20:00", - "endsAt": "2019-02-01T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "42b758e4-1a7c-434d-9951-ddff53503d1f", - "name": "Alex Dunn" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10563, - "name": ".NET" - }, - { - "id": 10583, - "name": "Languages" - }, - { - "id": 10587, - "name": "Mobile" - }, - { - "id": 10580, - "name": "Functional Programming" - }, - { - "id": 10593, - "name": "Tools" - } - ], - "sort": 4 - } - ], - "roomId": 2779, - "room": "Room 5" - }, - "index": 4 - }, - { - "id": 2780, - "name": "Room 6", - "session": { - "id": "68532", - "title": "A Piece of Git", - "description": "You use Git, and maybe you even know the internals: all those blobs, trees, commits and refs make it look like Git is sane, well-designed and organized system. But is it, really?\r\n\r\nAfter all, why are there three different kinds of rebase? What makes merge recursive? And what's the deal with line ending normalization? Edward Thomson shows off some of the weirder idiosyncrasies in Git and why it works the way it does.", - "startsAt": "2019-02-01T16:20:00", - "endsAt": "2019-02-01T17:20:00", - "isServiceSession": false, - "isPlenumSession": false, - "speakers": [ - { - "id": "fee375b8-047c-4ea2-ab43-9837f2420b19", - "name": "Edward Thomson" - } - ], - "categories": [ - { - "id": 2223, - "name": "Tags", - "categoryItems": [ - { - "id": 10593, - "name": "Tools" - }, - { - "id": 10575, - "name": "DevOps" - } - ], - "sort": 4 - } - ], - "roomId": 2780, - "room": "Room 6" - }, - "index": 5 - } - ] - } - ] - } -] \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Import/NDC_Sydney_2018.json b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Import/NDC_Sydney_2018.json deleted file mode 100644 index 705e4160bac7c350d7cf32954e365331fbf37230..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1158566 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 z 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 oLx=pB=dJ07xG|Lbc%0fy#9i~s-t diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Session.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Session.cs index 27b6ae5c..a3b7cbf4 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Session.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Session.cs @@ -6,12 +6,10 @@ namespace BackEnd.Data { public class Session : ConferenceDTO.Session { - public Conference Conference { get; set; } - public virtual ICollection SessionSpeakers { get; set; } - public Track Track { get; set; } + public virtual ICollection SessionAttendees { get; set; } - public virtual ICollection SessionTags { get; set; } + public Track Track { get; set; } } } \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/SessionAttendee.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/SessionAttendee.cs index e2733836..6c358231 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/SessionAttendee.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/SessionAttendee.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -7,11 +7,11 @@ namespace BackEnd.Data { public class SessionAttendee { - public int SessionID { get; set; } + public int SessionId { get; set; } public Session Session { get; set; } - public int AttendeeID { get; set; } + public int AttendeeId { get; set; } public Attendee Attendee { get; set; } } diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/SessionSpeaker.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/SessionSpeaker.cs index 73cf57b9..e69ffca2 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/SessionSpeaker.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/SessionSpeaker.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using ConferenceDTO; namespace BackEnd.Data { diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/SessionTag.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/SessionTag.cs deleted file mode 100644 index d2f59a17..00000000 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/SessionTag.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace BackEnd.Data -{ - public class SessionTag - { - public int SessionID { get; set; } - - public Session Session { get; set; } - - public int TagID { get; set; } - - public Tag Tag { get; set; } - } -} \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/SessionizeLoader.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/SessionizeLoader.cs index bf5f02af..a65c399f 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/SessionizeLoader.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/SessionizeLoader.cs @@ -10,17 +10,15 @@ namespace BackEnd { public class SessionizeLoader : DataLoader { - public override async Task LoadDataAsync(string conferenceName, Stream fileStream, ApplicationDbContext db) + public override async Task LoadDataAsync(Stream fileStream, ApplicationDbContext db) { - //var blah = new RootObject().rooms[0].sessions[0].speakers[0].name; + // var blah = new RootObject().rooms[0].sessions[0].speakers[0].name; var addedSpeakers = new Dictionary(); var addedTracks = new Dictionary(); - var addedTags = new Dictionary(); var array = await JToken.LoadAsync(new JsonTextReader(new StreamReader(fileStream))); - var conference = new Conference { Name = conferenceName }; - + var root = array.ToObject>(); foreach (var date in root) @@ -29,7 +27,7 @@ public override async Task LoadDataAsync(string conferenceName, Stream fileStrea { if (!addedTracks.ContainsKey(room.name)) { - var thisTrack = new Track { Name = room.name, Conference = conference }; + var thisTrack = new Track { Name = room.name }; db.Tracks.Add(thisTrack); addedTracks.Add(thisTrack.Name, thisTrack); } @@ -46,19 +44,8 @@ public override async Task LoadDataAsync(string conferenceName, Stream fileStrea } } - foreach (var category in thisSession.categories) - { - if (!addedTags.ContainsKey(category.name)) - { - var thisTag = new Tag { Name = category.name }; - db.Tags.Add(thisTag); - addedTags.Add(thisTag.Name, thisTag); - } - } - var session = new Session { - Conference = conference, Title = thisSession.title, StartTime = thisSession.startsAt, EndTime = thisSession.endsAt, diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Tag.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Tag.cs deleted file mode 100644 index 6e872ac5..00000000 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Tag.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Collections.Generic; - -namespace BackEnd.Data -{ - public class Tag : ConferenceDTO.Tag - { - public virtual ICollection SessionTags { get; set; } - } -} \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Track.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Track.cs index 6f72f990..ea8393b0 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Track.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Data/Track.cs @@ -6,9 +6,6 @@ namespace BackEnd.Data { public class Track : ConferenceDTO.Track { - [Required] - public Conference Conference { get; set; } - public virtual ICollection Sessions { get; set; } } } \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Infrastructure/EntityExtensions.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Infrastructure/EntityExtensions.cs index ca77dfec..26dc76ac 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Infrastructure/EntityExtensions.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Infrastructure/EntityExtensions.cs @@ -11,38 +11,30 @@ public static class EntityExtensions public static ConferenceDTO.SessionResponse MapSessionResponse(this Session session) => new ConferenceDTO.SessionResponse { - ID = session.ID, + Id = session.Id, Title = session.Title, StartTime = session.StartTime, EndTime = session.EndTime, - Tags = session.SessionTags? - .Select(st => new ConferenceDTO.Tag - { - ID = st.TagID, - Name = st.Tag.Name - }) - .ToList(), Speakers = session.SessionSpeakers? .Select(ss => new ConferenceDTO.Speaker { - ID = ss.SpeakerId, + Id = ss.SpeakerId, Name = ss.Speaker.Name }) .ToList(), TrackId = session.TrackId, Track = new ConferenceDTO.Track { - TrackID = session?.TrackId ?? 0, + Id = session?.TrackId ?? 0, Name = session.Track?.Name }, - ConferenceID = session.ConferenceID, Abstract = session.Abstract }; public static ConferenceDTO.SpeakerResponse MapSpeakerResponse(this Speaker speaker) => new ConferenceDTO.SpeakerResponse { - ID = speaker.ID, + Id = speaker.Id, Name = speaker.Name, Bio = speaker.Bio, WebSite = speaker.WebSite, @@ -50,7 +42,7 @@ public static ConferenceDTO.SpeakerResponse MapSpeakerResponse(this Speaker spea .Select(ss => new ConferenceDTO.Session { - ID = ss.SessionId, + Id = ss.SessionId, Title = ss.Session.Title }) .ToList() @@ -59,28 +51,20 @@ public static ConferenceDTO.SpeakerResponse MapSpeakerResponse(this Speaker spea public static ConferenceDTO.AttendeeResponse MapAttendeeResponse(this Attendee attendee) => new ConferenceDTO.AttendeeResponse { - ID = attendee.ID, + Id = attendee.Id, FirstName = attendee.FirstName, LastName = attendee.LastName, UserName = attendee.UserName, Sessions = attendee.SessionsAttendees? - .Select(s => + .Select(sa => new ConferenceDTO.Session { - ID = s.SessionID, - Title = s.Session.Title, - StartTime = s.Session.StartTime, - EndTime = s.Session.EndTime + Id = sa.SessionId, + Title = sa.Session.Title, + StartTime = sa.Session.StartTime, + EndTime = sa.Session.EndTime }) - .ToList(), - Conferences = attendee.ConferenceAttendees? - .Select(ca => - new ConferenceDTO.Conference - { - ID = ca.ConferenceID, - Name = ca.Conference.Name - }) - .ToList(), + .ToList() }; } } \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190128064407_Refactor.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190128064407_Refactor.cs deleted file mode 100644 index 5effcda7..00000000 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190128064407_Refactor.cs +++ /dev/null @@ -1,281 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace BackEnd.Migrations -{ - public partial class Refactor : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "ConferenceID", - table: "Speakers", - nullable: true); - - migrationBuilder.CreateTable( - name: "Attendees", - columns: table => new - { - ID = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - FirstName = table.Column(maxLength: 200, nullable: false), - LastName = table.Column(maxLength: 200, nullable: false), - UserName = table.Column(maxLength: 200, nullable: false), - EmailAddress = table.Column(maxLength: 256, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Attendees", x => x.ID); - }); - - migrationBuilder.CreateTable( - name: "Conferences", - columns: table => new - { - ID = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - Name = table.Column(maxLength: 200, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Conferences", x => x.ID); - }); - - migrationBuilder.CreateTable( - name: "Tags", - columns: table => new - { - ID = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - Name = table.Column(maxLength: 32, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Tags", x => x.ID); - }); - - migrationBuilder.CreateTable( - name: "ConferenceAttendee", - columns: table => new - { - ConferenceID = table.Column(nullable: false), - AttendeeID = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ConferenceAttendee", x => new { x.ConferenceID, x.AttendeeID }); - table.ForeignKey( - name: "FK_ConferenceAttendee_Attendees_AttendeeID", - column: x => x.AttendeeID, - principalTable: "Attendees", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_ConferenceAttendee_Conferences_ConferenceID", - column: x => x.ConferenceID, - principalTable: "Conferences", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Tracks", - columns: table => new - { - TrackID = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - ConferenceID = table.Column(nullable: false), - Name = table.Column(maxLength: 200, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Tracks", x => x.TrackID); - table.ForeignKey( - name: "FK_Tracks_Conferences_ConferenceID", - column: x => x.ConferenceID, - principalTable: "Conferences", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Sessions", - columns: table => new - { - ID = table.Column(nullable: false) - .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), - ConferenceID = table.Column(nullable: false), - Title = table.Column(maxLength: 200, nullable: false), - Abstract = table.Column(maxLength: 4000, nullable: true), - StartTime = table.Column(nullable: true), - EndTime = table.Column(nullable: true), - TrackId = table.Column(nullable: true), - AttendeeID = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Sessions", x => x.ID); - table.ForeignKey( - name: "FK_Sessions_Attendees_AttendeeID", - column: x => x.AttendeeID, - principalTable: "Attendees", - principalColumn: "ID", - onDelete: ReferentialAction.Restrict); - table.ForeignKey( - name: "FK_Sessions_Conferences_ConferenceID", - column: x => x.ConferenceID, - principalTable: "Conferences", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_Sessions_Tracks_TrackId", - column: x => x.TrackId, - principalTable: "Tracks", - principalColumn: "TrackID", - onDelete: ReferentialAction.Restrict); - }); - - migrationBuilder.CreateTable( - name: "SessionSpeaker", - columns: table => new - { - SessionId = table.Column(nullable: false), - SpeakerId = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_SessionSpeaker", x => new { x.SessionId, x.SpeakerId }); - table.ForeignKey( - name: "FK_SessionSpeaker_Sessions_SessionId", - column: x => x.SessionId, - principalTable: "Sessions", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_SessionSpeaker_Speakers_SpeakerId", - column: x => x.SpeakerId, - principalTable: "Speakers", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "SessionTag", - columns: table => new - { - SessionID = table.Column(nullable: false), - TagID = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_SessionTag", x => new { x.SessionID, x.TagID }); - table.ForeignKey( - name: "FK_SessionTag_Sessions_SessionID", - column: x => x.SessionID, - principalTable: "Sessions", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_SessionTag_Tags_TagID", - column: x => x.TagID, - principalTable: "Tags", - principalColumn: "ID", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_Speakers_ConferenceID", - table: "Speakers", - column: "ConferenceID"); - - migrationBuilder.CreateIndex( - name: "IX_Attendees_UserName", - table: "Attendees", - column: "UserName", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_ConferenceAttendee_AttendeeID", - table: "ConferenceAttendee", - column: "AttendeeID"); - - migrationBuilder.CreateIndex( - name: "IX_Sessions_AttendeeID", - table: "Sessions", - column: "AttendeeID"); - - migrationBuilder.CreateIndex( - name: "IX_Sessions_ConferenceID", - table: "Sessions", - column: "ConferenceID"); - - migrationBuilder.CreateIndex( - name: "IX_Sessions_TrackId", - table: "Sessions", - column: "TrackId"); - - migrationBuilder.CreateIndex( - name: "IX_SessionSpeaker_SpeakerId", - table: "SessionSpeaker", - column: "SpeakerId"); - - migrationBuilder.CreateIndex( - name: "IX_SessionTag_TagID", - table: "SessionTag", - column: "TagID"); - - migrationBuilder.CreateIndex( - name: "IX_Tracks_ConferenceID", - table: "Tracks", - column: "ConferenceID"); - - migrationBuilder.AddForeignKey( - name: "FK_Speakers_Conferences_ConferenceID", - table: "Speakers", - column: "ConferenceID", - principalTable: "Conferences", - principalColumn: "ID", - onDelete: ReferentialAction.Restrict); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_Speakers_Conferences_ConferenceID", - table: "Speakers"); - - migrationBuilder.DropTable( - name: "ConferenceAttendee"); - - migrationBuilder.DropTable( - name: "SessionSpeaker"); - - migrationBuilder.DropTable( - name: "SessionTag"); - - migrationBuilder.DropTable( - name: "Sessions"); - - migrationBuilder.DropTable( - name: "Tags"); - - migrationBuilder.DropTable( - name: "Attendees"); - - migrationBuilder.DropTable( - name: "Tracks"); - - migrationBuilder.DropTable( - name: "Conferences"); - - migrationBuilder.DropIndex( - name: "IX_Speakers_ConferenceID", - table: "Speakers"); - - migrationBuilder.DropColumn( - name: "ConferenceID", - table: "Speakers"); - } - } -} diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190128054119_Initial.Designer.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190614215301_Initial.Designer.cs similarity index 87% rename from save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190128054119_Initial.Designer.cs rename to save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190614215301_Initial.Designer.cs index 497774c4..e0ccbb77 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190128054119_Initial.Designer.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190614215301_Initial.Designer.cs @@ -9,20 +9,20 @@ namespace BackEnd.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20190128054119_Initial")] + [Migration("20190614215301_Initial")] partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.1-servicing-10028") + .HasAnnotation("ProductVersion", "3.0.0-preview6.19304.10") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("BackEnd.Models.Speaker", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); @@ -36,7 +36,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("WebSite") .HasMaxLength(1000); - b.HasKey("ID"); + b.HasKey("Id"); b.ToTable("Speakers"); }); diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190128054119_Initial.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190614215301_Initial.cs similarity index 89% rename from save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190128054119_Initial.cs rename to save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190614215301_Initial.cs index 9eb54949..b56fda42 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190128054119_Initial.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190614215301_Initial.cs @@ -11,7 +11,7 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "Speakers", columns: table => new { - ID = table.Column(nullable: false) + Id = table.Column(nullable: false) .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), Name = table.Column(maxLength: 200, nullable: false), Bio = table.Column(maxLength: 4000, nullable: true), @@ -19,7 +19,7 @@ protected override void Up(MigrationBuilder migrationBuilder) }, constraints: table => { - table.PrimaryKey("PK_Speakers", x => x.ID); + table.PrimaryKey("PK_Speakers", x => x.Id); }); } diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190128064407_Refactor.Designer.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190614225827_Refactor.Designer.cs similarity index 51% rename from save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190128064407_Refactor.Designer.cs rename to save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190614225827_Refactor.Designer.cs index 17d90fbe..a9bfe2fc 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190128064407_Refactor.Designer.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190614225827_Refactor.Designer.cs @@ -10,20 +10,20 @@ namespace BackEnd.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20190128064407_Refactor")] + [Migration("20190614225827_Refactor")] partial class Refactor { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.1-servicing-10028") + .HasAnnotation("ProductVersion", "3.0.0-preview6.19304.10") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("BackEnd.Data.Attendee", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); @@ -42,7 +42,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .IsRequired() .HasMaxLength(200); - b.HasKey("ID"); + b.HasKey("Id"); b.HasIndex("UserName") .IsUnique(); @@ -50,47 +50,15 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("Attendees"); }); - modelBuilder.Entity("BackEnd.Data.Conference", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("ID"); - - b.ToTable("Conferences"); - }); - - modelBuilder.Entity("BackEnd.Data.ConferenceAttendee", b => - { - b.Property("ConferenceID"); - - b.Property("AttendeeID"); - - b.HasKey("ConferenceID", "AttendeeID"); - - b.HasIndex("AttendeeID"); - - b.ToTable("ConferenceAttendee"); - }); - modelBuilder.Entity("BackEnd.Data.Session", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("Abstract") .HasMaxLength(4000); - b.Property("AttendeeID"); - - b.Property("ConferenceID"); - b.Property("EndTime"); b.Property("StartTime"); @@ -101,54 +69,48 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("TrackId"); - b.HasKey("ID"); - - b.HasIndex("AttendeeID"); - - b.HasIndex("ConferenceID"); + b.HasKey("Id"); b.HasIndex("TrackId"); b.ToTable("Sessions"); }); - modelBuilder.Entity("BackEnd.Data.SessionSpeaker", b => + modelBuilder.Entity("BackEnd.Data.SessionAttendee", b => { b.Property("SessionId"); - b.Property("SpeakerId"); + b.Property("AttendeeId"); - b.HasKey("SessionId", "SpeakerId"); + b.HasKey("SessionId", "AttendeeId"); - b.HasIndex("SpeakerId"); + b.HasIndex("AttendeeId"); - b.ToTable("SessionSpeaker"); + b.ToTable("SessionAttendee"); }); - modelBuilder.Entity("BackEnd.Data.SessionTag", b => + modelBuilder.Entity("BackEnd.Data.SessionSpeaker", b => { - b.Property("SessionID"); + b.Property("SessionId"); - b.Property("TagID"); + b.Property("SpeakerId"); - b.HasKey("SessionID", "TagID"); + b.HasKey("SessionId", "SpeakerId"); - b.HasIndex("TagID"); + b.HasIndex("SpeakerId"); - b.ToTable("SessionTag"); + b.ToTable("SessionSpeaker"); }); modelBuilder.Entity("BackEnd.Data.Speaker", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("Bio") .HasMaxLength(4000); - b.Property("ConferenceID"); - b.Property("Name") .IsRequired() .HasMaxLength(200); @@ -156,115 +118,61 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Property("WebSite") .HasMaxLength(1000); - b.HasKey("ID"); - - b.HasIndex("ConferenceID"); + b.HasKey("Id"); b.ToTable("Speakers"); }); - modelBuilder.Entity("BackEnd.Data.Tag", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("Name") - .IsRequired() - .HasMaxLength(32); - - b.HasKey("ID"); - - b.ToTable("Tags"); - }); - modelBuilder.Entity("BackEnd.Data.Track", b => { - b.Property("TrackID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - b.Property("ConferenceID"); - b.Property("Name") .IsRequired() .HasMaxLength(200); - b.HasKey("TrackID"); - - b.HasIndex("ConferenceID"); + b.HasKey("Id"); b.ToTable("Tracks"); }); - modelBuilder.Entity("BackEnd.Data.ConferenceAttendee", b => - { - b.HasOne("BackEnd.Data.Attendee", "Attendee") - .WithMany("ConferenceAttendees") - .HasForeignKey("AttendeeID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("BackEnd.Data.Conference", "Conference") - .WithMany("ConferenceAttendees") - .HasForeignKey("ConferenceID") - .OnDelete(DeleteBehavior.Cascade); - }); - modelBuilder.Entity("BackEnd.Data.Session", b => { - b.HasOne("BackEnd.Data.Attendee") - .WithMany("Sessions") - .HasForeignKey("AttendeeID"); - - b.HasOne("BackEnd.Data.Conference", "Conference") - .WithMany("Sessions") - .HasForeignKey("ConferenceID") - .OnDelete(DeleteBehavior.Cascade); - b.HasOne("BackEnd.Data.Track", "Track") .WithMany("Sessions") .HasForeignKey("TrackId"); }); + modelBuilder.Entity("BackEnd.Data.SessionAttendee", b => + { + b.HasOne("BackEnd.Data.Attendee", "Attendee") + .WithMany("SessionsAttendees") + .HasForeignKey("AttendeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("BackEnd.Data.Session", "Session") + .WithMany() + .HasForeignKey("SessionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("BackEnd.Data.SessionSpeaker", b => { b.HasOne("BackEnd.Data.Session", "Session") .WithMany("SessionSpeakers") .HasForeignKey("SessionId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); b.HasOne("BackEnd.Data.Speaker", "Speaker") .WithMany("SessionSpeakers") .HasForeignKey("SpeakerId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("BackEnd.Data.SessionTag", b => - { - b.HasOne("BackEnd.Data.Session", "Session") - .WithMany("SessionTags") - .HasForeignKey("SessionID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("BackEnd.Data.Tag", "Tag") - .WithMany("SessionTags") - .HasForeignKey("TagID") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("BackEnd.Data.Speaker", b => - { - b.HasOne("BackEnd.Data.Conference") - .WithMany("Speakers") - .HasForeignKey("ConferenceID"); - }); - - modelBuilder.Entity("BackEnd.Data.Track", b => - { - b.HasOne("BackEnd.Data.Conference", "Conference") - .WithMany("Tracks") - .HasForeignKey("ConferenceID") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); #pragma warning restore 612, 618 } diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190614225827_Refactor.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190614225827_Refactor.cs new file mode 100644 index 00000000..168a0ca7 --- /dev/null +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/20190614225827_Refactor.cs @@ -0,0 +1,151 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace BackEnd.Migrations +{ + public partial class Refactor : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Attendees", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), + FirstName = table.Column(maxLength: 200, nullable: false), + LastName = table.Column(maxLength: 200, nullable: false), + UserName = table.Column(maxLength: 200, nullable: false), + EmailAddress = table.Column(maxLength: 256, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Attendees", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Tracks", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), + Name = table.Column(maxLength: 200, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Tracks", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Sessions", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), + Title = table.Column(maxLength: 200, nullable: false), + Abstract = table.Column(maxLength: 4000, nullable: true), + StartTime = table.Column(nullable: true), + EndTime = table.Column(nullable: true), + TrackId = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Sessions", x => x.Id); + table.ForeignKey( + name: "FK_Sessions_Tracks_TrackId", + column: x => x.TrackId, + principalTable: "Tracks", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateTable( + name: "SessionAttendee", + columns: table => new + { + SessionId = table.Column(nullable: false), + AttendeeId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SessionAttendee", x => new { x.SessionId, x.AttendeeId }); + table.ForeignKey( + name: "FK_SessionAttendee_Attendees_AttendeeId", + column: x => x.AttendeeId, + principalTable: "Attendees", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_SessionAttendee_Sessions_SessionId", + column: x => x.SessionId, + principalTable: "Sessions", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "SessionSpeaker", + columns: table => new + { + SessionId = table.Column(nullable: false), + SpeakerId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SessionSpeaker", x => new { x.SessionId, x.SpeakerId }); + table.ForeignKey( + name: "FK_SessionSpeaker_Sessions_SessionId", + column: x => x.SessionId, + principalTable: "Sessions", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_SessionSpeaker_Speakers_SpeakerId", + column: x => x.SpeakerId, + principalTable: "Speakers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Attendees_UserName", + table: "Attendees", + column: "UserName", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_SessionAttendee_AttendeeId", + table: "SessionAttendee", + column: "AttendeeId"); + + migrationBuilder.CreateIndex( + name: "IX_Sessions_TrackId", + table: "Sessions", + column: "TrackId"); + + migrationBuilder.CreateIndex( + name: "IX_SessionSpeaker_SpeakerId", + table: "SessionSpeaker", + column: "SpeakerId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "SessionAttendee"); + + migrationBuilder.DropTable( + name: "SessionSpeaker"); + + migrationBuilder.DropTable( + name: "Attendees"); + + migrationBuilder.DropTable( + name: "Sessions"); + + migrationBuilder.DropTable( + name: "Tracks"); + } + } +} diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/ApplicationDbContextModelSnapshot.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/ApplicationDbContextModelSnapshot.cs index 6be8902f..5bec0e4c 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Migrations/ApplicationDbContextModelSnapshot.cs @@ -15,13 +15,13 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.1-servicing-10028") + .HasAnnotation("ProductVersion", "3.0.0-preview6.19304.10") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("BackEnd.Data.Attendee", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); @@ -40,7 +40,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasMaxLength(200); - b.HasKey("ID"); + b.HasKey("Id"); b.HasIndex("UserName") .IsUnique(); @@ -48,47 +48,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("Attendees"); }); - modelBuilder.Entity("BackEnd.Data.Conference", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("Name") - .IsRequired() - .HasMaxLength(200); - - b.HasKey("ID"); - - b.ToTable("Conferences"); - }); - - modelBuilder.Entity("BackEnd.Data.ConferenceAttendee", b => - { - b.Property("ConferenceID"); - - b.Property("AttendeeID"); - - b.HasKey("ConferenceID", "AttendeeID"); - - b.HasIndex("AttendeeID"); - - b.ToTable("ConferenceAttendee"); - }); - modelBuilder.Entity("BackEnd.Data.Session", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("Abstract") .HasMaxLength(4000); - b.Property("AttendeeID"); - - b.Property("ConferenceID"); - b.Property("EndTime"); b.Property("StartTime"); @@ -99,54 +67,48 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("TrackId"); - b.HasKey("ID"); - - b.HasIndex("AttendeeID"); - - b.HasIndex("ConferenceID"); + b.HasKey("Id"); b.HasIndex("TrackId"); b.ToTable("Sessions"); }); - modelBuilder.Entity("BackEnd.Data.SessionSpeaker", b => + modelBuilder.Entity("BackEnd.Data.SessionAttendee", b => { b.Property("SessionId"); - b.Property("SpeakerId"); + b.Property("AttendeeId"); - b.HasKey("SessionId", "SpeakerId"); + b.HasKey("SessionId", "AttendeeId"); - b.HasIndex("SpeakerId"); + b.HasIndex("AttendeeId"); - b.ToTable("SessionSpeaker"); + b.ToTable("SessionAttendee"); }); - modelBuilder.Entity("BackEnd.Data.SessionTag", b => + modelBuilder.Entity("BackEnd.Data.SessionSpeaker", b => { - b.Property("SessionID"); + b.Property("SessionId"); - b.Property("TagID"); + b.Property("SpeakerId"); - b.HasKey("SessionID", "TagID"); + b.HasKey("SessionId", "SpeakerId"); - b.HasIndex("TagID"); + b.HasIndex("SpeakerId"); - b.ToTable("SessionTag"); + b.ToTable("SessionSpeaker"); }); modelBuilder.Entity("BackEnd.Data.Speaker", b => { - b.Property("ID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); b.Property("Bio") .HasMaxLength(4000); - b.Property("ConferenceID"); - b.Property("Name") .IsRequired() .HasMaxLength(200); @@ -154,115 +116,61 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("WebSite") .HasMaxLength(1000); - b.HasKey("ID"); - - b.HasIndex("ConferenceID"); + b.HasKey("Id"); b.ToTable("Speakers"); }); - modelBuilder.Entity("BackEnd.Data.Tag", b => - { - b.Property("ID") - .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - - b.Property("Name") - .IsRequired() - .HasMaxLength(32); - - b.HasKey("ID"); - - b.ToTable("Tags"); - }); - modelBuilder.Entity("BackEnd.Data.Track", b => { - b.Property("TrackID") + b.Property("Id") .ValueGeneratedOnAdd() .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); - b.Property("ConferenceID"); - b.Property("Name") .IsRequired() .HasMaxLength(200); - b.HasKey("TrackID"); - - b.HasIndex("ConferenceID"); + b.HasKey("Id"); b.ToTable("Tracks"); }); - modelBuilder.Entity("BackEnd.Data.ConferenceAttendee", b => - { - b.HasOne("BackEnd.Data.Attendee", "Attendee") - .WithMany("ConferenceAttendees") - .HasForeignKey("AttendeeID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("BackEnd.Data.Conference", "Conference") - .WithMany("ConferenceAttendees") - .HasForeignKey("ConferenceID") - .OnDelete(DeleteBehavior.Cascade); - }); - modelBuilder.Entity("BackEnd.Data.Session", b => { - b.HasOne("BackEnd.Data.Attendee") - .WithMany("Sessions") - .HasForeignKey("AttendeeID"); - - b.HasOne("BackEnd.Data.Conference", "Conference") - .WithMany("Sessions") - .HasForeignKey("ConferenceID") - .OnDelete(DeleteBehavior.Cascade); - b.HasOne("BackEnd.Data.Track", "Track") .WithMany("Sessions") .HasForeignKey("TrackId"); }); + modelBuilder.Entity("BackEnd.Data.SessionAttendee", b => + { + b.HasOne("BackEnd.Data.Attendee", "Attendee") + .WithMany("SessionsAttendees") + .HasForeignKey("AttendeeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("BackEnd.Data.Session", "Session") + .WithMany() + .HasForeignKey("SessionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("BackEnd.Data.SessionSpeaker", b => { b.HasOne("BackEnd.Data.Session", "Session") .WithMany("SessionSpeakers") .HasForeignKey("SessionId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); b.HasOne("BackEnd.Data.Speaker", "Speaker") .WithMany("SessionSpeakers") .HasForeignKey("SpeakerId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("BackEnd.Data.SessionTag", b => - { - b.HasOne("BackEnd.Data.Session", "Session") - .WithMany("SessionTags") - .HasForeignKey("SessionID") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("BackEnd.Data.Tag", "Tag") - .WithMany("SessionTags") - .HasForeignKey("TagID") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("BackEnd.Data.Speaker", b => - { - b.HasOne("BackEnd.Data.Conference") - .WithMany("Speakers") - .HasForeignKey("ConferenceID"); - }); - - modelBuilder.Entity("BackEnd.Data.Track", b => - { - b.HasOne("BackEnd.Data.Conference", "Conference") - .WithMany("Tracks") - .HasForeignKey("ConferenceID") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); }); #pragma warning restore 612, 618 } diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Program.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Program.cs index c38605c3..e427203e 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Program.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Program.cs @@ -1,11 +1,10 @@ -using System; +using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace BackEnd @@ -14,11 +13,14 @@ public class Program { public static void Main(string[] args) { - CreateWebHostBuilder(args).Build().Run(); + CreateHostBuilder(args).Build().Run(); } - public static IWebHostBuilder CreateWebHostBuilder(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup(); + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); } } diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Properties/launchSettings.json b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Properties/launchSettings.json deleted file mode 100644 index a42a9703..00000000 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Properties/launchSettings.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "$schema": "http://json.schemastore.org/launchsettings.json", - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:54962", - "sslPort": 44357 - } - }, - "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "launchUrl": "api/values", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "BackEnd": { - "commandName": "Project", - "launchBrowser": true, - "launchUrl": "api/values", - "applicationUrl": "https://localhost:5001;http://localhost:5000", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Startup.cs b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Startup.cs index 89eff7ed..f58f6356 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Startup.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/Startup.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; @@ -11,9 +11,9 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Swashbuckle.AspNetCore.Swagger; +using Microsoft.OpenApi.Models; namespace BackEnd { @@ -41,34 +41,39 @@ public void ConfigureServices(IServiceCollection services) } }); - services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); + services.AddControllers(); services.AddSwaggerGen(options => - options.SwaggerDoc("v1", new Info { Title = "Conference Planner API", Version = "v1" }) - ); + { + options.SwaggerDoc("v1", new OpenApiInfo { Title = "Conference Planner API", Version = "v1" }); + options.DescribeAllEnumsAsStrings(); + }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseHttpsRedirection(); + + app.UseRouting(); + + app.UseAuthorization(); + app.UseSwagger(); app.UseSwaggerUI(options => options.SwaggerEndpoint("/swagger/v1/swagger.json", "Conference Planner API v1") ); - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else + app.UseEndpoints(endpoints => { - // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. - app.UseHsts(); - } - - app.UseHttpsRedirection(); - app.UseMvc(); + endpoints.MapControllers(); + }); app.Run(context => { diff --git a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/appsettings.json b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/appsettings.json index b6ede740..564944d6 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/BackEnd/appsettings.json +++ b/save-points/3-Front-End-started/ConferencePlanner/BackEnd/appsettings.json @@ -2,10 +2,12 @@ "ConnectionStrings": { "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-BackEnd-SavePoint3;Trusted_Connection=True;MultipleActiveResultSets=true" }, - "Logging": { - "LogLevel": { - "Default": "Warning" - } - }, - "AllowedHosts": "*" + "Logging": { + "LogLevel": { + "Default": "Warning", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" } \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Attendee.cs b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Attendee.cs index ec5a3a50..6fb8b5e5 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Attendee.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Attendee.cs @@ -6,7 +6,7 @@ namespace ConferenceDTO { public class Attendee { - public int ID { get; set; } + public int Id { get; set; } [Required] [StringLength(200)] diff --git a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/AttendeeResponse.cs b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/AttendeeResponse.cs index 54a61502..8f75153b 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/AttendeeResponse.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/AttendeeResponse.cs @@ -6,8 +6,6 @@ namespace ConferenceDTO { public class AttendeeResponse : Attendee { - public ICollection Conferences { get; set; } = new List(); - public ICollection Sessions { get; set; } = new List(); } } diff --git a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Conference.cs b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Conference.cs deleted file mode 100644 index bee6bcb3..00000000 --- a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Conference.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Text; - -namespace ConferenceDTO -{ - public class Conference - { - public int ID { get; set; } - - [Required] - [StringLength(200)] - public string Name { get; set; } - } -} \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/ConferenceDTO.csproj b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/ConferenceDTO.csproj index 04c4803a..2160f683 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/ConferenceDTO.csproj +++ b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/ConferenceDTO.csproj @@ -1,12 +1,9 @@ - + netstandard2.0 - - - diff --git a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/ConferenceResponse.cs b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/ConferenceResponse.cs deleted file mode 100644 index 7043b377..00000000 --- a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/ConferenceResponse.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace ConferenceDTO -{ - public class ConferenceResponse : Conference - { - public ICollection Sessions { get; set; } = new List(); - - public ICollection Tracks { get; set; } = new List(); - - public ICollection Speakers { get; set; } = new List(); - } -} diff --git a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/SearchResult.cs b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/SearchResult.cs index fdb50b84..1a132bbb 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/SearchResult.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/SearchResult.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Text; -using Newtonsoft.Json.Linq; namespace ConferenceDTO { @@ -9,15 +8,14 @@ public class SearchResult { public SearchResultType Type { get; set; } - public JObject Value { get; set; } + public SessionResponse Session { get; set; } + + public SpeakerResponse Speaker { get; set; } } public enum SearchResultType { - Attendee, - Conference, Session, - Track, Speaker } } \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Session.cs b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Session.cs index d20b39b3..5ad7540e 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Session.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Session.cs @@ -7,10 +7,7 @@ namespace ConferenceDTO { public class Session { - public int ID { get; set; } - - [Required] - public int ConferenceID { get; set; } + public int Id { get; set; } [Required] [StringLength(200)] diff --git a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/SessionResponse.cs b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/SessionResponse.cs index ee4086c4..0834be99 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/SessionResponse.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/SessionResponse.cs @@ -8,8 +8,6 @@ public class SessionResponse : Session { public Track Track { get; set; } - public ICollection Speakers { get; set; } = new List(); - - public ICollection Tags { get; set; } = new List(); + public List Speakers { get; set; } = new List(); } } diff --git a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Speaker.cs b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Speaker.cs index 99104980..f807e327 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Speaker.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Speaker.cs @@ -8,7 +8,7 @@ namespace ConferenceDTO { public class Speaker { - public int ID { get; set; } + public int Id { get; set; } [Required] [StringLength(200)] @@ -20,4 +20,4 @@ public class Speaker [StringLength(1000)] public virtual string WebSite { get; set; } } -} \ No newline at end of file +} diff --git a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/SpeakerResponse.cs b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/SpeakerResponse.cs index 7196069d..ef7dcd56 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/SpeakerResponse.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/SpeakerResponse.cs @@ -6,7 +6,7 @@ namespace ConferenceDTO { public class SpeakerResponse : Speaker { - // TODO: Set order of JSON proeprties so this shows up last not first + // TODO: Set order of JSON properties so this shows up last not first public ICollection Sessions { get; set; } = new List(); } } \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Tag.cs b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Tag.cs deleted file mode 100644 index d9966b74..00000000 --- a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Tag.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; - -namespace ConferenceDTO -{ - public class Tag - { - public int ID { get; set; } - - [Required] - [StringLength(32)] - public string Name { get; set; } - } -} \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/TagResponse.cs b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/TagResponse.cs deleted file mode 100644 index 85f651a8..00000000 --- a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/TagResponse.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace ConferenceDTO -{ - public class TagResponse : Tag - { - public ICollection Sessions { get; set; } = new List(); - } -} diff --git a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Track.cs b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Track.cs index 773e6281..c18691f1 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Track.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/Track.cs @@ -6,10 +6,7 @@ namespace ConferenceDTO { public class Track { - public int TrackID { get; set; } - - [Required] - public int ConferenceID { get; set; } + public int Id { get; set; } [Required] [StringLength(200)] diff --git a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/TrackResponse.cs b/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/TrackResponse.cs deleted file mode 100644 index 5d26c837..00000000 --- a/save-points/3-Front-End-started/ConferencePlanner/ConferenceDTO/TrackResponse.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace ConferenceDTO -{ - public class TrackResponse : Track - { - public Conference Conference { get; set; } - - public ICollection Sessions { get; set; } = new List(); - } -} diff --git a/save-points/3-Front-End-started/ConferencePlanner/ConferencePlanner.sln b/save-points/3-Front-End-started/ConferencePlanner/ConferencePlanner.sln index e6e0c14e..43731b5d 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/ConferencePlanner.sln +++ b/save-points/3-Front-End-started/ConferencePlanner/ConferencePlanner.sln @@ -1,13 +1,13 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.329 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29007.179 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BackEnd", "BackEnd\BackEnd.csproj", "{E7864CB1-70EF-4BDE-95D7-6078DE7F1F13}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BackEnd", "BackEnd\BackEnd.csproj", "{54B73C40-8060-4718-A682-5A1C32C1E83A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConferenceDTO", "ConferenceDTO\ConferenceDTO.csproj", "{49122DB1-E07B-47E4-B855-9FF6B8BD4DCC}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConferenceDTO", "ConferenceDTO\ConferenceDTO.csproj", "{B88921B6-460D-4B9B-A3EB-431AA1A2347B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FrontEnd", "FrontEnd\FrontEnd.csproj", "{4C883394-784B-4BA2-9EF1-3AF40500DDFC}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FrontEnd", "FrontEnd\FrontEnd.csproj", "{0B73E421-4D0D-4743-8E00-DF2DBBEFCEFB}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -15,23 +15,23 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E7864CB1-70EF-4BDE-95D7-6078DE7F1F13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E7864CB1-70EF-4BDE-95D7-6078DE7F1F13}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E7864CB1-70EF-4BDE-95D7-6078DE7F1F13}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E7864CB1-70EF-4BDE-95D7-6078DE7F1F13}.Release|Any CPU.Build.0 = Release|Any CPU - {49122DB1-E07B-47E4-B855-9FF6B8BD4DCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {49122DB1-E07B-47E4-B855-9FF6B8BD4DCC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {49122DB1-E07B-47E4-B855-9FF6B8BD4DCC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {49122DB1-E07B-47E4-B855-9FF6B8BD4DCC}.Release|Any CPU.Build.0 = Release|Any CPU - {4C883394-784B-4BA2-9EF1-3AF40500DDFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4C883394-784B-4BA2-9EF1-3AF40500DDFC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4C883394-784B-4BA2-9EF1-3AF40500DDFC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4C883394-784B-4BA2-9EF1-3AF40500DDFC}.Release|Any CPU.Build.0 = Release|Any CPU + {54B73C40-8060-4718-A682-5A1C32C1E83A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {54B73C40-8060-4718-A682-5A1C32C1E83A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {54B73C40-8060-4718-A682-5A1C32C1E83A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {54B73C40-8060-4718-A682-5A1C32C1E83A}.Release|Any CPU.Build.0 = Release|Any CPU + {B88921B6-460D-4B9B-A3EB-431AA1A2347B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B88921B6-460D-4B9B-A3EB-431AA1A2347B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B88921B6-460D-4B9B-A3EB-431AA1A2347B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B88921B6-460D-4B9B-A3EB-431AA1A2347B}.Release|Any CPU.Build.0 = Release|Any CPU + {0B73E421-4D0D-4743-8E00-DF2DBBEFCEFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0B73E421-4D0D-4743-8E00-DF2DBBEFCEFB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0B73E421-4D0D-4743-8E00-DF2DBBEFCEFB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0B73E421-4D0D-4743-8E00-DF2DBBEFCEFB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {716BD0AE-1BA1-4372-B4C1-BFE9CFA5FA18} + SolutionGuid = {7C5D815A-7FB9-4BB2-962E-F66EC67114A4} EndGlobalSection EndGlobal diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/FrontEnd.csproj b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/FrontEnd.csproj index c0322071..bd00f172 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/FrontEnd.csproj +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/FrontEnd.csproj @@ -1,20 +1,18 @@ - + - netcoreapp2.2 - InProcess + netcoreapp3.0 - - - - - - - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Error.cshtml.cs b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Error.cshtml.cs index ed43ff5e..6ba18379 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Error.cshtml.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Error.cshtml.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.Extensions.Logging; namespace FrontEnd.Pages { @@ -15,6 +16,12 @@ public class ErrorModel : PageModel public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); + private readonly ILogger logger; + + public ErrorModel(ILogger _logger) + { + logger = _logger; + } public void OnGet() { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Index.cshtml b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Index.cshtml index d04c2178..e1653290 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Index.cshtml +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Index.cshtml @@ -26,14 +26,14 @@
    @session.Track?.Name
    } -
    \ No newline at end of file + diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Index.cshtml.cs b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Index.cshtml.cs index f851096d..ed289931 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Index.cshtml.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Index.cshtml.cs @@ -6,24 +6,27 @@ using FrontEnd.Services; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.Extensions.Logging; namespace FrontEnd.Pages { public class IndexModel : PageModel { + private readonly ILogger logger; protected readonly IApiClient _apiClient; + public IndexModel(ILogger _logger, IApiClient apiClient) + { + logger = _logger; + _apiClient = apiClient; + } + public IEnumerable> Sessions { get; set; } public IEnumerable<(int Offset, DayOfWeek? DayofWeek)> DayOffsets { get; set; } public int CurrentDayOffset { get; set; } - public IndexModel(IApiClient apiClient) - { - _apiClient = apiClient; - } - public async Task OnGet(int day = 0) { CurrentDayOffset = day; diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Privacy.cshtml.cs b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Privacy.cshtml.cs index d29a3d1b..8be80822 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Privacy.cshtml.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Privacy.cshtml.cs @@ -4,13 +4,20 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Microsoft.Extensions.Logging; namespace FrontEnd.Pages { public class PrivacyModel : PageModel { + private readonly ILogger logger; + + public PrivacyModel(ILogger _logger) + { + logger = _logger; + } public void OnGet() { } } -} \ No newline at end of file +} diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Search.cshtml b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Search.cshtml index 8185c82c..9a4c55ba 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Search.cshtml +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Search.cshtml @@ -24,39 +24,39 @@ @foreach (var result in Model.SearchResults) {
    - @switch (result) + @switch (result.Type) { - case SpeakerResponse speaker: + case SearchResultType.Speaker:
    -

    Speaker: @speaker.Name

    +

    Speaker: @result.Speaker.Name

    - @foreach (var session in speaker.Sessions) + @foreach (var session in result.Speaker.Sessions) { - @session.Title + @session.Title }

    - @speaker.Bio + @result.Speaker.Bio

    break; - case SessionResponse session: + case SearchResultType.Session:
    -

    Session: @session.Title

    - @foreach (var speaker in session.Speakers) +

    Session: @result.Session.Title

    + @foreach (var speaker in result.Session.Speakers) { - @speaker.Name + @speaker.Name }

    - @session.Abstract + @result.Session.Abstract

    diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Search.cshtml.cs b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Search.cshtml.cs index ac0b40bb..cab28e7b 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Search.cshtml.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Search.cshtml.cs @@ -20,24 +20,12 @@ public SearchModel(IApiClient apiClient) public string Term { get; set; } - public List SearchResults { get; set; } + public List SearchResults { get; set; } public async Task OnGetAsync(string term) { Term = term; - var results = await _apiClient.SearchAsync(term); - SearchResults = results.Select(sr => - { - switch (sr.Type) - { - case SearchResultType.Session: - return (object)sr.Value.ToObject(); - case SearchResultType.Speaker: - return (object)sr.Value.ToObject(); - default: - return (object)sr; - } - }).ToList(); + SearchResults = await _apiClient.SearchAsync(term); } } -} \ No newline at end of file +} diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Session.cshtml b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Session.cshtml index 9f58f805..0986bb9d 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Session.cshtml +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Session.cshtml @@ -1,20 +1,21 @@ @page "{id}" @model SessionModel - +

    @Model.Session.Title

    @Model.Session.Track?.Name @foreach (var speaker in Model.Session.Speakers) { - @speaker.Name + @speaker.Name } -

    @Html.Raw(Model.Session.Abstract)

    \ No newline at end of file +@foreach (var para in Model.Session.Abstract.Split("\r\n", StringSplitOptions.RemoveEmptyEntries)) +{ +

    @para

    +} \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Session.cshtml.cs b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Session.cshtml.cs index 4d2d5036..5f5970d5 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Session.cshtml.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Session.cshtml.cs @@ -1,7 +1,6 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; -using System.Text.Encodings.Web; using System.Threading.Tasks; using ConferenceDTO; using FrontEnd.Services; @@ -14,12 +13,9 @@ public class SessionModel : PageModel { private readonly IApiClient _apiClient; - private readonly HtmlEncoder _htmlEncoder; - - public SessionModel(IApiClient apiClient, HtmlEncoder htmlEncoder) + public SessionModel(IApiClient apiClient) { _apiClient = apiClient; - _htmlEncoder = htmlEncoder; } public SessionResponse Session { get; set; } @@ -41,14 +37,7 @@ public async Task OnGetAsync(int id) DayOffset = Session.StartTime?.Subtract(startDate ?? DateTimeOffset.MinValue).Days; - if (!string.IsNullOrEmpty(Session.Abstract)) - { - var encodedCrLf = _htmlEncoder.Encode("\r\n"); - var encodedAbstract = _htmlEncoder.Encode(Session.Abstract); - Session.Abstract = "

    " + String.Join("

    ", encodedAbstract.Split(encodedCrLf, StringSplitOptions.RemoveEmptyEntries)) + "

    "; - } - return Page(); } } -} \ No newline at end of file +} diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Shared/_CookieConsentPartial.cshtml b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Shared/_CookieConsentPartial.cshtml deleted file mode 100644 index 7df65c45..00000000 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Shared/_CookieConsentPartial.cshtml +++ /dev/null @@ -1,25 +0,0 @@ -@using Microsoft.AspNetCore.Http.Features - -@{ - var consentFeature = Context.Features.Get(); - var showBanner = !consentFeature?.CanTrack ?? false; - var cookieString = consentFeature?.CreateConsentCookie(); -} - -@if (showBanner) -{ - - -} diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Shared/_Layout.cshtml b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Shared/_Layout.cshtml index 84190ec7..06af4af4 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Shared/_Layout.cshtml +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Shared/_Layout.cshtml @@ -1,20 +1,10 @@  - + @ViewData["Title"] - FrontEnd - - - - - - - + @@ -28,6 +18,9 @@ diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Speaker.cshtml.cs b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Speaker.cshtml.cs index fe15223a..1964785f 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Speaker.cshtml.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Pages/Speaker.cshtml.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -32,4 +32,4 @@ public async Task OnGet(int id) return Page(); } } -} \ No newline at end of file +} diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Program.cs b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Program.cs index bed9fe1d..ac4ecc54 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Program.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Program.cs @@ -1,11 +1,10 @@ -using System; +using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace FrontEnd @@ -14,11 +13,14 @@ public class Program { public static void Main(string[] args) { - CreateWebHostBuilder(args).Build().Run(); + CreateHostBuilder(args).Build().Run(); } - public static IWebHostBuilder CreateWebHostBuilder(string[] args) => - WebHost.CreateDefaultBuilder(args) - .UseStartup(); + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); } } diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Properties/launchSettings.json b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Properties/launchSettings.json deleted file mode 100644 index 7b97235d..00000000 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Properties/launchSettings.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:56570", - "sslPort": 44341 - } - }, - "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "FrontEnd": { - "commandName": "Project", - "launchBrowser": true, - "applicationUrl": "https://localhost:5001;http://localhost:5000", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Services/ApiClient.cs b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Services/ApiClient.cs index 11698367..dd955677 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Services/ApiClient.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Services/ApiClient.cs @@ -110,7 +110,7 @@ public async Task> GetSpeakersAsync() public async Task PutSessionAsync(Session session) { - var response = await _httpClient.PutAsJsonAsync($"/api/sessions/{session.ID}", session); + var response = await _httpClient.PutAsJsonAsync($"/api/sessions/{session.Id}", session); response.EnsureSuccessStatusCode(); } diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Startup.cs b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Startup.cs index 33e2de69..3d465cc9 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Startup.cs +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/Startup.cs @@ -5,11 +5,10 @@ using FrontEnd.Services; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.HttpsPolicy; -using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; namespace FrontEnd { @@ -25,24 +24,16 @@ public Startup(IConfiguration configuration) // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { - services.Configure(options => - { - // This lambda determines whether user consent for non-essential cookies is needed for a given request. - options.CheckConsentNeeded = context => true; - options.MinimumSameSitePolicy = SameSiteMode.None; - }); - - - services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); - services.AddHttpClient(client => { client.BaseAddress = new Uri(Configuration["serviceUrl"]); }); + + services.AddRazorPages(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { @@ -57,9 +48,15 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env) app.UseHttpsRedirection(); app.UseStaticFiles(); - app.UseCookiePolicy(); - app.UseMvc(); + app.UseRouting(); + + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapRazorPages(); + }); } } } diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/appsettings.json b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/appsettings.json index 62c89691..cb2b2d4d 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/appsettings.json +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/appsettings.json @@ -1,9 +1,11 @@ { + "ServiceUrl": "https://localhost:44334", "Logging": { "LogLevel": { - "Default": "Warning" + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" } }, - "AllowedHosts": "*", - "ServiceUrl": "https://localhost:44357/" + "AllowedHosts": "*" } diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/css/site.css b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/css/site.css index c486131d..e679a8ea 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/css/site.css +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/css/site.css @@ -7,6 +7,23 @@ a.navbar-brand { word-break: break-all; } +/* Provide sufficient contrast against white background */ +a { + color: #0366d6; +} + +.btn-primary { + color: #fff; + background-color: #1b6ec2; + border-color: #1861ac; +} + +.nav-pills .nav-link.active, .nav-pills .show > .nav-link { + color: #fff; + background-color: #1b6ec2; + border-color: #1861ac; +} + /* Sticky footer styles -------------------------------------------------- */ html { @@ -50,7 +67,5 @@ body { bottom: 0; width: 100%; white-space: nowrap; - /* Set the fixed height of the footer here */ - height: 60px; line-height: 60px; /* Vertically center the text there */ } diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css index a36cd328..68b84f84 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css @@ -1,13 +1,9 @@ /*! - * Bootstrap Grid v4.1.3 (https://getbootstrap.com/) - * Copyright 2011-2018 The Bootstrap Authors - * Copyright 2011-2018 Twitter, Inc. + * Bootstrap Grid v4.3.1 (https://getbootstrap.com/) + * Copyright 2011-2019 The Bootstrap Authors + * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ -@-ms-viewport { - width: device-width; -} - html { box-sizing: border-box; -ms-overflow-style: scrollbar; @@ -87,7 +83,6 @@ html { .col-xl-auto { position: relative; width: 100%; - min-height: 1px; padding-right: 15px; padding-left: 15px; } @@ -104,7 +99,7 @@ html { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; - max-width: none; + max-width: 100%; } .col-1 { @@ -310,7 +305,7 @@ html { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; - max-width: none; + max-width: 100%; } .col-sm-1 { -ms-flex: 0 0 8.333333%; @@ -482,7 +477,7 @@ html { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; - max-width: none; + max-width: 100%; } .col-md-1 { -ms-flex: 0 0 8.333333%; @@ -654,7 +649,7 @@ html { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; - max-width: none; + max-width: 100%; } .col-lg-1 { -ms-flex: 0 0 8.333333%; @@ -826,7 +821,7 @@ html { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; - max-width: none; + max-width: 100%; } .col-xl-1 { -ms-flex: 0 0 8.333333%; @@ -1909,4 +1904,1816 @@ html { align-self: stretch !important; } } + +.m-0 { + margin: 0 !important; +} + +.mt-0, +.my-0 { + margin-top: 0 !important; +} + +.mr-0, +.mx-0 { + margin-right: 0 !important; +} + +.mb-0, +.my-0 { + margin-bottom: 0 !important; +} + +.ml-0, +.mx-0 { + margin-left: 0 !important; +} + +.m-1 { + margin: 0.25rem !important; +} + +.mt-1, +.my-1 { + margin-top: 0.25rem !important; +} + +.mr-1, +.mx-1 { + margin-right: 0.25rem !important; +} + +.mb-1, +.my-1 { + margin-bottom: 0.25rem !important; +} + +.ml-1, +.mx-1 { + margin-left: 0.25rem !important; +} + +.m-2 { + margin: 0.5rem !important; +} + +.mt-2, +.my-2 { + margin-top: 0.5rem !important; +} + +.mr-2, +.mx-2 { + margin-right: 0.5rem !important; +} + +.mb-2, +.my-2 { + margin-bottom: 0.5rem !important; +} + +.ml-2, +.mx-2 { + margin-left: 0.5rem !important; +} + +.m-3 { + margin: 1rem !important; +} + +.mt-3, +.my-3 { + margin-top: 1rem !important; +} + +.mr-3, +.mx-3 { + margin-right: 1rem !important; +} + +.mb-3, +.my-3 { + margin-bottom: 1rem !important; +} + +.ml-3, +.mx-3 { + margin-left: 1rem !important; +} + +.m-4 { + margin: 1.5rem !important; +} + +.mt-4, +.my-4 { + margin-top: 1.5rem !important; +} + +.mr-4, +.mx-4 { + margin-right: 1.5rem !important; +} + +.mb-4, +.my-4 { + margin-bottom: 1.5rem !important; +} + +.ml-4, +.mx-4 { + margin-left: 1.5rem !important; +} + +.m-5 { + margin: 3rem !important; +} + +.mt-5, +.my-5 { + margin-top: 3rem !important; +} + +.mr-5, +.mx-5 { + margin-right: 3rem !important; +} + +.mb-5, +.my-5 { + margin-bottom: 3rem !important; +} + +.ml-5, +.mx-5 { + margin-left: 3rem !important; +} + +.p-0 { + padding: 0 !important; +} + +.pt-0, +.py-0 { + padding-top: 0 !important; +} + +.pr-0, +.px-0 { + padding-right: 0 !important; +} + +.pb-0, +.py-0 { + padding-bottom: 0 !important; +} + +.pl-0, +.px-0 { + padding-left: 0 !important; +} + +.p-1 { + padding: 0.25rem !important; +} + +.pt-1, +.py-1 { + padding-top: 0.25rem !important; +} + +.pr-1, +.px-1 { + padding-right: 0.25rem !important; +} + +.pb-1, +.py-1 { + padding-bottom: 0.25rem !important; +} + +.pl-1, +.px-1 { + padding-left: 0.25rem !important; +} + +.p-2 { + padding: 0.5rem !important; +} + +.pt-2, +.py-2 { + padding-top: 0.5rem !important; +} + +.pr-2, +.px-2 { + padding-right: 0.5rem !important; +} + +.pb-2, +.py-2 { + padding-bottom: 0.5rem !important; +} + +.pl-2, +.px-2 { + padding-left: 0.5rem !important; +} + +.p-3 { + padding: 1rem !important; +} + +.pt-3, +.py-3 { + padding-top: 1rem !important; +} + +.pr-3, +.px-3 { + padding-right: 1rem !important; +} + +.pb-3, +.py-3 { + padding-bottom: 1rem !important; +} + +.pl-3, +.px-3 { + padding-left: 1rem !important; +} + +.p-4 { + padding: 1.5rem !important; +} + +.pt-4, +.py-4 { + padding-top: 1.5rem !important; +} + +.pr-4, +.px-4 { + padding-right: 1.5rem !important; +} + +.pb-4, +.py-4 { + padding-bottom: 1.5rem !important; +} + +.pl-4, +.px-4 { + padding-left: 1.5rem !important; +} + +.p-5 { + padding: 3rem !important; +} + +.pt-5, +.py-5 { + padding-top: 3rem !important; +} + +.pr-5, +.px-5 { + padding-right: 3rem !important; +} + +.pb-5, +.py-5 { + padding-bottom: 3rem !important; +} + +.pl-5, +.px-5 { + padding-left: 3rem !important; +} + +.m-n1 { + margin: -0.25rem !important; +} + +.mt-n1, +.my-n1 { + margin-top: -0.25rem !important; +} + +.mr-n1, +.mx-n1 { + margin-right: -0.25rem !important; +} + +.mb-n1, +.my-n1 { + margin-bottom: -0.25rem !important; +} + +.ml-n1, +.mx-n1 { + margin-left: -0.25rem !important; +} + +.m-n2 { + margin: -0.5rem !important; +} + +.mt-n2, +.my-n2 { + margin-top: -0.5rem !important; +} + +.mr-n2, +.mx-n2 { + margin-right: -0.5rem !important; +} + +.mb-n2, +.my-n2 { + margin-bottom: -0.5rem !important; +} + +.ml-n2, +.mx-n2 { + margin-left: -0.5rem !important; +} + +.m-n3 { + margin: -1rem !important; +} + +.mt-n3, +.my-n3 { + margin-top: -1rem !important; +} + +.mr-n3, +.mx-n3 { + margin-right: -1rem !important; +} + +.mb-n3, +.my-n3 { + margin-bottom: -1rem !important; +} + +.ml-n3, +.mx-n3 { + margin-left: -1rem !important; +} + +.m-n4 { + margin: -1.5rem !important; +} + +.mt-n4, +.my-n4 { + margin-top: -1.5rem !important; +} + +.mr-n4, +.mx-n4 { + margin-right: -1.5rem !important; +} + +.mb-n4, +.my-n4 { + margin-bottom: -1.5rem !important; +} + +.ml-n4, +.mx-n4 { + margin-left: -1.5rem !important; +} + +.m-n5 { + margin: -3rem !important; +} + +.mt-n5, +.my-n5 { + margin-top: -3rem !important; +} + +.mr-n5, +.mx-n5 { + margin-right: -3rem !important; +} + +.mb-n5, +.my-n5 { + margin-bottom: -3rem !important; +} + +.ml-n5, +.mx-n5 { + margin-left: -3rem !important; +} + +.m-auto { + margin: auto !important; +} + +.mt-auto, +.my-auto { + margin-top: auto !important; +} + +.mr-auto, +.mx-auto { + margin-right: auto !important; +} + +.mb-auto, +.my-auto { + margin-bottom: auto !important; +} + +.ml-auto, +.mx-auto { + margin-left: auto !important; +} + +@media (min-width: 576px) { + .m-sm-0 { + margin: 0 !important; + } + .mt-sm-0, + .my-sm-0 { + margin-top: 0 !important; + } + .mr-sm-0, + .mx-sm-0 { + margin-right: 0 !important; + } + .mb-sm-0, + .my-sm-0 { + margin-bottom: 0 !important; + } + .ml-sm-0, + .mx-sm-0 { + margin-left: 0 !important; + } + .m-sm-1 { + margin: 0.25rem !important; + } + .mt-sm-1, + .my-sm-1 { + margin-top: 0.25rem !important; + } + .mr-sm-1, + .mx-sm-1 { + margin-right: 0.25rem !important; + } + .mb-sm-1, + .my-sm-1 { + margin-bottom: 0.25rem !important; + } + .ml-sm-1, + .mx-sm-1 { + margin-left: 0.25rem !important; + } + .m-sm-2 { + margin: 0.5rem !important; + } + .mt-sm-2, + .my-sm-2 { + margin-top: 0.5rem !important; + } + .mr-sm-2, + .mx-sm-2 { + margin-right: 0.5rem !important; + } + .mb-sm-2, + .my-sm-2 { + margin-bottom: 0.5rem !important; + } + .ml-sm-2, + .mx-sm-2 { + margin-left: 0.5rem !important; + } + .m-sm-3 { + margin: 1rem !important; + } + .mt-sm-3, + .my-sm-3 { + margin-top: 1rem !important; + } + .mr-sm-3, + .mx-sm-3 { + margin-right: 1rem !important; + } + .mb-sm-3, + .my-sm-3 { + margin-bottom: 1rem !important; + } + .ml-sm-3, + .mx-sm-3 { + margin-left: 1rem !important; + } + .m-sm-4 { + margin: 1.5rem !important; + } + .mt-sm-4, + .my-sm-4 { + margin-top: 1.5rem !important; + } + .mr-sm-4, + .mx-sm-4 { + margin-right: 1.5rem !important; + } + .mb-sm-4, + .my-sm-4 { + margin-bottom: 1.5rem !important; + } + .ml-sm-4, + .mx-sm-4 { + margin-left: 1.5rem !important; + } + .m-sm-5 { + margin: 3rem !important; + } + .mt-sm-5, + .my-sm-5 { + margin-top: 3rem !important; + } + .mr-sm-5, + .mx-sm-5 { + margin-right: 3rem !important; + } + .mb-sm-5, + .my-sm-5 { + margin-bottom: 3rem !important; + } + .ml-sm-5, + .mx-sm-5 { + margin-left: 3rem !important; + } + .p-sm-0 { + padding: 0 !important; + } + .pt-sm-0, + .py-sm-0 { + padding-top: 0 !important; + } + .pr-sm-0, + .px-sm-0 { + padding-right: 0 !important; + } + .pb-sm-0, + .py-sm-0 { + padding-bottom: 0 !important; + } + .pl-sm-0, + .px-sm-0 { + padding-left: 0 !important; + } + .p-sm-1 { + padding: 0.25rem !important; + } + .pt-sm-1, + .py-sm-1 { + padding-top: 0.25rem !important; + } + .pr-sm-1, + .px-sm-1 { + padding-right: 0.25rem !important; + } + .pb-sm-1, + .py-sm-1 { + padding-bottom: 0.25rem !important; + } + .pl-sm-1, + .px-sm-1 { + padding-left: 0.25rem !important; + } + .p-sm-2 { + padding: 0.5rem !important; + } + .pt-sm-2, + .py-sm-2 { + padding-top: 0.5rem !important; + } + .pr-sm-2, + .px-sm-2 { + padding-right: 0.5rem !important; + } + .pb-sm-2, + .py-sm-2 { + padding-bottom: 0.5rem !important; + } + .pl-sm-2, + .px-sm-2 { + padding-left: 0.5rem !important; + } + .p-sm-3 { + padding: 1rem !important; + } + .pt-sm-3, + .py-sm-3 { + padding-top: 1rem !important; + } + .pr-sm-3, + .px-sm-3 { + padding-right: 1rem !important; + } + .pb-sm-3, + .py-sm-3 { + padding-bottom: 1rem !important; + } + .pl-sm-3, + .px-sm-3 { + padding-left: 1rem !important; + } + .p-sm-4 { + padding: 1.5rem !important; + } + .pt-sm-4, + .py-sm-4 { + padding-top: 1.5rem !important; + } + .pr-sm-4, + .px-sm-4 { + padding-right: 1.5rem !important; + } + .pb-sm-4, + .py-sm-4 { + padding-bottom: 1.5rem !important; + } + .pl-sm-4, + .px-sm-4 { + padding-left: 1.5rem !important; + } + .p-sm-5 { + padding: 3rem !important; + } + .pt-sm-5, + .py-sm-5 { + padding-top: 3rem !important; + } + .pr-sm-5, + .px-sm-5 { + padding-right: 3rem !important; + } + .pb-sm-5, + .py-sm-5 { + padding-bottom: 3rem !important; + } + .pl-sm-5, + .px-sm-5 { + padding-left: 3rem !important; + } + .m-sm-n1 { + margin: -0.25rem !important; + } + .mt-sm-n1, + .my-sm-n1 { + margin-top: -0.25rem !important; + } + .mr-sm-n1, + .mx-sm-n1 { + margin-right: -0.25rem !important; + } + .mb-sm-n1, + .my-sm-n1 { + margin-bottom: -0.25rem !important; + } + .ml-sm-n1, + .mx-sm-n1 { + margin-left: -0.25rem !important; + } + .m-sm-n2 { + margin: -0.5rem !important; + } + .mt-sm-n2, + .my-sm-n2 { + margin-top: -0.5rem !important; + } + .mr-sm-n2, + .mx-sm-n2 { + margin-right: -0.5rem !important; + } + .mb-sm-n2, + .my-sm-n2 { + margin-bottom: -0.5rem !important; + } + .ml-sm-n2, + .mx-sm-n2 { + margin-left: -0.5rem !important; + } + .m-sm-n3 { + margin: -1rem !important; + } + .mt-sm-n3, + .my-sm-n3 { + margin-top: -1rem !important; + } + .mr-sm-n3, + .mx-sm-n3 { + margin-right: -1rem !important; + } + .mb-sm-n3, + .my-sm-n3 { + margin-bottom: -1rem !important; + } + .ml-sm-n3, + .mx-sm-n3 { + margin-left: -1rem !important; + } + .m-sm-n4 { + margin: -1.5rem !important; + } + .mt-sm-n4, + .my-sm-n4 { + margin-top: -1.5rem !important; + } + .mr-sm-n4, + .mx-sm-n4 { + margin-right: -1.5rem !important; + } + .mb-sm-n4, + .my-sm-n4 { + margin-bottom: -1.5rem !important; + } + .ml-sm-n4, + .mx-sm-n4 { + margin-left: -1.5rem !important; + } + .m-sm-n5 { + margin: -3rem !important; + } + .mt-sm-n5, + .my-sm-n5 { + margin-top: -3rem !important; + } + .mr-sm-n5, + .mx-sm-n5 { + margin-right: -3rem !important; + } + .mb-sm-n5, + .my-sm-n5 { + margin-bottom: -3rem !important; + } + .ml-sm-n5, + .mx-sm-n5 { + margin-left: -3rem !important; + } + .m-sm-auto { + margin: auto !important; + } + .mt-sm-auto, + .my-sm-auto { + margin-top: auto !important; + } + .mr-sm-auto, + .mx-sm-auto { + margin-right: auto !important; + } + .mb-sm-auto, + .my-sm-auto { + margin-bottom: auto !important; + } + .ml-sm-auto, + .mx-sm-auto { + margin-left: auto !important; + } +} + +@media (min-width: 768px) { + .m-md-0 { + margin: 0 !important; + } + .mt-md-0, + .my-md-0 { + margin-top: 0 !important; + } + .mr-md-0, + .mx-md-0 { + margin-right: 0 !important; + } + .mb-md-0, + .my-md-0 { + margin-bottom: 0 !important; + } + .ml-md-0, + .mx-md-0 { + margin-left: 0 !important; + } + .m-md-1 { + margin: 0.25rem !important; + } + .mt-md-1, + .my-md-1 { + margin-top: 0.25rem !important; + } + .mr-md-1, + .mx-md-1 { + margin-right: 0.25rem !important; + } + .mb-md-1, + .my-md-1 { + margin-bottom: 0.25rem !important; + } + .ml-md-1, + .mx-md-1 { + margin-left: 0.25rem !important; + } + .m-md-2 { + margin: 0.5rem !important; + } + .mt-md-2, + .my-md-2 { + margin-top: 0.5rem !important; + } + .mr-md-2, + .mx-md-2 { + margin-right: 0.5rem !important; + } + .mb-md-2, + .my-md-2 { + margin-bottom: 0.5rem !important; + } + .ml-md-2, + .mx-md-2 { + margin-left: 0.5rem !important; + } + .m-md-3 { + margin: 1rem !important; + } + .mt-md-3, + .my-md-3 { + margin-top: 1rem !important; + } + .mr-md-3, + .mx-md-3 { + margin-right: 1rem !important; + } + .mb-md-3, + .my-md-3 { + margin-bottom: 1rem !important; + } + .ml-md-3, + .mx-md-3 { + margin-left: 1rem !important; + } + .m-md-4 { + margin: 1.5rem !important; + } + .mt-md-4, + .my-md-4 { + margin-top: 1.5rem !important; + } + .mr-md-4, + .mx-md-4 { + margin-right: 1.5rem !important; + } + .mb-md-4, + .my-md-4 { + margin-bottom: 1.5rem !important; + } + .ml-md-4, + .mx-md-4 { + margin-left: 1.5rem !important; + } + .m-md-5 { + margin: 3rem !important; + } + .mt-md-5, + .my-md-5 { + margin-top: 3rem !important; + } + .mr-md-5, + .mx-md-5 { + margin-right: 3rem !important; + } + .mb-md-5, + .my-md-5 { + margin-bottom: 3rem !important; + } + .ml-md-5, + .mx-md-5 { + margin-left: 3rem !important; + } + .p-md-0 { + padding: 0 !important; + } + .pt-md-0, + .py-md-0 { + padding-top: 0 !important; + } + .pr-md-0, + .px-md-0 { + padding-right: 0 !important; + } + .pb-md-0, + .py-md-0 { + padding-bottom: 0 !important; + } + .pl-md-0, + .px-md-0 { + padding-left: 0 !important; + } + .p-md-1 { + padding: 0.25rem !important; + } + .pt-md-1, + .py-md-1 { + padding-top: 0.25rem !important; + } + .pr-md-1, + .px-md-1 { + padding-right: 0.25rem !important; + } + .pb-md-1, + .py-md-1 { + padding-bottom: 0.25rem !important; + } + .pl-md-1, + .px-md-1 { + padding-left: 0.25rem !important; + } + .p-md-2 { + padding: 0.5rem !important; + } + .pt-md-2, + .py-md-2 { + padding-top: 0.5rem !important; + } + .pr-md-2, + .px-md-2 { + padding-right: 0.5rem !important; + } + .pb-md-2, + .py-md-2 { + padding-bottom: 0.5rem !important; + } + .pl-md-2, + .px-md-2 { + padding-left: 0.5rem !important; + } + .p-md-3 { + padding: 1rem !important; + } + .pt-md-3, + .py-md-3 { + padding-top: 1rem !important; + } + .pr-md-3, + .px-md-3 { + padding-right: 1rem !important; + } + .pb-md-3, + .py-md-3 { + padding-bottom: 1rem !important; + } + .pl-md-3, + .px-md-3 { + padding-left: 1rem !important; + } + .p-md-4 { + padding: 1.5rem !important; + } + .pt-md-4, + .py-md-4 { + padding-top: 1.5rem !important; + } + .pr-md-4, + .px-md-4 { + padding-right: 1.5rem !important; + } + .pb-md-4, + .py-md-4 { + padding-bottom: 1.5rem !important; + } + .pl-md-4, + .px-md-4 { + padding-left: 1.5rem !important; + } + .p-md-5 { + padding: 3rem !important; + } + .pt-md-5, + .py-md-5 { + padding-top: 3rem !important; + } + .pr-md-5, + .px-md-5 { + padding-right: 3rem !important; + } + .pb-md-5, + .py-md-5 { + padding-bottom: 3rem !important; + } + .pl-md-5, + .px-md-5 { + padding-left: 3rem !important; + } + .m-md-n1 { + margin: -0.25rem !important; + } + .mt-md-n1, + .my-md-n1 { + margin-top: -0.25rem !important; + } + .mr-md-n1, + .mx-md-n1 { + margin-right: -0.25rem !important; + } + .mb-md-n1, + .my-md-n1 { + margin-bottom: -0.25rem !important; + } + .ml-md-n1, + .mx-md-n1 { + margin-left: -0.25rem !important; + } + .m-md-n2 { + margin: -0.5rem !important; + } + .mt-md-n2, + .my-md-n2 { + margin-top: -0.5rem !important; + } + .mr-md-n2, + .mx-md-n2 { + margin-right: -0.5rem !important; + } + .mb-md-n2, + .my-md-n2 { + margin-bottom: -0.5rem !important; + } + .ml-md-n2, + .mx-md-n2 { + margin-left: -0.5rem !important; + } + .m-md-n3 { + margin: -1rem !important; + } + .mt-md-n3, + .my-md-n3 { + margin-top: -1rem !important; + } + .mr-md-n3, + .mx-md-n3 { + margin-right: -1rem !important; + } + .mb-md-n3, + .my-md-n3 { + margin-bottom: -1rem !important; + } + .ml-md-n3, + .mx-md-n3 { + margin-left: -1rem !important; + } + .m-md-n4 { + margin: -1.5rem !important; + } + .mt-md-n4, + .my-md-n4 { + margin-top: -1.5rem !important; + } + .mr-md-n4, + .mx-md-n4 { + margin-right: -1.5rem !important; + } + .mb-md-n4, + .my-md-n4 { + margin-bottom: -1.5rem !important; + } + .ml-md-n4, + .mx-md-n4 { + margin-left: -1.5rem !important; + } + .m-md-n5 { + margin: -3rem !important; + } + .mt-md-n5, + .my-md-n5 { + margin-top: -3rem !important; + } + .mr-md-n5, + .mx-md-n5 { + margin-right: -3rem !important; + } + .mb-md-n5, + .my-md-n5 { + margin-bottom: -3rem !important; + } + .ml-md-n5, + .mx-md-n5 { + margin-left: -3rem !important; + } + .m-md-auto { + margin: auto !important; + } + .mt-md-auto, + .my-md-auto { + margin-top: auto !important; + } + .mr-md-auto, + .mx-md-auto { + margin-right: auto !important; + } + .mb-md-auto, + .my-md-auto { + margin-bottom: auto !important; + } + .ml-md-auto, + .mx-md-auto { + margin-left: auto !important; + } +} + +@media (min-width: 992px) { + .m-lg-0 { + margin: 0 !important; + } + .mt-lg-0, + .my-lg-0 { + margin-top: 0 !important; + } + .mr-lg-0, + .mx-lg-0 { + margin-right: 0 !important; + } + .mb-lg-0, + .my-lg-0 { + margin-bottom: 0 !important; + } + .ml-lg-0, + .mx-lg-0 { + margin-left: 0 !important; + } + .m-lg-1 { + margin: 0.25rem !important; + } + .mt-lg-1, + .my-lg-1 { + margin-top: 0.25rem !important; + } + .mr-lg-1, + .mx-lg-1 { + margin-right: 0.25rem !important; + } + .mb-lg-1, + .my-lg-1 { + margin-bottom: 0.25rem !important; + } + .ml-lg-1, + .mx-lg-1 { + margin-left: 0.25rem !important; + } + .m-lg-2 { + margin: 0.5rem !important; + } + .mt-lg-2, + .my-lg-2 { + margin-top: 0.5rem !important; + } + .mr-lg-2, + .mx-lg-2 { + margin-right: 0.5rem !important; + } + .mb-lg-2, + .my-lg-2 { + margin-bottom: 0.5rem !important; + } + .ml-lg-2, + .mx-lg-2 { + margin-left: 0.5rem !important; + } + .m-lg-3 { + margin: 1rem !important; + } + .mt-lg-3, + .my-lg-3 { + margin-top: 1rem !important; + } + .mr-lg-3, + .mx-lg-3 { + margin-right: 1rem !important; + } + .mb-lg-3, + .my-lg-3 { + margin-bottom: 1rem !important; + } + .ml-lg-3, + .mx-lg-3 { + margin-left: 1rem !important; + } + .m-lg-4 { + margin: 1.5rem !important; + } + .mt-lg-4, + .my-lg-4 { + margin-top: 1.5rem !important; + } + .mr-lg-4, + .mx-lg-4 { + margin-right: 1.5rem !important; + } + .mb-lg-4, + .my-lg-4 { + margin-bottom: 1.5rem !important; + } + .ml-lg-4, + .mx-lg-4 { + margin-left: 1.5rem !important; + } + .m-lg-5 { + margin: 3rem !important; + } + .mt-lg-5, + .my-lg-5 { + margin-top: 3rem !important; + } + .mr-lg-5, + .mx-lg-5 { + margin-right: 3rem !important; + } + .mb-lg-5, + .my-lg-5 { + margin-bottom: 3rem !important; + } + .ml-lg-5, + .mx-lg-5 { + margin-left: 3rem !important; + } + .p-lg-0 { + padding: 0 !important; + } + .pt-lg-0, + .py-lg-0 { + padding-top: 0 !important; + } + .pr-lg-0, + .px-lg-0 { + padding-right: 0 !important; + } + .pb-lg-0, + .py-lg-0 { + padding-bottom: 0 !important; + } + .pl-lg-0, + .px-lg-0 { + padding-left: 0 !important; + } + .p-lg-1 { + padding: 0.25rem !important; + } + .pt-lg-1, + .py-lg-1 { + padding-top: 0.25rem !important; + } + .pr-lg-1, + .px-lg-1 { + padding-right: 0.25rem !important; + } + .pb-lg-1, + .py-lg-1 { + padding-bottom: 0.25rem !important; + } + .pl-lg-1, + .px-lg-1 { + padding-left: 0.25rem !important; + } + .p-lg-2 { + padding: 0.5rem !important; + } + .pt-lg-2, + .py-lg-2 { + padding-top: 0.5rem !important; + } + .pr-lg-2, + .px-lg-2 { + padding-right: 0.5rem !important; + } + .pb-lg-2, + .py-lg-2 { + padding-bottom: 0.5rem !important; + } + .pl-lg-2, + .px-lg-2 { + padding-left: 0.5rem !important; + } + .p-lg-3 { + padding: 1rem !important; + } + .pt-lg-3, + .py-lg-3 { + padding-top: 1rem !important; + } + .pr-lg-3, + .px-lg-3 { + padding-right: 1rem !important; + } + .pb-lg-3, + .py-lg-3 { + padding-bottom: 1rem !important; + } + .pl-lg-3, + .px-lg-3 { + padding-left: 1rem !important; + } + .p-lg-4 { + padding: 1.5rem !important; + } + .pt-lg-4, + .py-lg-4 { + padding-top: 1.5rem !important; + } + .pr-lg-4, + .px-lg-4 { + padding-right: 1.5rem !important; + } + .pb-lg-4, + .py-lg-4 { + padding-bottom: 1.5rem !important; + } + .pl-lg-4, + .px-lg-4 { + padding-left: 1.5rem !important; + } + .p-lg-5 { + padding: 3rem !important; + } + .pt-lg-5, + .py-lg-5 { + padding-top: 3rem !important; + } + .pr-lg-5, + .px-lg-5 { + padding-right: 3rem !important; + } + .pb-lg-5, + .py-lg-5 { + padding-bottom: 3rem !important; + } + .pl-lg-5, + .px-lg-5 { + padding-left: 3rem !important; + } + .m-lg-n1 { + margin: -0.25rem !important; + } + .mt-lg-n1, + .my-lg-n1 { + margin-top: -0.25rem !important; + } + .mr-lg-n1, + .mx-lg-n1 { + margin-right: -0.25rem !important; + } + .mb-lg-n1, + .my-lg-n1 { + margin-bottom: -0.25rem !important; + } + .ml-lg-n1, + .mx-lg-n1 { + margin-left: -0.25rem !important; + } + .m-lg-n2 { + margin: -0.5rem !important; + } + .mt-lg-n2, + .my-lg-n2 { + margin-top: -0.5rem !important; + } + .mr-lg-n2, + .mx-lg-n2 { + margin-right: -0.5rem !important; + } + .mb-lg-n2, + .my-lg-n2 { + margin-bottom: -0.5rem !important; + } + .ml-lg-n2, + .mx-lg-n2 { + margin-left: -0.5rem !important; + } + .m-lg-n3 { + margin: -1rem !important; + } + .mt-lg-n3, + .my-lg-n3 { + margin-top: -1rem !important; + } + .mr-lg-n3, + .mx-lg-n3 { + margin-right: -1rem !important; + } + .mb-lg-n3, + .my-lg-n3 { + margin-bottom: -1rem !important; + } + .ml-lg-n3, + .mx-lg-n3 { + margin-left: -1rem !important; + } + .m-lg-n4 { + margin: -1.5rem !important; + } + .mt-lg-n4, + .my-lg-n4 { + margin-top: -1.5rem !important; + } + .mr-lg-n4, + .mx-lg-n4 { + margin-right: -1.5rem !important; + } + .mb-lg-n4, + .my-lg-n4 { + margin-bottom: -1.5rem !important; + } + .ml-lg-n4, + .mx-lg-n4 { + margin-left: -1.5rem !important; + } + .m-lg-n5 { + margin: -3rem !important; + } + .mt-lg-n5, + .my-lg-n5 { + margin-top: -3rem !important; + } + .mr-lg-n5, + .mx-lg-n5 { + margin-right: -3rem !important; + } + .mb-lg-n5, + .my-lg-n5 { + margin-bottom: -3rem !important; + } + .ml-lg-n5, + .mx-lg-n5 { + margin-left: -3rem !important; + } + .m-lg-auto { + margin: auto !important; + } + .mt-lg-auto, + .my-lg-auto { + margin-top: auto !important; + } + .mr-lg-auto, + .mx-lg-auto { + margin-right: auto !important; + } + .mb-lg-auto, + .my-lg-auto { + margin-bottom: auto !important; + } + .ml-lg-auto, + .mx-lg-auto { + margin-left: auto !important; + } +} + +@media (min-width: 1200px) { + .m-xl-0 { + margin: 0 !important; + } + .mt-xl-0, + .my-xl-0 { + margin-top: 0 !important; + } + .mr-xl-0, + .mx-xl-0 { + margin-right: 0 !important; + } + .mb-xl-0, + .my-xl-0 { + margin-bottom: 0 !important; + } + .ml-xl-0, + .mx-xl-0 { + margin-left: 0 !important; + } + .m-xl-1 { + margin: 0.25rem !important; + } + .mt-xl-1, + .my-xl-1 { + margin-top: 0.25rem !important; + } + .mr-xl-1, + .mx-xl-1 { + margin-right: 0.25rem !important; + } + .mb-xl-1, + .my-xl-1 { + margin-bottom: 0.25rem !important; + } + .ml-xl-1, + .mx-xl-1 { + margin-left: 0.25rem !important; + } + .m-xl-2 { + margin: 0.5rem !important; + } + .mt-xl-2, + .my-xl-2 { + margin-top: 0.5rem !important; + } + .mr-xl-2, + .mx-xl-2 { + margin-right: 0.5rem !important; + } + .mb-xl-2, + .my-xl-2 { + margin-bottom: 0.5rem !important; + } + .ml-xl-2, + .mx-xl-2 { + margin-left: 0.5rem !important; + } + .m-xl-3 { + margin: 1rem !important; + } + .mt-xl-3, + .my-xl-3 { + margin-top: 1rem !important; + } + .mr-xl-3, + .mx-xl-3 { + margin-right: 1rem !important; + } + .mb-xl-3, + .my-xl-3 { + margin-bottom: 1rem !important; + } + .ml-xl-3, + .mx-xl-3 { + margin-left: 1rem !important; + } + .m-xl-4 { + margin: 1.5rem !important; + } + .mt-xl-4, + .my-xl-4 { + margin-top: 1.5rem !important; + } + .mr-xl-4, + .mx-xl-4 { + margin-right: 1.5rem !important; + } + .mb-xl-4, + .my-xl-4 { + margin-bottom: 1.5rem !important; + } + .ml-xl-4, + .mx-xl-4 { + margin-left: 1.5rem !important; + } + .m-xl-5 { + margin: 3rem !important; + } + .mt-xl-5, + .my-xl-5 { + margin-top: 3rem !important; + } + .mr-xl-5, + .mx-xl-5 { + margin-right: 3rem !important; + } + .mb-xl-5, + .my-xl-5 { + margin-bottom: 3rem !important; + } + .ml-xl-5, + .mx-xl-5 { + margin-left: 3rem !important; + } + .p-xl-0 { + padding: 0 !important; + } + .pt-xl-0, + .py-xl-0 { + padding-top: 0 !important; + } + .pr-xl-0, + .px-xl-0 { + padding-right: 0 !important; + } + .pb-xl-0, + .py-xl-0 { + padding-bottom: 0 !important; + } + .pl-xl-0, + .px-xl-0 { + padding-left: 0 !important; + } + .p-xl-1 { + padding: 0.25rem !important; + } + .pt-xl-1, + .py-xl-1 { + padding-top: 0.25rem !important; + } + .pr-xl-1, + .px-xl-1 { + padding-right: 0.25rem !important; + } + .pb-xl-1, + .py-xl-1 { + padding-bottom: 0.25rem !important; + } + .pl-xl-1, + .px-xl-1 { + padding-left: 0.25rem !important; + } + .p-xl-2 { + padding: 0.5rem !important; + } + .pt-xl-2, + .py-xl-2 { + padding-top: 0.5rem !important; + } + .pr-xl-2, + .px-xl-2 { + padding-right: 0.5rem !important; + } + .pb-xl-2, + .py-xl-2 { + padding-bottom: 0.5rem !important; + } + .pl-xl-2, + .px-xl-2 { + padding-left: 0.5rem !important; + } + .p-xl-3 { + padding: 1rem !important; + } + .pt-xl-3, + .py-xl-3 { + padding-top: 1rem !important; + } + .pr-xl-3, + .px-xl-3 { + padding-right: 1rem !important; + } + .pb-xl-3, + .py-xl-3 { + padding-bottom: 1rem !important; + } + .pl-xl-3, + .px-xl-3 { + padding-left: 1rem !important; + } + .p-xl-4 { + padding: 1.5rem !important; + } + .pt-xl-4, + .py-xl-4 { + padding-top: 1.5rem !important; + } + .pr-xl-4, + .px-xl-4 { + padding-right: 1.5rem !important; + } + .pb-xl-4, + .py-xl-4 { + padding-bottom: 1.5rem !important; + } + .pl-xl-4, + .px-xl-4 { + padding-left: 1.5rem !important; + } + .p-xl-5 { + padding: 3rem !important; + } + .pt-xl-5, + .py-xl-5 { + padding-top: 3rem !important; + } + .pr-xl-5, + .px-xl-5 { + padding-right: 3rem !important; + } + .pb-xl-5, + .py-xl-5 { + padding-bottom: 3rem !important; + } + .pl-xl-5, + .px-xl-5 { + padding-left: 3rem !important; + } + .m-xl-n1 { + margin: -0.25rem !important; + } + .mt-xl-n1, + .my-xl-n1 { + margin-top: -0.25rem !important; + } + .mr-xl-n1, + .mx-xl-n1 { + margin-right: -0.25rem !important; + } + .mb-xl-n1, + .my-xl-n1 { + margin-bottom: -0.25rem !important; + } + .ml-xl-n1, + .mx-xl-n1 { + margin-left: -0.25rem !important; + } + .m-xl-n2 { + margin: -0.5rem !important; + } + .mt-xl-n2, + .my-xl-n2 { + margin-top: -0.5rem !important; + } + .mr-xl-n2, + .mx-xl-n2 { + margin-right: -0.5rem !important; + } + .mb-xl-n2, + .my-xl-n2 { + margin-bottom: -0.5rem !important; + } + .ml-xl-n2, + .mx-xl-n2 { + margin-left: -0.5rem !important; + } + .m-xl-n3 { + margin: -1rem !important; + } + .mt-xl-n3, + .my-xl-n3 { + margin-top: -1rem !important; + } + .mr-xl-n3, + .mx-xl-n3 { + margin-right: -1rem !important; + } + .mb-xl-n3, + .my-xl-n3 { + margin-bottom: -1rem !important; + } + .ml-xl-n3, + .mx-xl-n3 { + margin-left: -1rem !important; + } + .m-xl-n4 { + margin: -1.5rem !important; + } + .mt-xl-n4, + .my-xl-n4 { + margin-top: -1.5rem !important; + } + .mr-xl-n4, + .mx-xl-n4 { + margin-right: -1.5rem !important; + } + .mb-xl-n4, + .my-xl-n4 { + margin-bottom: -1.5rem !important; + } + .ml-xl-n4, + .mx-xl-n4 { + margin-left: -1.5rem !important; + } + .m-xl-n5 { + margin: -3rem !important; + } + .mt-xl-n5, + .my-xl-n5 { + margin-top: -3rem !important; + } + .mr-xl-n5, + .mx-xl-n5 { + margin-right: -3rem !important; + } + .mb-xl-n5, + .my-xl-n5 { + margin-bottom: -3rem !important; + } + .ml-xl-n5, + .mx-xl-n5 { + margin-left: -3rem !important; + } + .m-xl-auto { + margin: auto !important; + } + .mt-xl-auto, + .my-xl-auto { + margin-top: auto !important; + } + .mr-xl-auto, + .mx-xl-auto { + margin-right: auto !important; + } + .mb-xl-auto, + .my-xl-auto { + margin-bottom: auto !important; + } + .ml-xl-auto, + .mx-xl-auto { + margin-left: auto !important; + } +} /*# sourceMappingURL=bootstrap-grid.css.map */ \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map index a636ccee..db62f2f3 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map @@ -1 +1 @@ -{"version":3,"sources":["../../scss/bootstrap-grid.scss","bootstrap-grid.css","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_breakpoints.scss","../../scss/_variables.scss","../../scss/mixins/_grid-framework.scss","../../scss/utilities/_display.scss","../../scss/utilities/_flex.scss"],"names":[],"mappings":"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","file":"bootstrap-grid.css","sourcesContent":["/*!\n * Bootstrap Grid v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n@at-root {\n @-ms-viewport { width: device-width; } // stylelint-disable-line at-rule-no-vendor-prefix\n}\n\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n@import \"functions\";\n@import \"variables\";\n\n@import \"mixins/breakpoints\";\n@import \"mixins/grid-framework\";\n@import \"mixins/grid\";\n\n@import \"grid\";\n@import \"utilities/display\";\n@import \"utilities/flex\";\n","/*!\n * Bootstrap Grid v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n@-ms-viewport {\n width: device-width;\n}\n\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n.container {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n@media (min-width: 576px) {\n .container {\n max-width: 540px;\n }\n}\n\n@media (min-width: 768px) {\n .container {\n max-width: 720px;\n }\n}\n\n@media (min-width: 992px) {\n .container {\n max-width: 960px;\n }\n}\n\n@media (min-width: 1200px) {\n .container {\n max-width: 1140px;\n }\n}\n\n.container-fluid {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n.row {\n display: flex;\n flex-wrap: wrap;\n margin-right: -15px;\n margin-left: -15px;\n}\n\n.no-gutters {\n margin-right: 0;\n margin-left: 0;\n}\n\n.no-gutters > .col,\n.no-gutters > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n}\n\n.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n position: relative;\n width: 100%;\n min-height: 1px;\n padding-right: 15px;\n padding-left: 15px;\n}\n\n.col {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n}\n\n.col-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n}\n\n.col-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n}\n\n.col-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n}\n\n.col-3 {\n flex: 0 0 25%;\n max-width: 25%;\n}\n\n.col-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n}\n\n.col-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n}\n\n.col-6 {\n flex: 0 0 50%;\n max-width: 50%;\n}\n\n.col-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n}\n\n.col-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n}\n\n.col-9 {\n flex: 0 0 75%;\n max-width: 75%;\n}\n\n.col-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n}\n\n.col-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n}\n\n.col-12 {\n flex: 0 0 100%;\n max-width: 100%;\n}\n\n.order-first {\n order: -1;\n}\n\n.order-last {\n order: 13;\n}\n\n.order-0 {\n order: 0;\n}\n\n.order-1 {\n order: 1;\n}\n\n.order-2 {\n order: 2;\n}\n\n.order-3 {\n order: 3;\n}\n\n.order-4 {\n order: 4;\n}\n\n.order-5 {\n order: 5;\n}\n\n.order-6 {\n order: 6;\n}\n\n.order-7 {\n order: 7;\n}\n\n.order-8 {\n order: 8;\n}\n\n.order-9 {\n order: 9;\n}\n\n.order-10 {\n order: 10;\n}\n\n.order-11 {\n order: 11;\n}\n\n.order-12 {\n order: 12;\n}\n\n.offset-1 {\n margin-left: 8.333333%;\n}\n\n.offset-2 {\n margin-left: 16.666667%;\n}\n\n.offset-3 {\n margin-left: 25%;\n}\n\n.offset-4 {\n margin-left: 33.333333%;\n}\n\n.offset-5 {\n margin-left: 41.666667%;\n}\n\n.offset-6 {\n margin-left: 50%;\n}\n\n.offset-7 {\n margin-left: 58.333333%;\n}\n\n.offset-8 {\n margin-left: 66.666667%;\n}\n\n.offset-9 {\n margin-left: 75%;\n}\n\n.offset-10 {\n margin-left: 83.333333%;\n}\n\n.offset-11 {\n margin-left: 91.666667%;\n}\n\n@media (min-width: 576px) {\n .col-sm {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-sm-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-sm-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-sm-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-sm-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-sm-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-sm-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-sm-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-sm-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-sm-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-sm-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-sm-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-sm-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-sm-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-sm-first {\n order: -1;\n }\n .order-sm-last {\n order: 13;\n }\n .order-sm-0 {\n order: 0;\n }\n .order-sm-1 {\n order: 1;\n }\n .order-sm-2 {\n order: 2;\n }\n .order-sm-3 {\n order: 3;\n }\n .order-sm-4 {\n order: 4;\n }\n .order-sm-5 {\n order: 5;\n }\n .order-sm-6 {\n order: 6;\n }\n .order-sm-7 {\n order: 7;\n }\n .order-sm-8 {\n order: 8;\n }\n .order-sm-9 {\n order: 9;\n }\n .order-sm-10 {\n order: 10;\n }\n .order-sm-11 {\n order: 11;\n }\n .order-sm-12 {\n order: 12;\n }\n .offset-sm-0 {\n margin-left: 0;\n }\n .offset-sm-1 {\n margin-left: 8.333333%;\n }\n .offset-sm-2 {\n margin-left: 16.666667%;\n }\n .offset-sm-3 {\n margin-left: 25%;\n }\n .offset-sm-4 {\n margin-left: 33.333333%;\n }\n .offset-sm-5 {\n margin-left: 41.666667%;\n }\n .offset-sm-6 {\n margin-left: 50%;\n }\n .offset-sm-7 {\n margin-left: 58.333333%;\n }\n .offset-sm-8 {\n margin-left: 66.666667%;\n }\n .offset-sm-9 {\n margin-left: 75%;\n }\n .offset-sm-10 {\n margin-left: 83.333333%;\n }\n .offset-sm-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 768px) {\n .col-md {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-md-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-md-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-md-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-md-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-md-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-md-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-md-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-md-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-md-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-md-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-md-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-md-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-md-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-md-first {\n order: -1;\n }\n .order-md-last {\n order: 13;\n }\n .order-md-0 {\n order: 0;\n }\n .order-md-1 {\n order: 1;\n }\n .order-md-2 {\n order: 2;\n }\n .order-md-3 {\n order: 3;\n }\n .order-md-4 {\n order: 4;\n }\n .order-md-5 {\n order: 5;\n }\n .order-md-6 {\n order: 6;\n }\n .order-md-7 {\n order: 7;\n }\n .order-md-8 {\n order: 8;\n }\n .order-md-9 {\n order: 9;\n }\n .order-md-10 {\n order: 10;\n }\n .order-md-11 {\n order: 11;\n }\n .order-md-12 {\n order: 12;\n }\n .offset-md-0 {\n margin-left: 0;\n }\n .offset-md-1 {\n margin-left: 8.333333%;\n }\n .offset-md-2 {\n margin-left: 16.666667%;\n }\n .offset-md-3 {\n margin-left: 25%;\n }\n .offset-md-4 {\n margin-left: 33.333333%;\n }\n .offset-md-5 {\n margin-left: 41.666667%;\n }\n .offset-md-6 {\n margin-left: 50%;\n }\n .offset-md-7 {\n margin-left: 58.333333%;\n }\n .offset-md-8 {\n margin-left: 66.666667%;\n }\n .offset-md-9 {\n margin-left: 75%;\n }\n .offset-md-10 {\n margin-left: 83.333333%;\n }\n .offset-md-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 992px) {\n .col-lg {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-lg-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-lg-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-lg-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-lg-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-lg-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-lg-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-lg-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-lg-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-lg-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-lg-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-lg-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-lg-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-lg-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-lg-first {\n order: -1;\n }\n .order-lg-last {\n order: 13;\n }\n .order-lg-0 {\n order: 0;\n }\n .order-lg-1 {\n order: 1;\n }\n .order-lg-2 {\n order: 2;\n }\n .order-lg-3 {\n order: 3;\n }\n .order-lg-4 {\n order: 4;\n }\n .order-lg-5 {\n order: 5;\n }\n .order-lg-6 {\n order: 6;\n }\n .order-lg-7 {\n order: 7;\n }\n .order-lg-8 {\n order: 8;\n }\n .order-lg-9 {\n order: 9;\n }\n .order-lg-10 {\n order: 10;\n }\n .order-lg-11 {\n order: 11;\n }\n .order-lg-12 {\n order: 12;\n }\n .offset-lg-0 {\n margin-left: 0;\n }\n .offset-lg-1 {\n margin-left: 8.333333%;\n }\n .offset-lg-2 {\n margin-left: 16.666667%;\n }\n .offset-lg-3 {\n margin-left: 25%;\n }\n .offset-lg-4 {\n margin-left: 33.333333%;\n }\n .offset-lg-5 {\n margin-left: 41.666667%;\n }\n .offset-lg-6 {\n margin-left: 50%;\n }\n .offset-lg-7 {\n margin-left: 58.333333%;\n }\n .offset-lg-8 {\n margin-left: 66.666667%;\n }\n .offset-lg-9 {\n margin-left: 75%;\n }\n .offset-lg-10 {\n margin-left: 83.333333%;\n }\n .offset-lg-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 1200px) {\n .col-xl {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-xl-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-xl-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-xl-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-xl-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-xl-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-xl-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-xl-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-xl-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-xl-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-xl-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-xl-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-xl-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-xl-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-xl-first {\n order: -1;\n }\n .order-xl-last {\n order: 13;\n }\n .order-xl-0 {\n order: 0;\n }\n .order-xl-1 {\n order: 1;\n }\n .order-xl-2 {\n order: 2;\n }\n .order-xl-3 {\n order: 3;\n }\n .order-xl-4 {\n order: 4;\n }\n .order-xl-5 {\n order: 5;\n }\n .order-xl-6 {\n order: 6;\n }\n .order-xl-7 {\n order: 7;\n }\n .order-xl-8 {\n order: 8;\n }\n .order-xl-9 {\n order: 9;\n }\n .order-xl-10 {\n order: 10;\n }\n .order-xl-11 {\n order: 11;\n }\n .order-xl-12 {\n order: 12;\n }\n .offset-xl-0 {\n margin-left: 0;\n }\n .offset-xl-1 {\n margin-left: 8.333333%;\n }\n .offset-xl-2 {\n margin-left: 16.666667%;\n }\n .offset-xl-3 {\n margin-left: 25%;\n }\n .offset-xl-4 {\n margin-left: 33.333333%;\n }\n .offset-xl-5 {\n margin-left: 41.666667%;\n }\n .offset-xl-6 {\n margin-left: 50%;\n }\n .offset-xl-7 {\n margin-left: 58.333333%;\n }\n .offset-xl-8 {\n margin-left: 66.666667%;\n }\n .offset-xl-9 {\n margin-left: 75%;\n }\n .offset-xl-10 {\n margin-left: 83.333333%;\n }\n .offset-xl-11 {\n margin-left: 91.666667%;\n }\n}\n\n.d-none {\n display: none !important;\n}\n\n.d-inline {\n display: inline !important;\n}\n\n.d-inline-block {\n display: inline-block !important;\n}\n\n.d-block {\n display: block !important;\n}\n\n.d-table {\n display: table !important;\n}\n\n.d-table-row {\n display: table-row !important;\n}\n\n.d-table-cell {\n display: table-cell !important;\n}\n\n.d-flex {\n display: flex !important;\n}\n\n.d-inline-flex {\n display: inline-flex !important;\n}\n\n@media (min-width: 576px) {\n .d-sm-none {\n display: none !important;\n }\n .d-sm-inline {\n display: inline !important;\n }\n .d-sm-inline-block {\n display: inline-block !important;\n }\n .d-sm-block {\n display: block !important;\n }\n .d-sm-table {\n display: table !important;\n }\n .d-sm-table-row {\n display: table-row !important;\n }\n .d-sm-table-cell {\n display: table-cell !important;\n }\n .d-sm-flex {\n display: flex !important;\n }\n .d-sm-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 768px) {\n .d-md-none {\n display: none !important;\n }\n .d-md-inline {\n display: inline !important;\n }\n .d-md-inline-block {\n display: inline-block !important;\n }\n .d-md-block {\n display: block !important;\n }\n .d-md-table {\n display: table !important;\n }\n .d-md-table-row {\n display: table-row !important;\n }\n .d-md-table-cell {\n display: table-cell !important;\n }\n .d-md-flex {\n display: flex !important;\n }\n .d-md-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 992px) {\n .d-lg-none {\n display: none !important;\n }\n .d-lg-inline {\n display: inline !important;\n }\n .d-lg-inline-block {\n display: inline-block !important;\n }\n .d-lg-block {\n display: block !important;\n }\n .d-lg-table {\n display: table !important;\n }\n .d-lg-table-row {\n display: table-row !important;\n }\n .d-lg-table-cell {\n display: table-cell !important;\n }\n .d-lg-flex {\n display: flex !important;\n }\n .d-lg-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 1200px) {\n .d-xl-none {\n display: none !important;\n }\n .d-xl-inline {\n display: inline !important;\n }\n .d-xl-inline-block {\n display: inline-block !important;\n }\n .d-xl-block {\n display: block !important;\n }\n .d-xl-table {\n display: table !important;\n }\n .d-xl-table-row {\n display: table-row !important;\n }\n .d-xl-table-cell {\n display: table-cell !important;\n }\n .d-xl-flex {\n display: flex !important;\n }\n .d-xl-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media print {\n .d-print-none {\n display: none !important;\n }\n .d-print-inline {\n display: inline !important;\n }\n .d-print-inline-block {\n display: inline-block !important;\n }\n .d-print-block {\n display: block !important;\n }\n .d-print-table {\n display: table !important;\n }\n .d-print-table-row {\n display: table-row !important;\n }\n .d-print-table-cell {\n display: table-cell !important;\n }\n .d-print-flex {\n display: flex !important;\n }\n .d-print-inline-flex {\n display: inline-flex !important;\n }\n}\n\n.flex-row {\n flex-direction: row !important;\n}\n\n.flex-column {\n flex-direction: column !important;\n}\n\n.flex-row-reverse {\n flex-direction: row-reverse !important;\n}\n\n.flex-column-reverse {\n flex-direction: column-reverse !important;\n}\n\n.flex-wrap {\n flex-wrap: wrap !important;\n}\n\n.flex-nowrap {\n flex-wrap: nowrap !important;\n}\n\n.flex-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n}\n\n.flex-fill {\n flex: 1 1 auto !important;\n}\n\n.flex-grow-0 {\n flex-grow: 0 !important;\n}\n\n.flex-grow-1 {\n flex-grow: 1 !important;\n}\n\n.flex-shrink-0 {\n flex-shrink: 0 !important;\n}\n\n.flex-shrink-1 {\n flex-shrink: 1 !important;\n}\n\n.justify-content-start {\n justify-content: flex-start !important;\n}\n\n.justify-content-end {\n justify-content: flex-end !important;\n}\n\n.justify-content-center {\n justify-content: center !important;\n}\n\n.justify-content-between {\n justify-content: space-between !important;\n}\n\n.justify-content-around {\n justify-content: space-around !important;\n}\n\n.align-items-start {\n align-items: flex-start !important;\n}\n\n.align-items-end {\n align-items: flex-end !important;\n}\n\n.align-items-center {\n align-items: center !important;\n}\n\n.align-items-baseline {\n align-items: baseline !important;\n}\n\n.align-items-stretch {\n align-items: stretch !important;\n}\n\n.align-content-start {\n align-content: flex-start !important;\n}\n\n.align-content-end {\n align-content: flex-end !important;\n}\n\n.align-content-center {\n align-content: center !important;\n}\n\n.align-content-between {\n align-content: space-between !important;\n}\n\n.align-content-around {\n align-content: space-around !important;\n}\n\n.align-content-stretch {\n align-content: stretch !important;\n}\n\n.align-self-auto {\n align-self: auto !important;\n}\n\n.align-self-start {\n align-self: flex-start !important;\n}\n\n.align-self-end {\n align-self: flex-end !important;\n}\n\n.align-self-center {\n align-self: center !important;\n}\n\n.align-self-baseline {\n align-self: baseline !important;\n}\n\n.align-self-stretch {\n align-self: stretch !important;\n}\n\n@media (min-width: 576px) {\n .flex-sm-row {\n flex-direction: row !important;\n }\n .flex-sm-column {\n flex-direction: column !important;\n }\n .flex-sm-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-sm-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-sm-wrap {\n flex-wrap: wrap !important;\n }\n .flex-sm-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-sm-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-sm-fill {\n flex: 1 1 auto !important;\n }\n .flex-sm-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-sm-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-sm-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-sm-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-sm-start {\n justify-content: flex-start !important;\n }\n .justify-content-sm-end {\n justify-content: flex-end !important;\n }\n .justify-content-sm-center {\n justify-content: center !important;\n }\n .justify-content-sm-between {\n justify-content: space-between !important;\n }\n .justify-content-sm-around {\n justify-content: space-around !important;\n }\n .align-items-sm-start {\n align-items: flex-start !important;\n }\n .align-items-sm-end {\n align-items: flex-end !important;\n }\n .align-items-sm-center {\n align-items: center !important;\n }\n .align-items-sm-baseline {\n align-items: baseline !important;\n }\n .align-items-sm-stretch {\n align-items: stretch !important;\n }\n .align-content-sm-start {\n align-content: flex-start !important;\n }\n .align-content-sm-end {\n align-content: flex-end !important;\n }\n .align-content-sm-center {\n align-content: center !important;\n }\n .align-content-sm-between {\n align-content: space-between !important;\n }\n .align-content-sm-around {\n align-content: space-around !important;\n }\n .align-content-sm-stretch {\n align-content: stretch !important;\n }\n .align-self-sm-auto {\n align-self: auto !important;\n }\n .align-self-sm-start {\n align-self: flex-start !important;\n }\n .align-self-sm-end {\n align-self: flex-end !important;\n }\n .align-self-sm-center {\n align-self: center !important;\n }\n .align-self-sm-baseline {\n align-self: baseline !important;\n }\n .align-self-sm-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 768px) {\n .flex-md-row {\n flex-direction: row !important;\n }\n .flex-md-column {\n flex-direction: column !important;\n }\n .flex-md-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-md-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-md-wrap {\n flex-wrap: wrap !important;\n }\n .flex-md-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-md-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-md-fill {\n flex: 1 1 auto !important;\n }\n .flex-md-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-md-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-md-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-md-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-md-start {\n justify-content: flex-start !important;\n }\n .justify-content-md-end {\n justify-content: flex-end !important;\n }\n .justify-content-md-center {\n justify-content: center !important;\n }\n .justify-content-md-between {\n justify-content: space-between !important;\n }\n .justify-content-md-around {\n justify-content: space-around !important;\n }\n .align-items-md-start {\n align-items: flex-start !important;\n }\n .align-items-md-end {\n align-items: flex-end !important;\n }\n .align-items-md-center {\n align-items: center !important;\n }\n .align-items-md-baseline {\n align-items: baseline !important;\n }\n .align-items-md-stretch {\n align-items: stretch !important;\n }\n .align-content-md-start {\n align-content: flex-start !important;\n }\n .align-content-md-end {\n align-content: flex-end !important;\n }\n .align-content-md-center {\n align-content: center !important;\n }\n .align-content-md-between {\n align-content: space-between !important;\n }\n .align-content-md-around {\n align-content: space-around !important;\n }\n .align-content-md-stretch {\n align-content: stretch !important;\n }\n .align-self-md-auto {\n align-self: auto !important;\n }\n .align-self-md-start {\n align-self: flex-start !important;\n }\n .align-self-md-end {\n align-self: flex-end !important;\n }\n .align-self-md-center {\n align-self: center !important;\n }\n .align-self-md-baseline {\n align-self: baseline !important;\n }\n .align-self-md-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 992px) {\n .flex-lg-row {\n flex-direction: row !important;\n }\n .flex-lg-column {\n flex-direction: column !important;\n }\n .flex-lg-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-lg-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-lg-wrap {\n flex-wrap: wrap !important;\n }\n .flex-lg-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-lg-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-lg-fill {\n flex: 1 1 auto !important;\n }\n .flex-lg-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-lg-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-lg-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-lg-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-lg-start {\n justify-content: flex-start !important;\n }\n .justify-content-lg-end {\n justify-content: flex-end !important;\n }\n .justify-content-lg-center {\n justify-content: center !important;\n }\n .justify-content-lg-between {\n justify-content: space-between !important;\n }\n .justify-content-lg-around {\n justify-content: space-around !important;\n }\n .align-items-lg-start {\n align-items: flex-start !important;\n }\n .align-items-lg-end {\n align-items: flex-end !important;\n }\n .align-items-lg-center {\n align-items: center !important;\n }\n .align-items-lg-baseline {\n align-items: baseline !important;\n }\n .align-items-lg-stretch {\n align-items: stretch !important;\n }\n .align-content-lg-start {\n align-content: flex-start !important;\n }\n .align-content-lg-end {\n align-content: flex-end !important;\n }\n .align-content-lg-center {\n align-content: center !important;\n }\n .align-content-lg-between {\n align-content: space-between !important;\n }\n .align-content-lg-around {\n align-content: space-around !important;\n }\n .align-content-lg-stretch {\n align-content: stretch !important;\n }\n .align-self-lg-auto {\n align-self: auto !important;\n }\n .align-self-lg-start {\n align-self: flex-start !important;\n }\n .align-self-lg-end {\n align-self: flex-end !important;\n }\n .align-self-lg-center {\n align-self: center !important;\n }\n .align-self-lg-baseline {\n align-self: baseline !important;\n }\n .align-self-lg-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 1200px) {\n .flex-xl-row {\n flex-direction: row !important;\n }\n .flex-xl-column {\n flex-direction: column !important;\n }\n .flex-xl-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-xl-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-xl-wrap {\n flex-wrap: wrap !important;\n }\n .flex-xl-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-xl-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-xl-fill {\n flex: 1 1 auto !important;\n }\n .flex-xl-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-xl-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-xl-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-xl-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-xl-start {\n justify-content: flex-start !important;\n }\n .justify-content-xl-end {\n justify-content: flex-end !important;\n }\n .justify-content-xl-center {\n justify-content: center !important;\n }\n .justify-content-xl-between {\n justify-content: space-between !important;\n }\n .justify-content-xl-around {\n justify-content: space-around !important;\n }\n .align-items-xl-start {\n align-items: flex-start !important;\n }\n .align-items-xl-end {\n align-items: flex-end !important;\n }\n .align-items-xl-center {\n align-items: center !important;\n }\n .align-items-xl-baseline {\n align-items: baseline !important;\n }\n .align-items-xl-stretch {\n align-items: stretch !important;\n }\n .align-content-xl-start {\n align-content: flex-start !important;\n }\n .align-content-xl-end {\n align-content: flex-end !important;\n }\n .align-content-xl-center {\n align-content: center !important;\n }\n .align-content-xl-between {\n align-content: space-between !important;\n }\n .align-content-xl-around {\n align-content: space-around !important;\n }\n .align-content-xl-stretch {\n align-content: stretch !important;\n }\n .align-self-xl-auto {\n align-self: auto !important;\n }\n .align-self-xl-start {\n align-self: flex-start !important;\n }\n .align-self-xl-end {\n align-self: flex-end !important;\n }\n .align-self-xl-center {\n align-self: center !important;\n }\n .align-self-xl-baseline {\n align-self: baseline !important;\n }\n .align-self-xl-stretch {\n align-self: stretch !important;\n }\n}\n\n/*# sourceMappingURL=bootstrap-grid.css.map */","// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n@if $enable-grid-classes {\n .container {\n @include make-container();\n @include make-container-max-widths();\n }\n}\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but with 100% width for\n// fluid, full width layouts.\n\n@if $enable-grid-classes {\n .container-fluid {\n @include make-container();\n }\n}\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n@if $enable-grid-classes {\n .row {\n @include make-row();\n }\n\n // Remove the negative margin from default .row, then the horizontal padding\n // from all immediate children columns (to prevent runaway style inheritance).\n .no-gutters {\n margin-right: 0;\n margin-left: 0;\n\n > .col,\n > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n }\n }\n}\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n@if $enable-grid-classes {\n @include make-grid-columns();\n}\n","/// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n@mixin make-container() {\n width: 100%;\n padding-right: ($grid-gutter-width / 2);\n padding-left: ($grid-gutter-width / 2);\n margin-right: auto;\n margin-left: auto;\n}\n\n\n// For each breakpoint, define the maximum width of the container in a media query\n@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) {\n @each $breakpoint, $container-max-width in $max-widths {\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n max-width: $container-max-width;\n }\n }\n}\n\n@mixin make-row() {\n display: flex;\n flex-wrap: wrap;\n margin-right: ($grid-gutter-width / -2);\n margin-left: ($grid-gutter-width / -2);\n}\n\n@mixin make-col-ready() {\n position: relative;\n // Prevent columns from becoming too narrow when at smaller grid tiers by\n // always setting `width: 100%;`. This works because we use `flex` values\n // later on to override this initial width.\n width: 100%;\n min-height: 1px; // Prevent collapsing\n padding-right: ($grid-gutter-width / 2);\n padding-left: ($grid-gutter-width / 2);\n}\n\n@mixin make-col($size, $columns: $grid-columns) {\n flex: 0 0 percentage($size / $columns);\n // Add a `max-width` to ensure content within each column does not blow out\n // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari\n // do not appear to require this.\n max-width: percentage($size / $columns);\n}\n\n@mixin make-col-offset($size, $columns: $grid-columns) {\n $num: $size / $columns;\n margin-left: if($num == 0, 0, percentage($num));\n}\n","// Breakpoint viewport sizes and media queries.\n//\n// Breakpoints are defined as a map of (name: minimum width), order from small to large:\n//\n// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)\n//\n// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.\n\n// Name of the next breakpoint, or null for the last breakpoint.\n//\n// >> breakpoint-next(sm)\n// md\n// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// md\n// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))\n// md\n@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {\n $n: index($breakpoint-names, $name);\n @return if($n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);\n}\n\n// Minimum breakpoint width. Null for the smallest (first) breakpoint.\n//\n// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 576px\n@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {\n $min: map-get($breakpoints, $name);\n @return if($min != 0, $min, null);\n}\n\n// Maximum breakpoint width. Null for the largest (last) breakpoint.\n// The maximum value is calculated as the minimum of the next one less 0.02px\n// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths.\n// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max\n// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.\n// See https://bugs.webkit.org/show_bug.cgi?id=178261\n//\n// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 767.98px\n@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {\n $next: breakpoint-next($name, $breakpoints);\n @return if($next, breakpoint-min($next, $breakpoints) - .02px, null);\n}\n\n// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.\n// Useful for making responsive utilities.\n//\n// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"\" (Returns a blank string)\n// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"-sm\"\n@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {\n @return if(breakpoint-min($name, $breakpoints) == null, \"\", \"-#{$name}\");\n}\n\n// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.\n// Makes the @content apply to the given breakpoint and wider.\n@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n @if $min {\n @media (min-width: $min) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media of at most the maximum breakpoint width. No query for the largest breakpoint.\n// Makes the @content apply to the given breakpoint and narrower.\n@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {\n $max: breakpoint-max($name, $breakpoints);\n @if $max {\n @media (max-width: $max) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media that spans multiple breakpoint widths.\n// Makes the @content apply between the min and max breakpoints\n@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($lower, $breakpoints);\n $max: breakpoint-max($upper, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($lower, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($upper, $breakpoints) {\n @content;\n }\n }\n}\n\n// Media between the breakpoint's minimum and maximum widths.\n// No minimum for the smallest breakpoint, and no maximum for the largest one.\n// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.\n@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n $max: breakpoint-max($name, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($name, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($name, $breakpoints) {\n @content;\n }\n }\n}\n","// Variables\n//\n// Variables should follow the `$component-state-property-size` formula for\n// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs.\n\n\n//\n// Color system\n//\n\n$white: #fff !default;\n$gray-100: #f8f9fa !default;\n$gray-200: #e9ecef !default;\n$gray-300: #dee2e6 !default;\n$gray-400: #ced4da !default;\n$gray-500: #adb5bd !default;\n$gray-600: #6c757d !default;\n$gray-700: #495057 !default;\n$gray-800: #343a40 !default;\n$gray-900: #212529 !default;\n$black: #000 !default;\n\n$grays: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$grays: map-merge(\n (\n \"100\": $gray-100,\n \"200\": $gray-200,\n \"300\": $gray-300,\n \"400\": $gray-400,\n \"500\": $gray-500,\n \"600\": $gray-600,\n \"700\": $gray-700,\n \"800\": $gray-800,\n \"900\": $gray-900\n ),\n $grays\n);\n\n\n$blue: #007bff !default;\n$indigo: #6610f2 !default;\n$purple: #6f42c1 !default;\n$pink: #e83e8c !default;\n$red: #dc3545 !default;\n$orange: #fd7e14 !default;\n$yellow: #ffc107 !default;\n$green: #28a745 !default;\n$teal: #20c997 !default;\n$cyan: #17a2b8 !default;\n\n$colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$colors: map-merge(\n (\n \"blue\": $blue,\n \"indigo\": $indigo,\n \"purple\": $purple,\n \"pink\": $pink,\n \"red\": $red,\n \"orange\": $orange,\n \"yellow\": $yellow,\n \"green\": $green,\n \"teal\": $teal,\n \"cyan\": $cyan,\n \"white\": $white,\n \"gray\": $gray-600,\n \"gray-dark\": $gray-800\n ),\n $colors\n);\n\n$primary: $blue !default;\n$secondary: $gray-600 !default;\n$success: $green !default;\n$info: $cyan !default;\n$warning: $yellow !default;\n$danger: $red !default;\n$light: $gray-100 !default;\n$dark: $gray-800 !default;\n\n$theme-colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$theme-colors: map-merge(\n (\n \"primary\": $primary,\n \"secondary\": $secondary,\n \"success\": $success,\n \"info\": $info,\n \"warning\": $warning,\n \"danger\": $danger,\n \"light\": $light,\n \"dark\": $dark\n ),\n $theme-colors\n);\n\n// Set a specific jump point for requesting color jumps\n$theme-color-interval: 8% !default;\n\n// The yiq lightness value that determines when the lightness of color changes from \"dark\" to \"light\". Acceptable values are between 0 and 255.\n$yiq-contrasted-threshold: 150 !default;\n\n// Customize the light and dark text colors for use in our YIQ color contrast function.\n$yiq-text-dark: $gray-900 !default;\n$yiq-text-light: $white !default;\n\n// Options\n//\n// Quickly modify global styling by enabling or disabling optional features.\n\n$enable-caret: true !default;\n$enable-rounded: true !default;\n$enable-shadows: false !default;\n$enable-gradients: false !default;\n$enable-transitions: true !default;\n$enable-hover-media-query: false !default; // Deprecated, no longer affects any compiled CSS\n$enable-grid-classes: true !default;\n$enable-print-styles: true !default;\n\n\n// Spacing\n//\n// Control the default styling of most Bootstrap elements by modifying these\n// variables. Mostly focused on spacing.\n// You can add more entries to the $spacers map, should you need more variation.\n\n$spacer: 1rem !default;\n$spacers: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$spacers: map-merge(\n (\n 0: 0,\n 1: ($spacer * .25),\n 2: ($spacer * .5),\n 3: $spacer,\n 4: ($spacer * 1.5),\n 5: ($spacer * 3)\n ),\n $spacers\n);\n\n// This variable affects the `.h-*` and `.w-*` classes.\n$sizes: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$sizes: map-merge(\n (\n 25: 25%,\n 50: 50%,\n 75: 75%,\n 100: 100%,\n auto: auto\n ),\n $sizes\n);\n\n// Body\n//\n// Settings for the `` element.\n\n$body-bg: $white !default;\n$body-color: $gray-900 !default;\n\n// Links\n//\n// Style anchor elements.\n\n$link-color: theme-color(\"primary\") !default;\n$link-decoration: none !default;\n$link-hover-color: darken($link-color, 15%) !default;\n$link-hover-decoration: underline !default;\n\n// Paragraphs\n//\n// Style p element.\n\n$paragraph-margin-bottom: 1rem !default;\n\n\n// Grid breakpoints\n//\n// Define the minimum dimensions at which your layout will change,\n// adapting to different screen sizes, for use in media queries.\n\n$grid-breakpoints: (\n xs: 0,\n sm: 576px,\n md: 768px,\n lg: 992px,\n xl: 1200px\n) !default;\n\n@include _assert-ascending($grid-breakpoints, \"$grid-breakpoints\");\n@include _assert-starts-at-zero($grid-breakpoints);\n\n\n// Grid containers\n//\n// Define the maximum width of `.container` for different screen sizes.\n\n$container-max-widths: (\n sm: 540px,\n md: 720px,\n lg: 960px,\n xl: 1140px\n) !default;\n\n@include _assert-ascending($container-max-widths, \"$container-max-widths\");\n\n\n// Grid columns\n//\n// Set the number of columns and specify the width of the gutters.\n\n$grid-columns: 12 !default;\n$grid-gutter-width: 30px !default;\n\n// Components\n//\n// Define common padding and border radius sizes and more.\n\n$line-height-lg: 1.5 !default;\n$line-height-sm: 1.5 !default;\n\n$border-width: 1px !default;\n$border-color: $gray-300 !default;\n\n$border-radius: .25rem !default;\n$border-radius-lg: .3rem !default;\n$border-radius-sm: .2rem !default;\n\n$box-shadow-sm: 0 .125rem .25rem rgba($black, .075) !default;\n$box-shadow: 0 .5rem 1rem rgba($black, .15) !default;\n$box-shadow-lg: 0 1rem 3rem rgba($black, .175) !default;\n\n$component-active-color: $white !default;\n$component-active-bg: theme-color(\"primary\") !default;\n\n$caret-width: .3em !default;\n\n$transition-base: all .2s ease-in-out !default;\n$transition-fade: opacity .15s linear !default;\n$transition-collapse: height .35s ease !default;\n\n\n// Fonts\n//\n// Font, line-height, and color for body text, headings, and more.\n\n// stylelint-disable value-keyword-case\n$font-family-sans-serif: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\" !default;\n$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace !default;\n$font-family-base: $font-family-sans-serif !default;\n// stylelint-enable value-keyword-case\n\n$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`\n$font-size-lg: ($font-size-base * 1.25) !default;\n$font-size-sm: ($font-size-base * .875) !default;\n\n$font-weight-light: 300 !default;\n$font-weight-normal: 400 !default;\n$font-weight-bold: 700 !default;\n\n$font-weight-base: $font-weight-normal !default;\n$line-height-base: 1.5 !default;\n\n$h1-font-size: $font-size-base * 2.5 !default;\n$h2-font-size: $font-size-base * 2 !default;\n$h3-font-size: $font-size-base * 1.75 !default;\n$h4-font-size: $font-size-base * 1.5 !default;\n$h5-font-size: $font-size-base * 1.25 !default;\n$h6-font-size: $font-size-base !default;\n\n$headings-margin-bottom: ($spacer / 2) !default;\n$headings-font-family: inherit !default;\n$headings-font-weight: 500 !default;\n$headings-line-height: 1.2 !default;\n$headings-color: inherit !default;\n\n$display1-size: 6rem !default;\n$display2-size: 5.5rem !default;\n$display3-size: 4.5rem !default;\n$display4-size: 3.5rem !default;\n\n$display1-weight: 300 !default;\n$display2-weight: 300 !default;\n$display3-weight: 300 !default;\n$display4-weight: 300 !default;\n$display-line-height: $headings-line-height !default;\n\n$lead-font-size: ($font-size-base * 1.25) !default;\n$lead-font-weight: 300 !default;\n\n$small-font-size: 80% !default;\n\n$text-muted: $gray-600 !default;\n\n$blockquote-small-color: $gray-600 !default;\n$blockquote-font-size: ($font-size-base * 1.25) !default;\n\n$hr-border-color: rgba($black, .1) !default;\n$hr-border-width: $border-width !default;\n\n$mark-padding: .2em !default;\n\n$dt-font-weight: $font-weight-bold !default;\n\n$kbd-box-shadow: inset 0 -.1rem 0 rgba($black, .25) !default;\n$nested-kbd-font-weight: $font-weight-bold !default;\n\n$list-inline-padding: .5rem !default;\n\n$mark-bg: #fcf8e3 !default;\n\n$hr-margin-y: $spacer !default;\n\n\n// Tables\n//\n// Customizes the `.table` component with basic values, each used across all table variations.\n\n$table-cell-padding: .75rem !default;\n$table-cell-padding-sm: .3rem !default;\n\n$table-bg: transparent !default;\n$table-accent-bg: rgba($black, .05) !default;\n$table-hover-bg: rgba($black, .075) !default;\n$table-active-bg: $table-hover-bg !default;\n\n$table-border-width: $border-width !default;\n$table-border-color: $gray-300 !default;\n\n$table-head-bg: $gray-200 !default;\n$table-head-color: $gray-700 !default;\n\n$table-dark-bg: $gray-900 !default;\n$table-dark-accent-bg: rgba($white, .05) !default;\n$table-dark-hover-bg: rgba($white, .075) !default;\n$table-dark-border-color: lighten($gray-900, 7.5%) !default;\n$table-dark-color: $body-bg !default;\n\n$table-striped-order: odd !default;\n\n$table-caption-color: $text-muted !default;\n\n// Buttons + Forms\n//\n// Shared variables that are reassigned to `$input-` and `$btn-` specific variables.\n\n$input-btn-padding-y: .375rem !default;\n$input-btn-padding-x: .75rem !default;\n$input-btn-line-height: $line-height-base !default;\n\n$input-btn-focus-width: .2rem !default;\n$input-btn-focus-color: rgba($component-active-bg, .25) !default;\n$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default;\n\n$input-btn-padding-y-sm: .25rem !default;\n$input-btn-padding-x-sm: .5rem !default;\n$input-btn-line-height-sm: $line-height-sm !default;\n\n$input-btn-padding-y-lg: .5rem !default;\n$input-btn-padding-x-lg: 1rem !default;\n$input-btn-line-height-lg: $line-height-lg !default;\n\n$input-btn-border-width: $border-width !default;\n\n\n// Buttons\n//\n// For each of Bootstrap's buttons, define text, background, and border color.\n\n$btn-padding-y: $input-btn-padding-y !default;\n$btn-padding-x: $input-btn-padding-x !default;\n$btn-line-height: $input-btn-line-height !default;\n\n$btn-padding-y-sm: $input-btn-padding-y-sm !default;\n$btn-padding-x-sm: $input-btn-padding-x-sm !default;\n$btn-line-height-sm: $input-btn-line-height-sm !default;\n\n$btn-padding-y-lg: $input-btn-padding-y-lg !default;\n$btn-padding-x-lg: $input-btn-padding-x-lg !default;\n$btn-line-height-lg: $input-btn-line-height-lg !default;\n\n$btn-border-width: $input-btn-border-width !default;\n\n$btn-font-weight: $font-weight-normal !default;\n$btn-box-shadow: inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default;\n$btn-focus-width: $input-btn-focus-width !default;\n$btn-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$btn-disabled-opacity: .65 !default;\n$btn-active-box-shadow: inset 0 3px 5px rgba($black, .125) !default;\n\n$btn-link-disabled-color: $gray-600 !default;\n\n$btn-block-spacing-y: .5rem !default;\n\n// Allows for customizing button radius independently from global border radius\n$btn-border-radius: $border-radius !default;\n$btn-border-radius-lg: $border-radius-lg !default;\n$btn-border-radius-sm: $border-radius-sm !default;\n\n$btn-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n\n// Forms\n\n$label-margin-bottom: .5rem !default;\n\n$input-padding-y: $input-btn-padding-y !default;\n$input-padding-x: $input-btn-padding-x !default;\n$input-line-height: $input-btn-line-height !default;\n\n$input-padding-y-sm: $input-btn-padding-y-sm !default;\n$input-padding-x-sm: $input-btn-padding-x-sm !default;\n$input-line-height-sm: $input-btn-line-height-sm !default;\n\n$input-padding-y-lg: $input-btn-padding-y-lg !default;\n$input-padding-x-lg: $input-btn-padding-x-lg !default;\n$input-line-height-lg: $input-btn-line-height-lg !default;\n\n$input-bg: $white !default;\n$input-disabled-bg: $gray-200 !default;\n\n$input-color: $gray-700 !default;\n$input-border-color: $gray-400 !default;\n$input-border-width: $input-btn-border-width !default;\n$input-box-shadow: inset 0 1px 1px rgba($black, .075) !default;\n\n$input-border-radius: $border-radius !default;\n$input-border-radius-lg: $border-radius-lg !default;\n$input-border-radius-sm: $border-radius-sm !default;\n\n$input-focus-bg: $input-bg !default;\n$input-focus-border-color: lighten($component-active-bg, 25%) !default;\n$input-focus-color: $input-color !default;\n$input-focus-width: $input-btn-focus-width !default;\n$input-focus-box-shadow: $input-btn-focus-box-shadow !default;\n\n$input-placeholder-color: $gray-600 !default;\n$input-plaintext-color: $body-color !default;\n\n$input-height-border: $input-border-width * 2 !default;\n\n$input-height-inner: ($font-size-base * $input-btn-line-height) + ($input-btn-padding-y * 2) !default;\n$input-height: calc(#{$input-height-inner} + #{$input-height-border}) !default;\n\n$input-height-inner-sm: ($font-size-sm * $input-btn-line-height-sm) + ($input-btn-padding-y-sm * 2) !default;\n$input-height-sm: calc(#{$input-height-inner-sm} + #{$input-height-border}) !default;\n\n$input-height-inner-lg: ($font-size-lg * $input-btn-line-height-lg) + ($input-btn-padding-y-lg * 2) !default;\n$input-height-lg: calc(#{$input-height-inner-lg} + #{$input-height-border}) !default;\n\n$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$form-text-margin-top: .25rem !default;\n\n$form-check-input-gutter: 1.25rem !default;\n$form-check-input-margin-y: .3rem !default;\n$form-check-input-margin-x: .25rem !default;\n\n$form-check-inline-margin-x: .75rem !default;\n$form-check-inline-input-margin-x: .3125rem !default;\n\n$form-group-margin-bottom: 1rem !default;\n\n$input-group-addon-color: $input-color !default;\n$input-group-addon-bg: $gray-200 !default;\n$input-group-addon-border-color: $input-border-color !default;\n\n$custom-forms-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$custom-control-gutter: 1.5rem !default;\n$custom-control-spacer-x: 1rem !default;\n\n$custom-control-indicator-size: 1rem !default;\n$custom-control-indicator-bg: $gray-300 !default;\n$custom-control-indicator-bg-size: 50% 50% !default;\n$custom-control-indicator-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;\n\n$custom-control-indicator-disabled-bg: $gray-200 !default;\n$custom-control-label-disabled-color: $gray-600 !default;\n\n$custom-control-indicator-checked-color: $component-active-color !default;\n$custom-control-indicator-checked-bg: $component-active-bg !default;\n$custom-control-indicator-checked-disabled-bg: rgba(theme-color(\"primary\"), .5) !default;\n$custom-control-indicator-checked-box-shadow: none !default;\n\n$custom-control-indicator-focus-box-shadow: 0 0 0 1px $body-bg, $input-btn-focus-box-shadow !default;\n\n$custom-control-indicator-active-color: $component-active-color !default;\n$custom-control-indicator-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-control-indicator-active-box-shadow: none !default;\n\n$custom-checkbox-indicator-border-radius: $border-radius !default;\n$custom-checkbox-indicator-icon-checked: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n\n$custom-checkbox-indicator-indeterminate-bg: $component-active-bg !default;\n$custom-checkbox-indicator-indeterminate-color: $custom-control-indicator-checked-color !default;\n$custom-checkbox-indicator-icon-indeterminate: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$custom-checkbox-indicator-indeterminate-box-shadow: none !default;\n\n$custom-radio-indicator-border-radius: 50% !default;\n$custom-radio-indicator-icon-checked: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='#{$custom-control-indicator-checked-color}'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n\n$custom-select-padding-y: .375rem !default;\n$custom-select-padding-x: .75rem !default;\n$custom-select-height: $input-height !default;\n$custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator\n$custom-select-line-height: $input-btn-line-height !default;\n$custom-select-color: $input-color !default;\n$custom-select-disabled-color: $gray-600 !default;\n$custom-select-bg: $input-bg !default;\n$custom-select-disabled-bg: $gray-200 !default;\n$custom-select-bg-size: 8px 10px !default; // In pixels because image dimensions\n$custom-select-indicator-color: $gray-800 !default;\n$custom-select-indicator: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$custom-select-border-width: $input-btn-border-width !default;\n$custom-select-border-color: $input-border-color !default;\n$custom-select-border-radius: $border-radius !default;\n$custom-select-box-shadow: inset 0 1px 2px rgba($black, .075) !default;\n\n$custom-select-focus-border-color: $input-focus-border-color !default;\n$custom-select-focus-width: $input-btn-focus-width !default;\n$custom-select-focus-box-shadow: 0 0 0 $custom-select-focus-width rgba($custom-select-focus-border-color, .5) !default;\n\n$custom-select-font-size-sm: 75% !default;\n$custom-select-height-sm: $input-height-sm !default;\n\n$custom-select-font-size-lg: 125% !default;\n$custom-select-height-lg: $input-height-lg !default;\n\n$custom-range-track-width: 100% !default;\n$custom-range-track-height: .5rem !default;\n$custom-range-track-cursor: pointer !default;\n$custom-range-track-bg: $gray-300 !default;\n$custom-range-track-border-radius: 1rem !default;\n$custom-range-track-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;\n\n$custom-range-thumb-width: 1rem !default;\n$custom-range-thumb-height: $custom-range-thumb-width !default;\n$custom-range-thumb-bg: $component-active-bg !default;\n$custom-range-thumb-border: 0 !default;\n$custom-range-thumb-border-radius: 1rem !default;\n$custom-range-thumb-box-shadow: 0 .1rem .25rem rgba($black, .1) !default;\n$custom-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-btn-focus-box-shadow !default;\n$custom-range-thumb-focus-box-shadow-width: $input-btn-focus-width !default; // For focus box shadow issue in IE/Edge\n$custom-range-thumb-active-bg: lighten($component-active-bg, 35%) !default;\n\n$custom-file-height: $input-height !default;\n$custom-file-height-inner: $input-height-inner !default;\n$custom-file-focus-border-color: $input-focus-border-color !default;\n$custom-file-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$custom-file-disabled-bg: $input-disabled-bg !default;\n\n$custom-file-padding-y: $input-btn-padding-y !default;\n$custom-file-padding-x: $input-btn-padding-x !default;\n$custom-file-line-height: $input-btn-line-height !default;\n$custom-file-color: $input-color !default;\n$custom-file-bg: $input-bg !default;\n$custom-file-border-width: $input-btn-border-width !default;\n$custom-file-border-color: $input-border-color !default;\n$custom-file-border-radius: $input-border-radius !default;\n$custom-file-box-shadow: $input-box-shadow !default;\n$custom-file-button-color: $custom-file-color !default;\n$custom-file-button-bg: $input-group-addon-bg !default;\n$custom-file-text: (\n en: \"Browse\"\n) !default;\n\n\n// Form validation\n$form-feedback-margin-top: $form-text-margin-top !default;\n$form-feedback-font-size: $small-font-size !default;\n$form-feedback-valid-color: theme-color(\"success\") !default;\n$form-feedback-invalid-color: theme-color(\"danger\") !default;\n\n\n// Dropdowns\n//\n// Dropdown menu container and contents.\n\n$dropdown-min-width: 10rem !default;\n$dropdown-padding-y: .5rem !default;\n$dropdown-spacer: .125rem !default;\n$dropdown-bg: $white !default;\n$dropdown-border-color: rgba($black, .15) !default;\n$dropdown-border-radius: $border-radius !default;\n$dropdown-border-width: $border-width !default;\n$dropdown-divider-bg: $gray-200 !default;\n$dropdown-box-shadow: 0 .5rem 1rem rgba($black, .175) !default;\n\n$dropdown-link-color: $gray-900 !default;\n$dropdown-link-hover-color: darken($gray-900, 5%) !default;\n$dropdown-link-hover-bg: $gray-100 !default;\n\n$dropdown-link-active-color: $component-active-color !default;\n$dropdown-link-active-bg: $component-active-bg !default;\n\n$dropdown-link-disabled-color: $gray-600 !default;\n\n$dropdown-item-padding-y: .25rem !default;\n$dropdown-item-padding-x: 1.5rem !default;\n\n$dropdown-header-color: $gray-600 !default;\n\n\n// Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n\n$zindex-dropdown: 1000 !default;\n$zindex-sticky: 1020 !default;\n$zindex-fixed: 1030 !default;\n$zindex-modal-backdrop: 1040 !default;\n$zindex-modal: 1050 !default;\n$zindex-popover: 1060 !default;\n$zindex-tooltip: 1070 !default;\n\n// Navs\n\n$nav-link-padding-y: .5rem !default;\n$nav-link-padding-x: 1rem !default;\n$nav-link-disabled-color: $gray-600 !default;\n\n$nav-tabs-border-color: $gray-300 !default;\n$nav-tabs-border-width: $border-width !default;\n$nav-tabs-border-radius: $border-radius !default;\n$nav-tabs-link-hover-border-color: $gray-200 $gray-200 $nav-tabs-border-color !default;\n$nav-tabs-link-active-color: $gray-700 !default;\n$nav-tabs-link-active-bg: $body-bg !default;\n$nav-tabs-link-active-border-color: $gray-300 $gray-300 $nav-tabs-link-active-bg !default;\n\n$nav-pills-border-radius: $border-radius !default;\n$nav-pills-link-active-color: $component-active-color !default;\n$nav-pills-link-active-bg: $component-active-bg !default;\n\n$nav-divider-color: $gray-200 !default;\n$nav-divider-margin-y: ($spacer / 2) !default;\n\n// Navbar\n\n$navbar-padding-y: ($spacer / 2) !default;\n$navbar-padding-x: $spacer !default;\n\n$navbar-nav-link-padding-x: .5rem !default;\n\n$navbar-brand-font-size: $font-size-lg !default;\n// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link\n$nav-link-height: ($font-size-base * $line-height-base + $nav-link-padding-y * 2) !default;\n$navbar-brand-height: $navbar-brand-font-size * $line-height-base !default;\n$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) / 2 !default;\n\n$navbar-toggler-padding-y: .25rem !default;\n$navbar-toggler-padding-x: .75rem !default;\n$navbar-toggler-font-size: $font-size-lg !default;\n$navbar-toggler-border-radius: $btn-border-radius !default;\n\n$navbar-dark-color: rgba($white, .5) !default;\n$navbar-dark-hover-color: rgba($white, .75) !default;\n$navbar-dark-active-color: $white !default;\n$navbar-dark-disabled-color: rgba($white, .25) !default;\n$navbar-dark-toggler-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$navbar-dark-toggler-border-color: rgba($white, .1) !default;\n\n$navbar-light-color: rgba($black, .5) !default;\n$navbar-light-hover-color: rgba($black, .7) !default;\n$navbar-light-active-color: rgba($black, .9) !default;\n$navbar-light-disabled-color: rgba($black, .3) !default;\n$navbar-light-toggler-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$navbar-light-toggler-border-color: rgba($black, .1) !default;\n\n// Pagination\n\n$pagination-padding-y: .5rem !default;\n$pagination-padding-x: .75rem !default;\n$pagination-padding-y-sm: .25rem !default;\n$pagination-padding-x-sm: .5rem !default;\n$pagination-padding-y-lg: .75rem !default;\n$pagination-padding-x-lg: 1.5rem !default;\n$pagination-line-height: 1.25 !default;\n\n$pagination-color: $link-color !default;\n$pagination-bg: $white !default;\n$pagination-border-width: $border-width !default;\n$pagination-border-color: $gray-300 !default;\n\n$pagination-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$pagination-focus-outline: 0 !default;\n\n$pagination-hover-color: $link-hover-color !default;\n$pagination-hover-bg: $gray-200 !default;\n$pagination-hover-border-color: $gray-300 !default;\n\n$pagination-active-color: $component-active-color !default;\n$pagination-active-bg: $component-active-bg !default;\n$pagination-active-border-color: $pagination-active-bg !default;\n\n$pagination-disabled-color: $gray-600 !default;\n$pagination-disabled-bg: $white !default;\n$pagination-disabled-border-color: $gray-300 !default;\n\n\n// Jumbotron\n\n$jumbotron-padding: 2rem !default;\n$jumbotron-bg: $gray-200 !default;\n\n\n// Cards\n\n$card-spacer-y: .75rem !default;\n$card-spacer-x: 1.25rem !default;\n$card-border-width: $border-width !default;\n$card-border-radius: $border-radius !default;\n$card-border-color: rgba($black, .125) !default;\n$card-inner-border-radius: calc(#{$card-border-radius} - #{$card-border-width}) !default;\n$card-cap-bg: rgba($black, .03) !default;\n$card-bg: $white !default;\n\n$card-img-overlay-padding: 1.25rem !default;\n\n$card-group-margin: ($grid-gutter-width / 2) !default;\n$card-deck-margin: $card-group-margin !default;\n\n$card-columns-count: 3 !default;\n$card-columns-gap: 1.25rem !default;\n$card-columns-margin: $card-spacer-y !default;\n\n\n// Tooltips\n\n$tooltip-font-size: $font-size-sm !default;\n$tooltip-max-width: 200px !default;\n$tooltip-color: $white !default;\n$tooltip-bg: $black !default;\n$tooltip-border-radius: $border-radius !default;\n$tooltip-opacity: .9 !default;\n$tooltip-padding-y: .25rem !default;\n$tooltip-padding-x: .5rem !default;\n$tooltip-margin: 0 !default;\n\n$tooltip-arrow-width: .8rem !default;\n$tooltip-arrow-height: .4rem !default;\n$tooltip-arrow-color: $tooltip-bg !default;\n\n\n// Popovers\n\n$popover-font-size: $font-size-sm !default;\n$popover-bg: $white !default;\n$popover-max-width: 276px !default;\n$popover-border-width: $border-width !default;\n$popover-border-color: rgba($black, .2) !default;\n$popover-border-radius: $border-radius-lg !default;\n$popover-box-shadow: 0 .25rem .5rem rgba($black, .2) !default;\n\n$popover-header-bg: darken($popover-bg, 3%) !default;\n$popover-header-color: $headings-color !default;\n$popover-header-padding-y: .5rem !default;\n$popover-header-padding-x: .75rem !default;\n\n$popover-body-color: $body-color !default;\n$popover-body-padding-y: $popover-header-padding-y !default;\n$popover-body-padding-x: $popover-header-padding-x !default;\n\n$popover-arrow-width: 1rem !default;\n$popover-arrow-height: .5rem !default;\n$popover-arrow-color: $popover-bg !default;\n\n$popover-arrow-outer-color: fade-in($popover-border-color, .05) !default;\n\n\n// Badges\n\n$badge-font-size: 75% !default;\n$badge-font-weight: $font-weight-bold !default;\n$badge-padding-y: .25em !default;\n$badge-padding-x: .4em !default;\n$badge-border-radius: $border-radius !default;\n\n$badge-pill-padding-x: .6em !default;\n// Use a higher than normal value to ensure completely rounded edges when\n// customizing padding or font-size on labels.\n$badge-pill-border-radius: 10rem !default;\n\n\n// Modals\n\n// Padding applied to the modal body\n$modal-inner-padding: 1rem !default;\n\n$modal-dialog-margin: .5rem !default;\n$modal-dialog-margin-y-sm-up: 1.75rem !default;\n\n$modal-title-line-height: $line-height-base !default;\n\n$modal-content-bg: $white !default;\n$modal-content-border-color: rgba($black, .2) !default;\n$modal-content-border-width: $border-width !default;\n$modal-content-border-radius: $border-radius-lg !default;\n$modal-content-box-shadow-xs: 0 .25rem .5rem rgba($black, .5) !default;\n$modal-content-box-shadow-sm-up: 0 .5rem 1rem rgba($black, .5) !default;\n\n$modal-backdrop-bg: $black !default;\n$modal-backdrop-opacity: .5 !default;\n$modal-header-border-color: $gray-200 !default;\n$modal-footer-border-color: $modal-header-border-color !default;\n$modal-header-border-width: $modal-content-border-width !default;\n$modal-footer-border-width: $modal-header-border-width !default;\n$modal-header-padding: 1rem !default;\n\n$modal-lg: 800px !default;\n$modal-md: 500px !default;\n$modal-sm: 300px !default;\n\n$modal-transition: transform .3s ease-out !default;\n\n\n// Alerts\n//\n// Define alert colors, border radius, and padding.\n\n$alert-padding-y: .75rem !default;\n$alert-padding-x: 1.25rem !default;\n$alert-margin-bottom: 1rem !default;\n$alert-border-radius: $border-radius !default;\n$alert-link-font-weight: $font-weight-bold !default;\n$alert-border-width: $border-width !default;\n\n$alert-bg-level: -10 !default;\n$alert-border-level: -9 !default;\n$alert-color-level: 6 !default;\n\n\n// Progress bars\n\n$progress-height: 1rem !default;\n$progress-font-size: ($font-size-base * .75) !default;\n$progress-bg: $gray-200 !default;\n$progress-border-radius: $border-radius !default;\n$progress-box-shadow: inset 0 .1rem .1rem rgba($black, .1) !default;\n$progress-bar-color: $white !default;\n$progress-bar-bg: theme-color(\"primary\") !default;\n$progress-bar-animation-timing: 1s linear infinite !default;\n$progress-bar-transition: width .6s ease !default;\n\n// List group\n\n$list-group-bg: $white !default;\n$list-group-border-color: rgba($black, .125) !default;\n$list-group-border-width: $border-width !default;\n$list-group-border-radius: $border-radius !default;\n\n$list-group-item-padding-y: .75rem !default;\n$list-group-item-padding-x: 1.25rem !default;\n\n$list-group-hover-bg: $gray-100 !default;\n$list-group-active-color: $component-active-color !default;\n$list-group-active-bg: $component-active-bg !default;\n$list-group-active-border-color: $list-group-active-bg !default;\n\n$list-group-disabled-color: $gray-600 !default;\n$list-group-disabled-bg: $list-group-bg !default;\n\n$list-group-action-color: $gray-700 !default;\n$list-group-action-hover-color: $list-group-action-color !default;\n\n$list-group-action-active-color: $body-color !default;\n$list-group-action-active-bg: $gray-200 !default;\n\n\n// Image thumbnails\n\n$thumbnail-padding: .25rem !default;\n$thumbnail-bg: $body-bg !default;\n$thumbnail-border-width: $border-width !default;\n$thumbnail-border-color: $gray-300 !default;\n$thumbnail-border-radius: $border-radius !default;\n$thumbnail-box-shadow: 0 1px 2px rgba($black, .075) !default;\n\n\n// Figures\n\n$figure-caption-font-size: 90% !default;\n$figure-caption-color: $gray-600 !default;\n\n\n// Breadcrumbs\n\n$breadcrumb-padding-y: .75rem !default;\n$breadcrumb-padding-x: 1rem !default;\n$breadcrumb-item-padding: .5rem !default;\n\n$breadcrumb-margin-bottom: 1rem !default;\n\n$breadcrumb-bg: $gray-200 !default;\n$breadcrumb-divider-color: $gray-600 !default;\n$breadcrumb-active-color: $gray-600 !default;\n$breadcrumb-divider: quote(\"/\") !default;\n\n$breadcrumb-border-radius: $border-radius !default;\n\n\n// Carousel\n\n$carousel-control-color: $white !default;\n$carousel-control-width: 15% !default;\n$carousel-control-opacity: .5 !default;\n\n$carousel-indicator-width: 30px !default;\n$carousel-indicator-height: 3px !default;\n$carousel-indicator-spacer: 3px !default;\n$carousel-indicator-active-bg: $white !default;\n\n$carousel-caption-width: 70% !default;\n$carousel-caption-color: $white !default;\n\n$carousel-control-icon-width: 20px !default;\n\n$carousel-control-prev-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$carousel-control-next-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n\n$carousel-transition: transform .6s ease !default; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)\n\n\n// Close\n\n$close-font-size: $font-size-base * 1.5 !default;\n$close-font-weight: $font-weight-bold !default;\n$close-color: $black !default;\n$close-text-shadow: 0 1px 0 $white !default;\n\n// Code\n\n$code-font-size: 87.5% !default;\n$code-color: $pink !default;\n\n$kbd-padding-y: .2rem !default;\n$kbd-padding-x: .4rem !default;\n$kbd-font-size: $code-font-size !default;\n$kbd-color: $white !default;\n$kbd-bg: $gray-900 !default;\n\n$pre-color: $gray-900 !default;\n$pre-scrollable-max-height: 340px !default;\n\n\n// Printing\n$print-page-size: a3 !default;\n$print-body-min-width: map-get($grid-breakpoints, \"lg\") !default;\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `$grid-columns`.\n\n@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {\n // Common properties for all breakpoints\n %grid-column {\n position: relative;\n width: 100%;\n min-height: 1px; // Prevent columns from collapsing when empty\n padding-right: ($gutter / 2);\n padding-left: ($gutter / 2);\n }\n\n @each $breakpoint in map-keys($breakpoints) {\n $infix: breakpoint-infix($breakpoint, $breakpoints);\n\n // Allow columns to stretch full width below their breakpoints\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @extend %grid-column;\n }\n }\n .col#{$infix},\n .col#{$infix}-auto {\n @extend %grid-column;\n }\n\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n // Provide basic `.col-{bp}` classes for equal-width flexbox columns\n .col#{$infix} {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col#{$infix}-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none; // Reset earlier grid tiers\n }\n\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @include make-col($i, $columns);\n }\n }\n\n .order#{$infix}-first { order: -1; }\n\n .order#{$infix}-last { order: $columns + 1; }\n\n @for $i from 0 through $columns {\n .order#{$infix}-#{$i} { order: $i; }\n }\n\n // `$columns - 1` because offsetting by the width of an entire row isn't possible\n @for $i from 0 through ($columns - 1) {\n @if not ($infix == \"\" and $i == 0) { // Avoid emitting useless .offset-0\n .offset#{$infix}-#{$i} {\n @include make-col-offset($i, $columns);\n }\n }\n }\n }\n }\n}\n","// stylelint-disable declaration-no-important\n\n//\n// Utilities for common `display` values\n//\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n .d#{$infix}-none { display: none !important; }\n .d#{$infix}-inline { display: inline !important; }\n .d#{$infix}-inline-block { display: inline-block !important; }\n .d#{$infix}-block { display: block !important; }\n .d#{$infix}-table { display: table !important; }\n .d#{$infix}-table-row { display: table-row !important; }\n .d#{$infix}-table-cell { display: table-cell !important; }\n .d#{$infix}-flex { display: flex !important; }\n .d#{$infix}-inline-flex { display: inline-flex !important; }\n }\n}\n\n\n//\n// Utilities for toggling `display` in print\n//\n\n@media print {\n .d-print-none { display: none !important; }\n .d-print-inline { display: inline !important; }\n .d-print-inline-block { display: inline-block !important; }\n .d-print-block { display: block !important; }\n .d-print-table { display: table !important; }\n .d-print-table-row { display: table-row !important; }\n .d-print-table-cell { display: table-cell !important; }\n .d-print-flex { display: flex !important; }\n .d-print-inline-flex { display: inline-flex !important; }\n}\n","// stylelint-disable declaration-no-important\n\n// Flex variation\n//\n// Custom styles for additional flex alignment options.\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n .flex#{$infix}-row { flex-direction: row !important; }\n .flex#{$infix}-column { flex-direction: column !important; }\n .flex#{$infix}-row-reverse { flex-direction: row-reverse !important; }\n .flex#{$infix}-column-reverse { flex-direction: column-reverse !important; }\n\n .flex#{$infix}-wrap { flex-wrap: wrap !important; }\n .flex#{$infix}-nowrap { flex-wrap: nowrap !important; }\n .flex#{$infix}-wrap-reverse { flex-wrap: wrap-reverse !important; }\n .flex#{$infix}-fill { flex: 1 1 auto !important; }\n .flex#{$infix}-grow-0 { flex-grow: 0 !important; }\n .flex#{$infix}-grow-1 { flex-grow: 1 !important; }\n .flex#{$infix}-shrink-0 { flex-shrink: 0 !important; }\n .flex#{$infix}-shrink-1 { flex-shrink: 1 !important; }\n\n .justify-content#{$infix}-start { justify-content: flex-start !important; }\n .justify-content#{$infix}-end { justify-content: flex-end !important; }\n .justify-content#{$infix}-center { justify-content: center !important; }\n .justify-content#{$infix}-between { justify-content: space-between !important; }\n .justify-content#{$infix}-around { justify-content: space-around !important; }\n\n .align-items#{$infix}-start { align-items: flex-start !important; }\n .align-items#{$infix}-end { align-items: flex-end !important; }\n .align-items#{$infix}-center { align-items: center !important; }\n .align-items#{$infix}-baseline { align-items: baseline !important; }\n .align-items#{$infix}-stretch { align-items: stretch !important; }\n\n .align-content#{$infix}-start { align-content: flex-start !important; }\n .align-content#{$infix}-end { align-content: flex-end !important; }\n .align-content#{$infix}-center { align-content: center !important; }\n .align-content#{$infix}-between { align-content: space-between !important; }\n .align-content#{$infix}-around { align-content: space-around !important; }\n .align-content#{$infix}-stretch { align-content: stretch !important; }\n\n .align-self#{$infix}-auto { align-self: auto !important; }\n .align-self#{$infix}-start { align-self: flex-start !important; }\n .align-self#{$infix}-end { align-self: flex-end !important; }\n .align-self#{$infix}-center { align-self: center !important; }\n .align-self#{$infix}-baseline { align-self: baseline !important; }\n .align-self#{$infix}-stretch { align-self: stretch !important; }\n }\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../../scss/bootstrap-grid.scss","bootstrap-grid.css","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_breakpoints.scss","../../scss/_variables.scss","../../scss/mixins/_grid-framework.scss","../../scss/utilities/_display.scss","../../scss/utilities/_flex.scss","../../scss/utilities/_spacing.scss"],"names":[],"mappings":"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vBQ;IHTR,gBAA8C;EF4vB9C;EKnvBQ;IHTR,uBAA8C;EF+vB9C;EKtvBQ;IHTR,uBAA8C;EFkwB9C;EKzvBQ;IHTR,gBAA8C;EFqwB9C;EK5vBQ;IHTR,uBAA8C;EFwwB9C;EK/vBQ;IHTR,uBAA8C;EF2wB9C;AACF;;AMlzBM;EAAwB,wBAA0B;ANszBxD;;AMtzBM;EAAwB,0BAA0B;AN0zBxD;;AM1zBM;EAAwB,gCAA0B;AN8zBxD;;AM9zBM;EAAwB,yBAA0B;ANk0BxD;;AMl0BM;EAAwB,yBAA0B;ANs0BxD;;AMt0BM;EAAwB,6BAA0B;AN00BxD;;AM10BM;EAAwB,8BAA0B;AN80BxD;;AM90BM;EAAwB,+BAA0B;EAA1B,wBAA0B;ANk1BxD;;AMl1BM;EAAwB,sCAA0B;EAA1B,+BAA0B;ANs1BxD;;AGryBI;EGjDE;IAAwB,wBAA0B;EN21BtD;EM31BI;IAAwB,0BAA0B;EN81BtD;EM91BI;IAAwB,gCAA0B;ENi2BtD;EMj2BI;IAAwB,yBAA0B;ENo2BtD;EMp2BI;IAAwB,yBAA0B;ENu2BtD;EMv2BI;IAAwB,6BAA0B;EN02BtD;EM12BI;IAAwB,8BAA0B;EN62BtD;EM72BI;IAAwB,+BAA0B;IAA1B,wBAA0B;ENg3BtD;EMh3BI;IAAwB,sCAA0B;IAA1B,+BAA0B;ENm3BtD;AACF;;AGn0BI;EGjDE;IAAwB,wBAA0B;ENy3BtD;EMz3BI;IAAwB,0BAA0B;EN43BtD;EM53BI;IAAwB,gCAA0B;EN+3BtD;EM/3BI;IAAwB,yBAA0B;ENk4BtD;EMl4BI;IAAwB,yBAA0B;ENq4BtD;EMr4BI;IAAwB,6BAA0B;ENw4BtD;EMx4BI;IAAwB,8BAA0B;EN24BtD;EM34BI;IAAwB,+BAA0B;IAA1B,wBAA0B;EN84BtD;EM94BI;IAAwB,sCAA0B;IAA1B,+BAA0B;ENi5BtD;AACF;;AGj2BI;EGjDE;IAAwB,wBAA0B;ENu5BtD;EMv5BI;IAAwB,0BAA0B;EN05BtD;EM15BI;IAAwB,gCAA0B;EN65BtD;EM75BI;IAAwB,yBAA0B;ENg6BtD;EMh6BI;IAAwB,yBAA0B;ENm6BtD;EMn6BI;IAAwB,6BAA0B;ENs6BtD;EMt6BI;IAAwB,8BAA0B;ENy6BtD;EMz6BI;IAAwB,+BAA0B;IAA1B,wBAA0B;EN46BtD;EM56BI;IAAwB,sCAA0B;IAA1B,+BAA0B;EN+6BtD;AACF;;AG/3BI;EGjDE;IAAwB,wBAA0B;ENq7BtD;EMr7BI;IAAwB,0BAA0B;ENw7BtD;EMx7BI;IAAwB,gCAA0B;EN27BtD;EM37BI;IAAwB,yBAA0B;EN87BtD;EM97BI;IAAwB,yBAA0B;ENi8BtD;EMj8BI;IAAwB,6BAA0B;ENo8BtD;EMp8BI;IAAwB,8BAA0B;ENu8BtD;EMv8BI;IAAwB,+BAA0B;IAA1B,wBAA0B;EN08BtD;EM18BI;IAAwB,sCAA0B;IAA1B,+BAA0B;EN68BtD;AACF;;AMp8BA;EAEI;IAAqB,wBAA0B;ENu8BjD;EMv8BE;IAAqB,0BAA0B;EN08BjD;EM18BE;IAAqB,gCAA0B;EN68BjD;EM78BE;IAAqB,yBAA0B;ENg9BjD;EMh9BE;IAAqB,yBAA0B;ENm9BjD;EMn9BE;IAAqB,6BAA0B;ENs9BjD;EMt9BE;IAAqB,8BAA0B;ENy9BjD;EMz9BE;IAAqB,+BAA0B;IAA1B,wBAA0B;EN49BjD;EM59BE;IAAqB,sCAA0B;IAA1B,+BAA0B;EN+9BjD;AACF;;AO7+BI;EAAgC,kCAA8B;EAA9B,8BAA8B;APi/BlE;;AOh/BI;EAAgC,qCAAiC;EAAjC,iCAAiC;APo/BrE;;AOn/BI;EAAgC,0CAAsC;EAAtC,sCAAsC;APu/B1E;;AOt/BI;EAAgC,6CAAyC;EAAzC,yCAAyC;AP0/B7E;;AOx/BI;EAA8B,8BAA0B;EAA1B,0BAA0B;AP4/B5D;;AO3/BI;EAA8B,gCAA4B;EAA5B,4BAA4B;AP+/B9D;;AO9/BI;EAA8B,sCAAkC;EAAlC,kCAAkC;APkgCpE;;AOjgCI;EAA8B,6BAAyB;EAAzB,yBAAyB;APqgC3D;;AOpgCI;EAA8B,+BAAuB;EAAvB,uBAAuB;APwgCzD;;AOvgCI;EAA8B,+BAAuB;EAAvB,uBAAuB;AP2gCzD;;AO1gCI;EAA8B,+BAAyB;EAAzB,yBAAyB;AP8gC3D;;AO7gCI;EAA8B,+BAAyB;EAAzB,yBAAyB;APihC3D;;AO/gCI;EAAoC,+BAAsC;EAAtC,sCAAsC;APmhC9E;;AOlhCI;EAAoC,6BAAoC;EAApC,oCAAoC;APshC5E;;AOrhCI;EAAoC,gCAAkC;EAAlC,kCAAkC;APyhC1E;;AOxhCI;EAAoC,iCAAyC;EAAzC,yCAAyC;AP4hCjF;;AO3hCI;EAAoC,oCAAwC;EAAxC,wCAAwC;AP+hChF;;AO7hCI;EAAiC,gCAAkC;EAAlC,kCAAkC;APiiCvE;;AOhiCI;EAAiC,8BAAgC;EAAhC,gCAAgC;APoiCrE;;AOniCI;EAAiC,iCAA8B;EAA9B,8BAA8B;APuiCnE;;AOtiCI;EAAiC,mCAAgC;EAAhC,gCAAgC;AP0iCrE;;AOziCI;EAAiC,kCAA+B;EAA/B,+BAA+B;AP6iCpE;;AO3iCI;EAAkC,oCAAoC;EAApC,oCAAoC;AP+iC1E;;AO9iCI;EAAkC,kCAAkC;EAAlC,kCAAkC;APkjCxE;;AOjjCI;EAAkC,qCAAgC;EAAhC,gCAAgC;APqjCtE;;AOpjCI;EAAkC,sCAAuC;EAAvC,uCAAuC;APwjC7E;;AOvjCI;EAAkC,yCAAsC;EAAtC,sCAAsC;AP2jC5E;;AO1jCI;EAAkC,sCAAiC;EAAjC,iCAAiC;AP8jCvE;;AO5jCI;EAAgC,oCAA2B;EAA3B,2BAA2B;APgkC/D;;AO/jCI;EAAgC,qCAAiC;EAAjC,iCAAiC;APmkCrE;;AOlkCI;EAAgC,mCAA+B;EAA/B,+BAA+B;APskCnE;;AOrkCI;EAAgC,sCAA6B;EAA7B,6BAA6B;APykCjE;;AOxkCI;EAAgC,wCAA+B;EAA/B,+BAA+B;AP4kCnE;;AO3kCI;EAAgC,uCAA8B;EAA9B,8BAA8B;AP+kClE;;AGnkCI;EIlDA;IAAgC,kCAA8B;IAA9B,8BAA8B;EP0nChE;EOznCE;IAAgC,qCAAiC;IAAjC,iCAAiC;EP4nCnE;EO3nCE;IAAgC,0CAAsC;IAAtC,sCAAsC;EP8nCxE;EO7nCE;IAAgC,6CAAyC;IAAzC,yCAAyC;EPgoC3E;EO9nCE;IAA8B,8BAA0B;IAA1B,0BAA0B;EPioC1D;EOhoCE;IAA8B,gCAA4B;IAA5B,4BAA4B;EPmoC5D;EOloCE;IAA8B,sCAAkC;IAAlC,kCAAkC;EPqoClE;EOpoCE;IAA8B,6BAAyB;IAAzB,yBAAyB;EPuoCzD;EOtoCE;IAA8B,+BAAuB;IAAvB,uBAAuB;EPyoCvD;EOxoCE;IAA8B,+BAAuB;IAAvB,uBAAuB;EP2oCvD;EO1oCE;IAA8B,+BAAyB;IAAzB,yBAAyB;EP6oCzD;EO5oCE;IAA8B,+BAAyB;IAAzB,yBAAyB;EP+oCzD;EO7oCE;IAAoC,+BAAsC;IAAtC,sCAAsC;EPgpC5E;EO/oCE;IAAoC,6BAAoC;IAApC,oCAAoC;EPkpC1E;EOjpCE;IAAoC,gCAAkC;IAAlC,kCAAkC;EPopCxE;EOnpCE;IAAoC,iCAAyC;IAAzC,yCAAyC;EPspC/E;EOrpCE;IAAoC,oCAAwC;IAAxC,wCAAwC;EPwpC9E;EOtpCE;IAAiC,gCAAkC;IAAlC,kCAAkC;EPypCrE;EOxpCE;IAAiC,8BAAgC;IAAhC,gCAAgC;EP2pCnE;EO1pCE;IAAiC,iCAA8B;IAA9B,8BAA8B;EP6pCjE;EO5pCE;IAAiC,mCAAgC;IAAhC,gCAAgC;EP+pCnE;EO9pCE;IAAiC,kCAA+B;IAA/B,+BAA+B;EPiqClE;EO/pCE;IAAkC,oCAAoC;IAApC,oCAAoC;EPkqCxE;EOjqCE;IAAkC,kCAAkC;IAAlC,kCAAkC;EPoqCtE;EOnqCE;IAAkC,qCAAgC;IAAhC,gCAAgC;EPsqCpE;EOrqCE;IAAkC,sCAAuC;IAAvC,uCAAuC;EPwqC3E;EOvqCE;IAAkC,yCAAsC;IAAtC,sCAAsC;EP0qC1E;EOzqCE;IAAkC,sCAAiC;IAAjC,iCAAiC;EP4qCrE;EO1qCE;IAAgC,oCAA2B;IAA3B,2BAA2B;EP6qC7D;EO5qCE;IAAgC,qCAAiC;IAAjC,iCAAiC;EP+qCnE;EO9qCE;IAAgC,mCAA+B;IAA/B,+BAA+B;EPirCjE;EOhrCE;IAAgC,sCAA6B;IAA7B,6BAA6B;EPmrC/D;EOlrCE;IAAgC,wCAA+B;IAA/B,+BAA+B;EPqrCjE;EOprCE;IAAgC,uCAA8B;IAA9B,8BAA8B;EPurChE;AACF;;AG5qCI;EIlDA;IAAgC,kCAA8B;IAA9B,8BAA8B;EPmuChE;EOluCE;IAAgC,qCAAiC;IAAjC,iCAAiC;EPquCnE;EOpuCE;IAAgC,0CAAsC;IAAtC,sCAAsC;EPuuCxE;EOtuCE;IAAgC,6CAAyC;IAAzC,yCAAyC;EPyuC3E;EOvuCE;IAA8B,8BAA0B;IAA1B,0BAA0B;EP0uC1D;EOzuCE;IAA8B,gCAA4B;IAA5B,4BAA4B;EP4uC5D;EO3uCE;IAA8B,sCAAkC;IAAlC,kCAAkC;EP8uClE;EO7uCE;IAA8B,6BAAyB;IAAzB,yBAAyB;EPgvCzD;EO/uCE;IAA8B,+BAAuB;IAAvB,uBAAuB;EPkvCvD;EOjvCE;IAA8B,+BAAuB;IAAvB,uBAAuB;EPovCvD;EOnvCE;IAA8B,+BAAyB;IAAzB,yBAAyB;EPsvCzD;EOrvCE;IAA8B,+BAAyB;IAAzB,yBAAyB;EPwvCzD;EOtvCE;IAAoC,+BAAsC;IAAtC,sCAAsC;EPyvC5E;EOxvCE;IAAoC,6BAAoC;IAApC,oCAAoC;EP2vC1E;EO1vCE;IAAoC,gCAAkC;IAAlC,kCAAkC;EP6vCxE;EO5vCE;IAAoC,iCAAyC;IAAzC,yCAAyC;EP+vC/E;EO9vCE;IAAoC,oCAAwC;IAAxC,wCAAwC;EPiwC9E;EO/vCE;IAAiC,gCAAkC;IAAlC,kCAAkC;EPkwCrE;EOjwCE;IAAiC,8BAAgC;IAAhC,gCAAgC;EPowCnE;EOnwCE;IAAiC,iCAA8B;IAA9B,8BAA8B;EPswCjE;EOrwCE;IAAiC,mCAAgC;IAAhC,gCAAgC;EPwwCnE;EOvwCE;IAAiC,kCAA+B;IAA/B,+BAA+B;EP0wClE;EOxwCE;IAAkC,oCAAoC;IAApC,oCAAoC;EP2wCxE;EO1wCE;IAAkC,kCAAkC;IAAlC,kCAAkC;EP6wCtE;EO5wCE;IAAkC,qCAAgC;IAAhC,gCAAgC;EP+wCpE;EO9wCE;IAAkC,sCAAuC;IAAvC,uCAAuC;EPixC3E;EOhxCE;IAAkC,yCAAsC;IAAtC,sCAAsC;EPmxC1E;EOlxCE;IAAkC,sCAAiC;IAAjC,iCAAiC;EPqxCrE;EOnxCE;IAAgC,oCAA2B;IAA3B,2BAA2B;EPsxC7D;EOrxCE;IAAgC,qCAAiC;IAAjC,iCAAiC;EPwxCnE;EOvxCE;IAAgC,mCAA+B;IAA/B,+BAA+B;EP0xCjE;EOzxCE;IAAgC,sCAA6B;IAA7B,6BAA6B;EP4xC/D;EO3xCE;IAAgC,wCAA+B;IAA/B,+BAA+B;EP8xCjE;EO7xCE;IAAgC,uCAA8B;IAA9B,8BAA8B;EPgyChE;AACF;;AGrxCI;EIlDA;IAAgC,kCAA8B;IAA9B,8BAA8B;EP40ChE;EO30CE;IAAgC,qCAAiC;IAAjC,iCAAiC;EP80CnE;EO70CE;IAAgC,0CAAsC;IAAtC,sCAAsC;EPg1CxE;EO/0CE;IAAgC,6CAAyC;IAAzC,yCAAyC;EPk1C3E;EOh1CE;IAA8B,8BAA0B;IAA1B,0BAA0B;EPm1C1D;EOl1CE;IAA8B,gCAA4B;IAA5B,4BAA4B;EPq1C5D;EOp1CE;IAA8B,sCAAkC;IAAlC,kCAAkC;EPu1ClE;EOt1CE;IAA8B,6BAAyB;IAAzB,yBAAyB;EPy1CzD;EOx1CE;IAA8B,+BAAuB;IAAvB,uBAAuB;EP21CvD;EO11CE;IAA8B,+BAAuB;IAAvB,uBAAuB;EP61CvD;EO51CE;IAA8B,+BAAyB;IAAzB,yBAAyB;EP+1CzD;EO91CE;IAA8B,+BAAyB;IAAzB,yBAAyB;EPi2CzD;EO/1CE;IAAoC,+BAAsC;IAAtC,sCAAsC;EPk2C5E;EOj2CE;IAAoC,6BAAoC;IAApC,oCAAoC;EPo2C1E;EOn2CE;IAAoC,gCAAkC;IAAlC,kCAAkC;EPs2CxE;EOr2CE;IAAoC,iCAAyC;IAAzC,yCAAyC;EPw2C/E;EOv2CE;IAAoC,oCAAwC;IAAxC,wCAAwC;EP02C9E;EOx2CE;IAAiC,gCAAkC;IAAlC,kCAAkC;EP22CrE;EO12CE;IAAiC,8BAAgC;IAAhC,gCAAgC;EP62CnE;EO52CE;IAAiC,iCAA8B;IAA9B,8BAA8B;EP+2CjE;EO92CE;IAAiC,mCAAgC;IAAhC,gCAAgC;EPi3CnE;EOh3CE;IAAiC,kCAA+B;IAA/B,+BAA+B;EPm3ClE;EOj3CE;IAAkC,oCAAoC;IAApC,oCAAoC;EPo3CxE;EOn3CE;IAAkC,kCAAkC;IAAlC,kCAAkC;EPs3CtE;EOr3CE;IAAkC,qCAAgC;IAAhC,gCAAgC;EPw3CpE;EOv3CE;IAAkC,sCAAuC;IAAvC,uCAAuC;EP03C3E;EOz3CE;IAAkC,yCAAsC;IAAtC,sCAAsC;EP43C1E;EO33CE;IAAkC,sCAAiC;IAAjC,iCAAiC;EP83CrE;EO53CE;IAAgC,oCAA2B;IAA3B,2BAA2B;EP+3C7D;EO93CE;IAAgC,qCAAiC;IAAjC,iCAAiC;EPi4CnE;EOh4CE;IAAgC,mCAA+B;IAA/B,+BAA+B;EPm4CjE;EOl4CE;IAAgC,sCAA6B;IAA7B,6BAA6B;EPq4C/D;EOp4CE;IAAgC,wCAA+B;IAA/B,+BAA+B;EPu4CjE;EOt4CE;IAAgC,uCAA8B;IAA9B,8BAA8B;EPy4ChE;AACF;;AG93CI;EIlDA;IAAgC,kCAA8B;IAA9B,8BAA8B;EPq7ChE;EOp7CE;IAAgC,qCAAiC;IAAjC,iCAAiC;EPu7CnE;EOt7CE;IAAgC,0CAAsC;IAAtC,sCAAsC;EPy7CxE;EOx7CE;IAAgC,6CAAyC;IAAzC,yCAAyC;EP27C3E;EOz7CE;IAA8B,8BAA0B;IAA1B,0BAA0B;EP47C1D;EO37CE;IAA8B,gCAA4B;IAA5B,4BAA4B;EP87C5D;EO77CE;IAA8B,sCAAkC;IAAlC,kCAAkC;EPg8ClE;EO/7CE;IAA8B,6BAAyB;IAAzB,yBAAyB;EPk8CzD;EOj8CE;IAA8B,+BAAuB;IAAvB,uBAAuB;EPo8CvD;EOn8CE;IAA8B,+BAAuB;IAAvB,uBAAuB;EPs8CvD;EOr8CE;IAA8B,+BAAyB;IAAzB,yBAAyB;EPw8CzD;EOv8CE;IAA8B,+BAAyB;IAAzB,yBAAyB;EP08CzD;EOx8CE;IAAoC,+BAAsC;IAAtC,sCAAsC;EP28C5E;EO18CE;IAAoC,6BAAoC;IAApC,oCAAoC;EP68C1E;EO58CE;IAAoC,gCAAkC;IAAlC,kCAAkC;EP+8CxE;EO98CE;IAAoC,iCAAyC;IAAzC,yCAAyC;EPi9C/E;EOh9CE;IAAoC,oCAAwC;IAAxC,wCAAwC;EPm9C9E;EOj9CE;IAAiC,gCAAkC;IAAlC,kCAAkC;EPo9CrE;EOn9CE;IAAiC,8BAAgC;IAAhC,gCAAgC;EPs9CnE;EOr9CE;IAAiC,iCAA8B;IAA9B,8BAA8B;EPw9CjE;EOv9CE;IAAiC,mCAAgC;IAAhC,gCAAgC;EP09CnE;EOz9CE;IAAiC,kCAA+B;IAA/B,+BAA+B;EP49ClE;EO19CE;IAAkC,oCAAoC;IAApC,oCAAoC;EP69CxE;EO59CE;IAAkC,kCAAkC;IAAlC,kCAAkC;EP+9CtE;EO99CE;IAAkC,qCAAgC;IAAhC,gCAAgC;EPi+CpE;EOh+CE;IAAkC,sCAAuC;IAAvC,uCAAuC;EPm+C3E;EOl+CE;IAAkC,yCAAsC;IAAtC,sCAAsC;EPq+C1E;EOp+CE;IAAkC,sCAAiC;IAAjC,iCAAiC;EPu+CrE;EOr+CE;IAAgC,oCAA2B;IAA3B,2BAA2B;EPw+C7D;EOv+CE;IAAgC,qCAAiC;IAAjC,iCAAiC;EP0+CnE;EOz+CE;IAAgC,mCAA+B;IAA/B,+BAA+B;EP4+CjE;EO3+CE;IAAgC,sCAA6B;IAA7B,6BAA6B;EP8+C/D;EO7+CE;IAAgC,wCAA+B;IAA/B,+BAA+B;EPg/CjE;EO/+CE;IAAgC,uCAA8B;IAA9B,8BAA8B;EPk/ChE;AACF;;AQzhDQ;EAAgC,oBAA4B;AR6hDpE;;AQ5hDQ;;EAEE,wBAAoC;AR+hD9C;;AQ7hDQ;;EAEE,0BAAwC;ARgiDlD;;AQ9hDQ;;EAEE,2BAA0C;ARiiDpD;;AQ/hDQ;;EAEE,yBAAsC;ARkiDhD;;AQjjDQ;EAAgC,0BAA4B;ARqjDpE;;AQpjDQ;;EAEE,8BAAoC;ARujD9C;;AQrjDQ;;EAEE,gCAAwC;ARwjDlD;;AQtjDQ;;EAEE,iCAA0C;ARyjDpD;;AQvjDQ;;EAEE,+BAAsC;AR0jDhD;;AQzkDQ;EAAgC,yBAA4B;AR6kDpE;;AQ5kDQ;;EAEE,6BAAoC;AR+kD9C;;AQ7kDQ;;EAEE,+BAAwC;ARglDlD;;AQ9kDQ;;EAEE,gCAA0C;ARilDpD;;AQ/kDQ;;EAEE,8BAAsC;ARklDhD;;AQjmDQ;EAAgC,uBAA4B;ARqmDpE;;AQpmDQ;;EAEE,2BAAoC;ARumD9C;;AQrmDQ;;EAEE,6BAAwC;ARwmDlD;;AQtmDQ;;EAEE,8BAA0C;ARymDpD;;AQvmDQ;;EAEE,4BAAsC;AR0mDhD;;AQznDQ;EAAgC,yBAA4B;AR6nDpE;;AQ5nDQ;;EAEE,6BAAoC;AR+nD9C;;AQ7nDQ;;EAEE,+BAAwC;ARgoDlD;;AQ9nDQ;;EAEE,gCAA0C;ARioDpD;;AQ/nDQ;;EAEE,8BAAsC;ARkoDhD;;AQjpDQ;EAAgC,uBAA4B;ARqpDpE;;AQppDQ;;EAEE,2BAAoC;ARupD9C;;AQrpDQ;;EAEE,6BAAwC;ARwpDlD;;AQtpDQ;;EAEE,8BAA0C;ARypDpD;;AQvpDQ;;EAEE,4BAAsC;AR0pDhD;;AQzqDQ;EAAgC,qBAA4B;AR6qDpE;;AQ5qDQ;;EAEE,yBAAoC;AR+qD9C;;AQ7qDQ;;EAEE,2BAAwC;ARgrDlD;;AQ9qDQ;;EAEE,4BAA0C;ARirDpD;;AQ/qDQ;;EAEE,0BAAsC;ARkrDhD;;AQjsDQ;EAAgC,2BAA4B;ARqsDpE;;AQpsDQ;;EAEE,+BAAoC;ARusD9C;;AQrsDQ;;EAEE,iCAAwC;ARwsDlD;;AQtsDQ;;EAEE,kCAA0C;ARysDpD;;AQvsDQ;;EAEE,gCAAsC;AR0sDhD;;AQztDQ;EAAgC,0BAA4B;AR6tDpE;;AQ5tDQ;;EAEE,8BAAoC;AR+tD9C;;AQ7tDQ;;EAEE,gCAAwC;ARguDlD;;AQ9tDQ;;EAEE,iCAA0C;ARiuDpD;;AQ/tDQ;;EAEE,+BAAsC;ARkuDhD;;AQjvDQ;EAAgC,wBAA4B;ARqvDpE;;AQpvDQ;;EAEE,4BAAoC;ARuvD9C;;AQrvDQ;;EAEE,8BAAwC;ARwvDlD;;AQtvDQ;;EAEE,+BAA0C;ARyvDpD;;AQvvDQ;;EAEE,6BAAsC;AR0vDhD;;AQzwDQ;EAAgC,0BAA4B;AR6wDpE;;AQ5wDQ;;EAEE,8BAAoC;AR+wD9C;;AQ7wDQ;;EAEE,gCAAwC;ARgxDlD;;AQ9wDQ;;EAEE,iCAA0C;ARixDpD;;AQ/wDQ;;EAEE,+BAAsC;ARkxDhD;;AQjyDQ;EAAgC,wBAA4B;ARqyDpE;;AQpyDQ;;EAEE,4BAAoC;ARuyD9C;;AQryDQ;;EAEE,8BAAwC;ARwyDlD;;AQtyDQ;;EAEE,+BAA0C;ARyyDpD;;AQvyDQ;;EAEE,6BAAsC;AR0yDhD;;AQlyDQ;EAAwB,2BAA2B;ARsyD3D;;AQryDQ;;EAEE,+BAA+B;ARwyDzC;;AQtyDQ;;EAEE,iCAAiC;ARyyD3C;;AQvyDQ;;EAEE,kCAAkC;AR0yD5C;;AQxyDQ;;EAEE,gCAAgC;AR2yD1C;;AQ1zDQ;EAAwB,0BAA2B;AR8zD3D;;AQ7zDQ;;EAEE,8BAA+B;ARg0DzC;;AQ9zDQ;;EAEE,gCAAiC;ARi0D3C;;AQ/zDQ;;EAEE,iCAAkC;ARk0D5C;;AQh0DQ;;EAEE,+BAAgC;ARm0D1C;;AQl1DQ;EAAwB,wBAA2B;ARs1D3D;;AQr1DQ;;EAEE,4BAA+B;ARw1DzC;;AQt1DQ;;EAEE,8BAAiC;ARy1D3C;;AQv1DQ;;EAEE,+BAAkC;AR01D5C;;AQx1DQ;;EAEE,6BAAgC;AR21D1C;;AQ12DQ;EAAwB,0BAA2B;AR82D3D;;AQ72DQ;;EAEE,8BAA+B;ARg3DzC;;AQ92DQ;;EAEE,gCAAiC;ARi3D3C;;AQ/2DQ;;EAEE,iCAAkC;ARk3D5C;;AQh3DQ;;EAEE,+BAAgC;ARm3D1C;;AQl4DQ;EAAwB,wBAA2B;ARs4D3D;;AQr4DQ;;EAEE,4BAA+B;ARw4DzC;;AQt4DQ;;EAEE,8BAAiC;ARy4D3C;;AQv4DQ;;EAEE,+BAAkC;AR04D5C;;AQx4DQ;;EAEE,6BAAgC;AR24D1C;;AQr4DI;EAAmB,uBAAuB;ARy4D9C;;AQx4DI;;EAEE,2BAA2B;AR24DjC;;AQz4DI;;EAEE,6BAA6B;AR44DnC;;AQ14DI;;EAEE,8BAA8B;AR64DpC;;AQ34DI;;EAEE,4BAA4B;AR84DlC;;AGv5DI;EKlDI;IAAgC,oBAA4B;ER88DlE;EQ78DM;;IAEE,wBAAoC;ER+8D5C;EQ78DM;;IAEE,0BAAwC;ER+8DhD;EQ78DM;;IAEE,2BAA0C;ER+8DlD;EQ78DM;;IAEE,yBAAsC;ER+8D9C;EQ99DM;IAAgC,0BAA4B;ERi+DlE;EQh+DM;;IAEE,8BAAoC;ERk+D5C;EQh+DM;;IAEE,gCAAwC;ERk+DhD;EQh+DM;;IAEE,iCAA0C;ERk+DlD;EQh+DM;;IAEE,+BAAsC;ERk+D9C;EQj/DM;IAAgC,yBAA4B;ERo/DlE;EQn/DM;;IAEE,6BAAoC;ERq/D5C;EQn/DM;;IAEE,+BAAwC;ERq/DhD;EQn/DM;;IAEE,gCAA0C;ERq/DlD;EQn/DM;;IAEE,8BAAsC;ERq/D9C;EQpgEM;IAAgC,uBAA4B;ERugElE;EQtgEM;;IAEE,2BAAoC;ERwgE5C;EQtgEM;;IAEE,6BAAwC;ERwgEhD;EQtgEM;;IAEE,8BAA0C;ERwgElD;EQtgEM;;IAEE,4BAAsC;ERwgE9C;EQvhEM;IAAgC,yBAA4B;ER0hElE;EQzhEM;;IAEE,6BAAoC;ER2hE5C;EQzhEM;;IAEE,+BAAwC;ER2hEhD;EQzhEM;;IAEE,gCAA0C;ER2hElD;EQzhEM;;IAEE,8BAAsC;ER2hE9C;EQ1iEM;IAAgC,uBAA4B;ER6iElE;EQ5iEM;;IAEE,2BAAoC;ER8iE5C;EQ5iEM;;IAEE,6BAAwC;ER8iEhD;EQ5iEM;;IAEE,8BAA0C;ER8iElD;EQ5iEM;;IAEE,4BAAsC;ER8iE9C;EQ7jEM;IAAgC,qBAA4B;ERgkElE;EQ/jEM;;IAEE,yBAAoC;ERikE5C;EQ/jEM;;IAEE,2BAAwC;ERikEhD;EQ/jEM;;IAEE,4BAA0C;ERikElD;EQ/jEM;;IAEE,0BAAsC;ERikE9C;EQhlEM;IAAgC,2BAA4B;ERmlElE;EQllEM;;IAEE,+BAAoC;ERolE5C;EQllEM;;IAEE,iCAAwC;ERolEhD;EQllEM;;IAEE,kCAA0C;ERolElD;EQllEM;;IAEE,gCAAsC;ERolE9C;EQnmEM;IAAgC,0BAA4B;ERsmElE;EQrmEM;;IAEE,8BAAoC;ERumE5C;EQrmEM;;IAEE,gCAAwC;ERumEhD;EQrmEM;;IAEE,iCAA0C;ERumElD;EQrmEM;;IAEE,+BAAsC;ERumE9C;EQtnEM;IAAgC,wBAA4B;ERynElE;EQxnEM;;IAEE,4BAAoC;ER0nE5C;EQxnEM;;IAEE,8BAAwC;ER0nEhD;EQxnEM;;IAEE,+BAA0C;ER0nElD;EQxnEM;;IAEE,6BAAsC;ER0nE9C;EQzoEM;IAAgC,0BAA4B;ER4oElE;EQ3oEM;;IAEE,8BAAoC;ER6oE5C;EQ3oEM;;IAEE,gCAAwC;ER6oEhD;EQ3oEM;;IAEE,iCAA0C;ER6oElD;EQ3oEM;;IAEE,+BAAsC;ER6oE9C;EQ5pEM;IAAgC,wBAA4B;ER+pElE;EQ9pEM;;IAEE,4BAAoC;ERgqE5C;EQ9pEM;;IAEE,8BAAwC;ERgqEhD;EQ9pEM;;IAEE,+BAA0C;ERgqElD;EQ9pEM;;IAEE,6BAAsC;ERgqE9C;EQxpEM;IAAwB,2BAA2B;ER2pEzD;EQ1pEM;;IAEE,+BAA+B;ER4pEvC;EQ1pEM;;IAEE,iCAAiC;ER4pEzC;EQ1pEM;;IAEE,kCAAkC;ER4pE1C;EQ1pEM;;IAEE,gCAAgC;ER4pExC;EQ3qEM;IAAwB,0BAA2B;ER8qEzD;EQ7qEM;;IAEE,8BAA+B;ER+qEvC;EQ7qEM;;IAEE,gCAAiC;ER+qEzC;EQ7qEM;;IAEE,iCAAkC;ER+qE1C;EQ7qEM;;IAEE,+BAAgC;ER+qExC;EQ9rEM;IAAwB,wBAA2B;ERisEzD;EQhsEM;;IAEE,4BAA+B;ERksEvC;EQhsEM;;IAEE,8BAAiC;ERksEzC;EQhsEM;;IAEE,+BAAkC;ERksE1C;EQhsEM;;IAEE,6BAAgC;ERksExC;EQjtEM;IAAwB,0BAA2B;ERotEzD;EQntEM;;IAEE,8BAA+B;ERqtEvC;EQntEM;;IAEE,gCAAiC;ERqtEzC;EQntEM;;IAEE,iCAAkC;ERqtE1C;EQntEM;;IAEE,+BAAgC;ERqtExC;EQpuEM;IAAwB,wBAA2B;ERuuEzD;EQtuEM;;IAEE,4BAA+B;ERwuEvC;EQtuEM;;IAEE,8BAAiC;ERwuEzC;EQtuEM;;IAEE,+BAAkC;ERwuE1C;EQtuEM;;IAEE,6BAAgC;ERwuExC;EQluEE;IAAmB,uBAAuB;ERquE5C;EQpuEE;;IAEE,2BAA2B;ERsuE/B;EQpuEE;;IAEE,6BAA6B;ERsuEjC;EQpuEE;;IAEE,8BAA8B;ERsuElC;EQpuEE;;IAEE,4BAA4B;ERsuEhC;AACF;;AGhvEI;EKlDI;IAAgC,oBAA4B;ERuyElE;EQtyEM;;IAEE,wBAAoC;ERwyE5C;EQtyEM;;IAEE,0BAAwC;ERwyEhD;EQtyEM;;IAEE,2BAA0C;ERwyElD;EQtyEM;;IAEE,yBAAsC;ERwyE9C;EQvzEM;IAAgC,0BAA4B;ER0zElE;EQzzEM;;IAEE,8BAAoC;ER2zE5C;EQzzEM;;IAEE,gCAAwC;ER2zEhD;EQzzEM;;IAEE,iCAA0C;ER2zElD;EQzzEM;;IAEE,+BAAsC;ER2zE9C;EQ10EM;IAAgC,yBAA4B;ER60ElE;EQ50EM;;IAEE,6BAAoC;ER80E5C;EQ50EM;;IAEE,+BAAwC;ER80EhD;EQ50EM;;IAEE,gCAA0C;ER80ElD;EQ50EM;;IAEE,8BAAsC;ER80E9C;EQ71EM;IAAgC,uBAA4B;ERg2ElE;EQ/1EM;;IAEE,2BAAoC;ERi2E5C;EQ/1EM;;IAEE,6BAAwC;ERi2EhD;EQ/1EM;;IAEE,8BAA0C;ERi2ElD;EQ/1EM;;IAEE,4BAAsC;ERi2E9C;EQh3EM;IAAgC,yBAA4B;ERm3ElE;EQl3EM;;IAEE,6BAAoC;ERo3E5C;EQl3EM;;IAEE,+BAAwC;ERo3EhD;EQl3EM;;IAEE,gCAA0C;ERo3ElD;EQl3EM;;IAEE,8BAAsC;ERo3E9C;EQn4EM;IAAgC,uBAA4B;ERs4ElE;EQr4EM;;IAEE,2BAAoC;ERu4E5C;EQr4EM;;IAEE,6BAAwC;ERu4EhD;EQr4EM;;IAEE,8BAA0C;ERu4ElD;EQr4EM;;IAEE,4BAAsC;ERu4E9C;EQt5EM;IAAgC,qBAA4B;ERy5ElE;EQx5EM;;IAEE,yBAAoC;ER05E5C;EQx5EM;;IAEE,2BAAwC;ER05EhD;EQx5EM;;IAEE,4BAA0C;ER05ElD;EQx5EM;;IAEE,0BAAsC;ER05E9C;EQz6EM;IAAgC,2BAA4B;ER46ElE;EQ36EM;;IAEE,+BAAoC;ER66E5C;EQ36EM;;IAEE,iCAAwC;ER66EhD;EQ36EM;;IAEE,kCAA0C;ER66ElD;EQ36EM;;IAEE,gCAAsC;ER66E9C;EQ57EM;IAAgC,0BAA4B;ER+7ElE;EQ97EM;;IAEE,8BAAoC;ERg8E5C;EQ97EM;;IAEE,gCAAwC;ERg8EhD;EQ97EM;;IAEE,iCAA0C;ERg8ElD;EQ97EM;;IAEE,+BAAsC;ERg8E9C;EQ/8EM;IAAgC,wBAA4B;ERk9ElE;EQj9EM;;IAEE,4BAAoC;ERm9E5C;EQj9EM;;IAEE,8BAAwC;ERm9EhD;EQj9EM;;IAEE,+BAA0C;ERm9ElD;EQj9EM;;IAEE,6BAAsC;ERm9E9C;EQl+EM;IAAgC,0BAA4B;ERq+ElE;EQp+EM;;IAEE,8BAAoC;ERs+E5C;EQp+EM;;IAEE,gCAAwC;ERs+EhD;EQp+EM;;IAEE,iCAA0C;ERs+ElD;EQp+EM;;IAEE,+BAAsC;ERs+E9C;EQr/EM;IAAgC,wBAA4B;ERw/ElE;EQv/EM;;IAEE,4BAAoC;ERy/E5C;EQv/EM;;IAEE,8BAAwC;ERy/EhD;EQv/EM;;IAEE,+BAA0C;ERy/ElD;EQv/EM;;IAEE,6BAAsC;ERy/E9C;EQj/EM;IAAwB,2BAA2B;ERo/EzD;EQn/EM;;IAEE,+BAA+B;ERq/EvC;EQn/EM;;IAEE,iCAAiC;ERq/EzC;EQn/EM;;IAEE,kCAAkC;ERq/E1C;EQn/EM;;IAEE,gCAAgC;ERq/ExC;EQpgFM;IAAwB,0BAA2B;ERugFzD;EQtgFM;;IAEE,8BAA+B;ERwgFvC;EQtgFM;;IAEE,gCAAiC;ERwgFzC;EQtgFM;;IAEE,iCAAkC;ERwgF1C;EQtgFM;;IAEE,+BAAgC;ERwgFxC;EQvhFM;IAAwB,wBAA2B;ER0hFzD;EQzhFM;;IAEE,4BAA+B;ER2hFvC;EQzhFM;;IAEE,8BAAiC;ER2hFzC;EQzhFM;;IAEE,+BAAkC;ER2hF1C;EQzhFM;;IAEE,6BAAgC;ER2hFxC;EQ1iFM;IAAwB,0BAA2B;ER6iFzD;EQ5iFM;;IAEE,8BAA+B;ER8iFvC;EQ5iFM;;IAEE,gCAAiC;ER8iFzC;EQ5iFM;;IAEE,iCAAkC;ER8iF1C;EQ5iFM;;IAEE,+BAAgC;ER8iFxC;EQ7jFM;IAAwB,wBAA2B;ERgkFzD;EQ/jFM;;IAEE,4BAA+B;ERikFvC;EQ/jFM;;IAEE,8BAAiC;ERikFzC;EQ/jFM;;IAEE,+BAAkC;ERikF1C;EQ/jFM;;IAEE,6BAAgC;ERikFxC;EQ3jFE;IAAmB,uBAAuB;ER8jF5C;EQ7jFE;;IAEE,2BAA2B;ER+jF/B;EQ7jFE;;IAEE,6BAA6B;ER+jFjC;EQ7jFE;;IAEE,8BAA8B;ER+jFlC;EQ7jFE;;IAEE,4BAA4B;ER+jFhC;AACF;;AGzkFI;EKlDI;IAAgC,oBAA4B;ERgoFlE;EQ/nFM;;IAEE,wBAAoC;ERioF5C;EQ/nFM;;IAEE,0BAAwC;ERioFhD;EQ/nFM;;IAEE,2BAA0C;ERioFlD;EQ/nFM;;IAEE,yBAAsC;ERioF9C;EQhpFM;IAAgC,0BAA4B;ERmpFlE;EQlpFM;;IAEE,8BAAoC;ERopF5C;EQlpFM;;IAEE,gCAAwC;ERopFhD;EQlpFM;;IAEE,iCAA0C;ERopFlD;EQlpFM;;IAEE,+BAAsC;ERopF9C;EQnqFM;IAAgC,yBAA4B;ERsqFlE;EQrqFM;;IAEE,6BAAoC;ERuqF5C;EQrqFM;;IAEE,+BAAwC;ERuqFhD;EQrqFM;;IAEE,gCAA0C;ERuqFlD;EQrqFM;;IAEE,8BAAsC;ERuqF9C;EQtrFM;IAAgC,uBAA4B;ERyrFlE;EQxrFM;;IAEE,2BAAoC;ER0rF5C;EQxrFM;;IAEE,6BAAwC;ER0rFhD;EQxrFM;;IAEE,8BAA0C;ER0rFlD;EQxrFM;;IAEE,4BAAsC;ER0rF9C;EQzsFM;IAAgC,yBAA4B;ER4sFlE;EQ3sFM;;IAEE,6BAAoC;ER6sF5C;EQ3sFM;;IAEE,+BAAwC;ER6sFhD;EQ3sFM;;IAEE,gCAA0C;ER6sFlD;EQ3sFM;;IAEE,8BAAsC;ER6sF9C;EQ5tFM;IAAgC,uBAA4B;ER+tFlE;EQ9tFM;;IAEE,2BAAoC;ERguF5C;EQ9tFM;;IAEE,6BAAwC;ERguFhD;EQ9tFM;;IAEE,8BAA0C;ERguFlD;EQ9tFM;;IAEE,4BAAsC;ERguF9C;EQ/uFM;IAAgC,qBAA4B;ERkvFlE;EQjvFM;;IAEE,yBAAoC;ERmvF5C;EQjvFM;;IAEE,2BAAwC;ERmvFhD;EQjvFM;;IAEE,4BAA0C;ERmvFlD;EQjvFM;;IAEE,0BAAsC;ERmvF9C;EQlwFM;IAAgC,2BAA4B;ERqwFlE;EQpwFM;;IAEE,+BAAoC;ERswF5C;EQpwFM;;IAEE,iCAAwC;ERswFhD;EQpwFM;;IAEE,kCAA0C;ERswFlD;EQpwFM;;IAEE,gCAAsC;ERswF9C;EQrxFM;IAAgC,0BAA4B;ERwxFlE;EQvxFM;;IAEE,8BAAoC;ERyxF5C;EQvxFM;;IAEE,gCAAwC;ERyxFhD;EQvxFM;;IAEE,iCAA0C;ERyxFlD;EQvxFM;;IAEE,+BAAsC;ERyxF9C;EQxyFM;IAAgC,wBAA4B;ER2yFlE;EQ1yFM;;IAEE,4BAAoC;ER4yF5C;EQ1yFM;;IAEE,8BAAwC;ER4yFhD;EQ1yFM;;IAEE,+BAA0C;ER4yFlD;EQ1yFM;;IAEE,6BAAsC;ER4yF9C;EQ3zFM;IAAgC,0BAA4B;ER8zFlE;EQ7zFM;;IAEE,8BAAoC;ER+zF5C;EQ7zFM;;IAEE,gCAAwC;ER+zFhD;EQ7zFM;;IAEE,iCAA0C;ER+zFlD;EQ7zFM;;IAEE,+BAAsC;ER+zF9C;EQ90FM;IAAgC,wBAA4B;ERi1FlE;EQh1FM;;IAEE,4BAAoC;ERk1F5C;EQh1FM;;IAEE,8BAAwC;ERk1FhD;EQh1FM;;IAEE,+BAA0C;ERk1FlD;EQh1FM;;IAEE,6BAAsC;ERk1F9C;EQ10FM;IAAwB,2BAA2B;ER60FzD;EQ50FM;;IAEE,+BAA+B;ER80FvC;EQ50FM;;IAEE,iCAAiC;ER80FzC;EQ50FM;;IAEE,kCAAkC;ER80F1C;EQ50FM;;IAEE,gCAAgC;ER80FxC;EQ71FM;IAAwB,0BAA2B;ERg2FzD;EQ/1FM;;IAEE,8BAA+B;ERi2FvC;EQ/1FM;;IAEE,gCAAiC;ERi2FzC;EQ/1FM;;IAEE,iCAAkC;ERi2F1C;EQ/1FM;;IAEE,+BAAgC;ERi2FxC;EQh3FM;IAAwB,wBAA2B;ERm3FzD;EQl3FM;;IAEE,4BAA+B;ERo3FvC;EQl3FM;;IAEE,8BAAiC;ERo3FzC;EQl3FM;;IAEE,+BAAkC;ERo3F1C;EQl3FM;;IAEE,6BAAgC;ERo3FxC;EQn4FM;IAAwB,0BAA2B;ERs4FzD;EQr4FM;;IAEE,8BAA+B;ERu4FvC;EQr4FM;;IAEE,gCAAiC;ERu4FzC;EQr4FM;;IAEE,iCAAkC;ERu4F1C;EQr4FM;;IAEE,+BAAgC;ERu4FxC;EQt5FM;IAAwB,wBAA2B;ERy5FzD;EQx5FM;;IAEE,4BAA+B;ER05FvC;EQx5FM;;IAEE,8BAAiC;ER05FzC;EQx5FM;;IAEE,+BAAkC;ER05F1C;EQx5FM;;IAEE,6BAAgC;ER05FxC;EQp5FE;IAAmB,uBAAuB;ERu5F5C;EQt5FE;;IAEE,2BAA2B;ERw5F/B;EQt5FE;;IAEE,6BAA6B;ERw5FjC;EQt5FE;;IAEE,8BAA8B;ERw5FlC;EQt5FE;;IAEE,4BAA4B;ERw5FhC;AACF;;AGl6FI;EKlDI;IAAgC,oBAA4B;ERy9FlE;EQx9FM;;IAEE,wBAAoC;ER09F5C;EQx9FM;;IAEE,0BAAwC;ER09FhD;EQx9FM;;IAEE,2BAA0C;ER09FlD;EQx9FM;;IAEE,yBAAsC;ER09F9C;EQz+FM;IAAgC,0BAA4B;ER4+FlE;EQ3+FM;;IAEE,8BAAoC;ER6+F5C;EQ3+FM;;IAEE,gCAAwC;ER6+FhD;EQ3+FM;;IAEE,iCAA0C;ER6+FlD;EQ3+FM;;IAEE,+BAAsC;ER6+F9C;EQ5/FM;IAAgC,yBAA4B;ER+/FlE;EQ9/FM;;IAEE,6BAAoC;ERggG5C;EQ9/FM;;IAEE,+BAAwC;ERggGhD;EQ9/FM;;IAEE,gCAA0C;ERggGlD;EQ9/FM;;IAEE,8BAAsC;ERggG9C;EQ/gGM;IAAgC,uBAA4B;ERkhGlE;EQjhGM;;IAEE,2BAAoC;ERmhG5C;EQjhGM;;IAEE,6BAAwC;ERmhGhD;EQjhGM;;IAEE,8BAA0C;ERmhGlD;EQjhGM;;IAEE,4BAAsC;ERmhG9C;EQliGM;IAAgC,yBAA4B;ERqiGlE;EQpiGM;;IAEE,6BAAoC;ERsiG5C;EQpiGM;;IAEE,+BAAwC;ERsiGhD;EQpiGM;;IAEE,gCAA0C;ERsiGlD;EQpiGM;;IAEE,8BAAsC;ERsiG9C;EQrjGM;IAAgC,uBAA4B;ERwjGlE;EQvjGM;;IAEE,2BAAoC;ERyjG5C;EQvjGM;;IAEE,6BAAwC;ERyjGhD;EQvjGM;;IAEE,8BAA0C;ERyjGlD;EQvjGM;;IAEE,4BAAsC;ERyjG9C;EQxkGM;IAAgC,qBAA4B;ER2kGlE;EQ1kGM;;IAEE,yBAAoC;ER4kG5C;EQ1kGM;;IAEE,2BAAwC;ER4kGhD;EQ1kGM;;IAEE,4BAA0C;ER4kGlD;EQ1kGM;;IAEE,0BAAsC;ER4kG9C;EQ3lGM;IAAgC,2BAA4B;ER8lGlE;EQ7lGM;;IAEE,+BAAoC;ER+lG5C;EQ7lGM;;IAEE,iCAAwC;ER+lGhD;EQ7lGM;;IAEE,kCAA0C;ER+lGlD;EQ7lGM;;IAEE,gCAAsC;ER+lG9C;EQ9mGM;IAAgC,0BAA4B;ERinGlE;EQhnGM;;IAEE,8BAAoC;ERknG5C;EQhnGM;;IAEE,gCAAwC;ERknGhD;EQhnGM;;IAEE,iCAA0C;ERknGlD;EQhnGM;;IAEE,+BAAsC;ERknG9C;EQjoGM;IAAgC,wBAA4B;ERooGlE;EQnoGM;;IAEE,4BAAoC;ERqoG5C;EQnoGM;;IAEE,8BAAwC;ERqoGhD;EQnoGM;;IAEE,+BAA0C;ERqoGlD;EQnoGM;;IAEE,6BAAsC;ERqoG9C;EQppGM;IAAgC,0BAA4B;ERupGlE;EQtpGM;;IAEE,8BAAoC;ERwpG5C;EQtpGM;;IAEE,gCAAwC;ERwpGhD;EQtpGM;;IAEE,iCAA0C;ERwpGlD;EQtpGM;;IAEE,+BAAsC;ERwpG9C;EQvqGM;IAAgC,wBAA4B;ER0qGlE;EQzqGM;;IAEE,4BAAoC;ER2qG5C;EQzqGM;;IAEE,8BAAwC;ER2qGhD;EQzqGM;;IAEE,+BAA0C;ER2qGlD;EQzqGM;;IAEE,6BAAsC;ER2qG9C;EQnqGM;IAAwB,2BAA2B;ERsqGzD;EQrqGM;;IAEE,+BAA+B;ERuqGvC;EQrqGM;;IAEE,iCAAiC;ERuqGzC;EQrqGM;;IAEE,kCAAkC;ERuqG1C;EQrqGM;;IAEE,gCAAgC;ERuqGxC;EQtrGM;IAAwB,0BAA2B;ERyrGzD;EQxrGM;;IAEE,8BAA+B;ER0rGvC;EQxrGM;;IAEE,gCAAiC;ER0rGzC;EQxrGM;;IAEE,iCAAkC;ER0rG1C;EQxrGM;;IAEE,+BAAgC;ER0rGxC;EQzsGM;IAAwB,wBAA2B;ER4sGzD;EQ3sGM;;IAEE,4BAA+B;ER6sGvC;EQ3sGM;;IAEE,8BAAiC;ER6sGzC;EQ3sGM;;IAEE,+BAAkC;ER6sG1C;EQ3sGM;;IAEE,6BAAgC;ER6sGxC;EQ5tGM;IAAwB,0BAA2B;ER+tGzD;EQ9tGM;;IAEE,8BAA+B;ERguGvC;EQ9tGM;;IAEE,gCAAiC;ERguGzC;EQ9tGM;;IAEE,iCAAkC;ERguG1C;EQ9tGM;;IAEE,+BAAgC;ERguGxC;EQ/uGM;IAAwB,wBAA2B;ERkvGzD;EQjvGM;;IAEE,4BAA+B;ERmvGvC;EQjvGM;;IAEE,8BAAiC;ERmvGzC;EQjvGM;;IAEE,+BAAkC;ERmvG1C;EQjvGM;;IAEE,6BAAgC;ERmvGxC;EQ7uGE;IAAmB,uBAAuB;ERgvG5C;EQ/uGE;;IAEE,2BAA2B;ERivG/B;EQ/uGE;;IAEE,6BAA6B;ERivGjC;EQ/uGE;;IAEE,8BAA8B;ERivGlC;EQ/uGE;;IAEE,4BAA4B;ERivGhC;AACF","file":"bootstrap-grid.css","sourcesContent":["/*!\n * Bootstrap Grid v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n@import \"functions\";\n@import \"variables\";\n\n@import \"mixins/breakpoints\";\n@import \"mixins/grid-framework\";\n@import \"mixins/grid\";\n\n@import \"grid\";\n@import \"utilities/display\";\n@import \"utilities/flex\";\n@import \"utilities/spacing\";\n","/*!\n * Bootstrap Grid v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n.container {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n@media (min-width: 576px) {\n .container {\n max-width: 540px;\n }\n}\n\n@media (min-width: 768px) {\n .container {\n max-width: 720px;\n }\n}\n\n@media (min-width: 992px) {\n .container {\n max-width: 960px;\n }\n}\n\n@media (min-width: 1200px) {\n .container {\n max-width: 1140px;\n }\n}\n\n.container-fluid {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n.row {\n display: flex;\n flex-wrap: wrap;\n margin-right: -15px;\n margin-left: -15px;\n}\n\n.no-gutters {\n margin-right: 0;\n margin-left: 0;\n}\n\n.no-gutters > .col,\n.no-gutters > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n}\n\n.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n position: relative;\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n}\n\n.col {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n}\n\n.col-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n}\n\n.col-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n}\n\n.col-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n}\n\n.col-3 {\n flex: 0 0 25%;\n max-width: 25%;\n}\n\n.col-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n}\n\n.col-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n}\n\n.col-6 {\n flex: 0 0 50%;\n max-width: 50%;\n}\n\n.col-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n}\n\n.col-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n}\n\n.col-9 {\n flex: 0 0 75%;\n max-width: 75%;\n}\n\n.col-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n}\n\n.col-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n}\n\n.col-12 {\n flex: 0 0 100%;\n max-width: 100%;\n}\n\n.order-first {\n order: -1;\n}\n\n.order-last {\n order: 13;\n}\n\n.order-0 {\n order: 0;\n}\n\n.order-1 {\n order: 1;\n}\n\n.order-2 {\n order: 2;\n}\n\n.order-3 {\n order: 3;\n}\n\n.order-4 {\n order: 4;\n}\n\n.order-5 {\n order: 5;\n}\n\n.order-6 {\n order: 6;\n}\n\n.order-7 {\n order: 7;\n}\n\n.order-8 {\n order: 8;\n}\n\n.order-9 {\n order: 9;\n}\n\n.order-10 {\n order: 10;\n}\n\n.order-11 {\n order: 11;\n}\n\n.order-12 {\n order: 12;\n}\n\n.offset-1 {\n margin-left: 8.333333%;\n}\n\n.offset-2 {\n margin-left: 16.666667%;\n}\n\n.offset-3 {\n margin-left: 25%;\n}\n\n.offset-4 {\n margin-left: 33.333333%;\n}\n\n.offset-5 {\n margin-left: 41.666667%;\n}\n\n.offset-6 {\n margin-left: 50%;\n}\n\n.offset-7 {\n margin-left: 58.333333%;\n}\n\n.offset-8 {\n margin-left: 66.666667%;\n}\n\n.offset-9 {\n margin-left: 75%;\n}\n\n.offset-10 {\n margin-left: 83.333333%;\n}\n\n.offset-11 {\n margin-left: 91.666667%;\n}\n\n@media (min-width: 576px) {\n .col-sm {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-sm-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-sm-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-sm-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-sm-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-sm-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-sm-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-sm-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-sm-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-sm-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-sm-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-sm-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-sm-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-sm-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-sm-first {\n order: -1;\n }\n .order-sm-last {\n order: 13;\n }\n .order-sm-0 {\n order: 0;\n }\n .order-sm-1 {\n order: 1;\n }\n .order-sm-2 {\n order: 2;\n }\n .order-sm-3 {\n order: 3;\n }\n .order-sm-4 {\n order: 4;\n }\n .order-sm-5 {\n order: 5;\n }\n .order-sm-6 {\n order: 6;\n }\n .order-sm-7 {\n order: 7;\n }\n .order-sm-8 {\n order: 8;\n }\n .order-sm-9 {\n order: 9;\n }\n .order-sm-10 {\n order: 10;\n }\n .order-sm-11 {\n order: 11;\n }\n .order-sm-12 {\n order: 12;\n }\n .offset-sm-0 {\n margin-left: 0;\n }\n .offset-sm-1 {\n margin-left: 8.333333%;\n }\n .offset-sm-2 {\n margin-left: 16.666667%;\n }\n .offset-sm-3 {\n margin-left: 25%;\n }\n .offset-sm-4 {\n margin-left: 33.333333%;\n }\n .offset-sm-5 {\n margin-left: 41.666667%;\n }\n .offset-sm-6 {\n margin-left: 50%;\n }\n .offset-sm-7 {\n margin-left: 58.333333%;\n }\n .offset-sm-8 {\n margin-left: 66.666667%;\n }\n .offset-sm-9 {\n margin-left: 75%;\n }\n .offset-sm-10 {\n margin-left: 83.333333%;\n }\n .offset-sm-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 768px) {\n .col-md {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-md-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-md-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-md-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-md-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-md-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-md-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-md-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-md-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-md-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-md-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-md-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-md-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-md-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-md-first {\n order: -1;\n }\n .order-md-last {\n order: 13;\n }\n .order-md-0 {\n order: 0;\n }\n .order-md-1 {\n order: 1;\n }\n .order-md-2 {\n order: 2;\n }\n .order-md-3 {\n order: 3;\n }\n .order-md-4 {\n order: 4;\n }\n .order-md-5 {\n order: 5;\n }\n .order-md-6 {\n order: 6;\n }\n .order-md-7 {\n order: 7;\n }\n .order-md-8 {\n order: 8;\n }\n .order-md-9 {\n order: 9;\n }\n .order-md-10 {\n order: 10;\n }\n .order-md-11 {\n order: 11;\n }\n .order-md-12 {\n order: 12;\n }\n .offset-md-0 {\n margin-left: 0;\n }\n .offset-md-1 {\n margin-left: 8.333333%;\n }\n .offset-md-2 {\n margin-left: 16.666667%;\n }\n .offset-md-3 {\n margin-left: 25%;\n }\n .offset-md-4 {\n margin-left: 33.333333%;\n }\n .offset-md-5 {\n margin-left: 41.666667%;\n }\n .offset-md-6 {\n margin-left: 50%;\n }\n .offset-md-7 {\n margin-left: 58.333333%;\n }\n .offset-md-8 {\n margin-left: 66.666667%;\n }\n .offset-md-9 {\n margin-left: 75%;\n }\n .offset-md-10 {\n margin-left: 83.333333%;\n }\n .offset-md-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 992px) {\n .col-lg {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-lg-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-lg-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-lg-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-lg-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-lg-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-lg-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-lg-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-lg-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-lg-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-lg-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-lg-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-lg-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-lg-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-lg-first {\n order: -1;\n }\n .order-lg-last {\n order: 13;\n }\n .order-lg-0 {\n order: 0;\n }\n .order-lg-1 {\n order: 1;\n }\n .order-lg-2 {\n order: 2;\n }\n .order-lg-3 {\n order: 3;\n }\n .order-lg-4 {\n order: 4;\n }\n .order-lg-5 {\n order: 5;\n }\n .order-lg-6 {\n order: 6;\n }\n .order-lg-7 {\n order: 7;\n }\n .order-lg-8 {\n order: 8;\n }\n .order-lg-9 {\n order: 9;\n }\n .order-lg-10 {\n order: 10;\n }\n .order-lg-11 {\n order: 11;\n }\n .order-lg-12 {\n order: 12;\n }\n .offset-lg-0 {\n margin-left: 0;\n }\n .offset-lg-1 {\n margin-left: 8.333333%;\n }\n .offset-lg-2 {\n margin-left: 16.666667%;\n }\n .offset-lg-3 {\n margin-left: 25%;\n }\n .offset-lg-4 {\n margin-left: 33.333333%;\n }\n .offset-lg-5 {\n margin-left: 41.666667%;\n }\n .offset-lg-6 {\n margin-left: 50%;\n }\n .offset-lg-7 {\n margin-left: 58.333333%;\n }\n .offset-lg-8 {\n margin-left: 66.666667%;\n }\n .offset-lg-9 {\n margin-left: 75%;\n }\n .offset-lg-10 {\n margin-left: 83.333333%;\n }\n .offset-lg-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 1200px) {\n .col-xl {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-xl-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-xl-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-xl-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-xl-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-xl-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-xl-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-xl-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-xl-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-xl-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-xl-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-xl-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-xl-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-xl-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-xl-first {\n order: -1;\n }\n .order-xl-last {\n order: 13;\n }\n .order-xl-0 {\n order: 0;\n }\n .order-xl-1 {\n order: 1;\n }\n .order-xl-2 {\n order: 2;\n }\n .order-xl-3 {\n order: 3;\n }\n .order-xl-4 {\n order: 4;\n }\n .order-xl-5 {\n order: 5;\n }\n .order-xl-6 {\n order: 6;\n }\n .order-xl-7 {\n order: 7;\n }\n .order-xl-8 {\n order: 8;\n }\n .order-xl-9 {\n order: 9;\n }\n .order-xl-10 {\n order: 10;\n }\n .order-xl-11 {\n order: 11;\n }\n .order-xl-12 {\n order: 12;\n }\n .offset-xl-0 {\n margin-left: 0;\n }\n .offset-xl-1 {\n margin-left: 8.333333%;\n }\n .offset-xl-2 {\n margin-left: 16.666667%;\n }\n .offset-xl-3 {\n margin-left: 25%;\n }\n .offset-xl-4 {\n margin-left: 33.333333%;\n }\n .offset-xl-5 {\n margin-left: 41.666667%;\n }\n .offset-xl-6 {\n margin-left: 50%;\n }\n .offset-xl-7 {\n margin-left: 58.333333%;\n }\n .offset-xl-8 {\n margin-left: 66.666667%;\n }\n .offset-xl-9 {\n margin-left: 75%;\n }\n .offset-xl-10 {\n margin-left: 83.333333%;\n }\n .offset-xl-11 {\n margin-left: 91.666667%;\n }\n}\n\n.d-none {\n display: none !important;\n}\n\n.d-inline {\n display: inline !important;\n}\n\n.d-inline-block {\n display: inline-block !important;\n}\n\n.d-block {\n display: block !important;\n}\n\n.d-table {\n display: table !important;\n}\n\n.d-table-row {\n display: table-row !important;\n}\n\n.d-table-cell {\n display: table-cell !important;\n}\n\n.d-flex {\n display: flex !important;\n}\n\n.d-inline-flex {\n display: inline-flex !important;\n}\n\n@media (min-width: 576px) {\n .d-sm-none {\n display: none !important;\n }\n .d-sm-inline {\n display: inline !important;\n }\n .d-sm-inline-block {\n display: inline-block !important;\n }\n .d-sm-block {\n display: block !important;\n }\n .d-sm-table {\n display: table !important;\n }\n .d-sm-table-row {\n display: table-row !important;\n }\n .d-sm-table-cell {\n display: table-cell !important;\n }\n .d-sm-flex {\n display: flex !important;\n }\n .d-sm-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 768px) {\n .d-md-none {\n display: none !important;\n }\n .d-md-inline {\n display: inline !important;\n }\n .d-md-inline-block {\n display: inline-block !important;\n }\n .d-md-block {\n display: block !important;\n }\n .d-md-table {\n display: table !important;\n }\n .d-md-table-row {\n display: table-row !important;\n }\n .d-md-table-cell {\n display: table-cell !important;\n }\n .d-md-flex {\n display: flex !important;\n }\n .d-md-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 992px) {\n .d-lg-none {\n display: none !important;\n }\n .d-lg-inline {\n display: inline !important;\n }\n .d-lg-inline-block {\n display: inline-block !important;\n }\n .d-lg-block {\n display: block !important;\n }\n .d-lg-table {\n display: table !important;\n }\n .d-lg-table-row {\n display: table-row !important;\n }\n .d-lg-table-cell {\n display: table-cell !important;\n }\n .d-lg-flex {\n display: flex !important;\n }\n .d-lg-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 1200px) {\n .d-xl-none {\n display: none !important;\n }\n .d-xl-inline {\n display: inline !important;\n }\n .d-xl-inline-block {\n display: inline-block !important;\n }\n .d-xl-block {\n display: block !important;\n }\n .d-xl-table {\n display: table !important;\n }\n .d-xl-table-row {\n display: table-row !important;\n }\n .d-xl-table-cell {\n display: table-cell !important;\n }\n .d-xl-flex {\n display: flex !important;\n }\n .d-xl-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media print {\n .d-print-none {\n display: none !important;\n }\n .d-print-inline {\n display: inline !important;\n }\n .d-print-inline-block {\n display: inline-block !important;\n }\n .d-print-block {\n display: block !important;\n }\n .d-print-table {\n display: table !important;\n }\n .d-print-table-row {\n display: table-row !important;\n }\n .d-print-table-cell {\n display: table-cell !important;\n }\n .d-print-flex {\n display: flex !important;\n }\n .d-print-inline-flex {\n display: inline-flex !important;\n }\n}\n\n.flex-row {\n flex-direction: row !important;\n}\n\n.flex-column {\n flex-direction: column !important;\n}\n\n.flex-row-reverse {\n flex-direction: row-reverse !important;\n}\n\n.flex-column-reverse {\n flex-direction: column-reverse !important;\n}\n\n.flex-wrap {\n flex-wrap: wrap !important;\n}\n\n.flex-nowrap {\n flex-wrap: nowrap !important;\n}\n\n.flex-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n}\n\n.flex-fill {\n flex: 1 1 auto !important;\n}\n\n.flex-grow-0 {\n flex-grow: 0 !important;\n}\n\n.flex-grow-1 {\n flex-grow: 1 !important;\n}\n\n.flex-shrink-0 {\n flex-shrink: 0 !important;\n}\n\n.flex-shrink-1 {\n flex-shrink: 1 !important;\n}\n\n.justify-content-start {\n justify-content: flex-start !important;\n}\n\n.justify-content-end {\n justify-content: flex-end !important;\n}\n\n.justify-content-center {\n justify-content: center !important;\n}\n\n.justify-content-between {\n justify-content: space-between !important;\n}\n\n.justify-content-around {\n justify-content: space-around !important;\n}\n\n.align-items-start {\n align-items: flex-start !important;\n}\n\n.align-items-end {\n align-items: flex-end !important;\n}\n\n.align-items-center {\n align-items: center !important;\n}\n\n.align-items-baseline {\n align-items: baseline !important;\n}\n\n.align-items-stretch {\n align-items: stretch !important;\n}\n\n.align-content-start {\n align-content: flex-start !important;\n}\n\n.align-content-end {\n align-content: flex-end !important;\n}\n\n.align-content-center {\n align-content: center !important;\n}\n\n.align-content-between {\n align-content: space-between !important;\n}\n\n.align-content-around {\n align-content: space-around !important;\n}\n\n.align-content-stretch {\n align-content: stretch !important;\n}\n\n.align-self-auto {\n align-self: auto !important;\n}\n\n.align-self-start {\n align-self: flex-start !important;\n}\n\n.align-self-end {\n align-self: flex-end !important;\n}\n\n.align-self-center {\n align-self: center !important;\n}\n\n.align-self-baseline {\n align-self: baseline !important;\n}\n\n.align-self-stretch {\n align-self: stretch !important;\n}\n\n@media (min-width: 576px) {\n .flex-sm-row {\n flex-direction: row !important;\n }\n .flex-sm-column {\n flex-direction: column !important;\n }\n .flex-sm-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-sm-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-sm-wrap {\n flex-wrap: wrap !important;\n }\n .flex-sm-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-sm-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-sm-fill {\n flex: 1 1 auto !important;\n }\n .flex-sm-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-sm-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-sm-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-sm-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-sm-start {\n justify-content: flex-start !important;\n }\n .justify-content-sm-end {\n justify-content: flex-end !important;\n }\n .justify-content-sm-center {\n justify-content: center !important;\n }\n .justify-content-sm-between {\n justify-content: space-between !important;\n }\n .justify-content-sm-around {\n justify-content: space-around !important;\n }\n .align-items-sm-start {\n align-items: flex-start !important;\n }\n .align-items-sm-end {\n align-items: flex-end !important;\n }\n .align-items-sm-center {\n align-items: center !important;\n }\n .align-items-sm-baseline {\n align-items: baseline !important;\n }\n .align-items-sm-stretch {\n align-items: stretch !important;\n }\n .align-content-sm-start {\n align-content: flex-start !important;\n }\n .align-content-sm-end {\n align-content: flex-end !important;\n }\n .align-content-sm-center {\n align-content: center !important;\n }\n .align-content-sm-between {\n align-content: space-between !important;\n }\n .align-content-sm-around {\n align-content: space-around !important;\n }\n .align-content-sm-stretch {\n align-content: stretch !important;\n }\n .align-self-sm-auto {\n align-self: auto !important;\n }\n .align-self-sm-start {\n align-self: flex-start !important;\n }\n .align-self-sm-end {\n align-self: flex-end !important;\n }\n .align-self-sm-center {\n align-self: center !important;\n }\n .align-self-sm-baseline {\n align-self: baseline !important;\n }\n .align-self-sm-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 768px) {\n .flex-md-row {\n flex-direction: row !important;\n }\n .flex-md-column {\n flex-direction: column !important;\n }\n .flex-md-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-md-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-md-wrap {\n flex-wrap: wrap !important;\n }\n .flex-md-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-md-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-md-fill {\n flex: 1 1 auto !important;\n }\n .flex-md-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-md-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-md-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-md-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-md-start {\n justify-content: flex-start !important;\n }\n .justify-content-md-end {\n justify-content: flex-end !important;\n }\n .justify-content-md-center {\n justify-content: center !important;\n }\n .justify-content-md-between {\n justify-content: space-between !important;\n }\n .justify-content-md-around {\n justify-content: space-around !important;\n }\n .align-items-md-start {\n align-items: flex-start !important;\n }\n .align-items-md-end {\n align-items: flex-end !important;\n }\n .align-items-md-center {\n align-items: center !important;\n }\n .align-items-md-baseline {\n align-items: baseline !important;\n }\n .align-items-md-stretch {\n align-items: stretch !important;\n }\n .align-content-md-start {\n align-content: flex-start !important;\n }\n .align-content-md-end {\n align-content: flex-end !important;\n }\n .align-content-md-center {\n align-content: center !important;\n }\n .align-content-md-between {\n align-content: space-between !important;\n }\n .align-content-md-around {\n align-content: space-around !important;\n }\n .align-content-md-stretch {\n align-content: stretch !important;\n }\n .align-self-md-auto {\n align-self: auto !important;\n }\n .align-self-md-start {\n align-self: flex-start !important;\n }\n .align-self-md-end {\n align-self: flex-end !important;\n }\n .align-self-md-center {\n align-self: center !important;\n }\n .align-self-md-baseline {\n align-self: baseline !important;\n }\n .align-self-md-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 992px) {\n .flex-lg-row {\n flex-direction: row !important;\n }\n .flex-lg-column {\n flex-direction: column !important;\n }\n .flex-lg-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-lg-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-lg-wrap {\n flex-wrap: wrap !important;\n }\n .flex-lg-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-lg-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-lg-fill {\n flex: 1 1 auto !important;\n }\n .flex-lg-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-lg-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-lg-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-lg-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-lg-start {\n justify-content: flex-start !important;\n }\n .justify-content-lg-end {\n justify-content: flex-end !important;\n }\n .justify-content-lg-center {\n justify-content: center !important;\n }\n .justify-content-lg-between {\n justify-content: space-between !important;\n }\n .justify-content-lg-around {\n justify-content: space-around !important;\n }\n .align-items-lg-start {\n align-items: flex-start !important;\n }\n .align-items-lg-end {\n align-items: flex-end !important;\n }\n .align-items-lg-center {\n align-items: center !important;\n }\n .align-items-lg-baseline {\n align-items: baseline !important;\n }\n .align-items-lg-stretch {\n align-items: stretch !important;\n }\n .align-content-lg-start {\n align-content: flex-start !important;\n }\n .align-content-lg-end {\n align-content: flex-end !important;\n }\n .align-content-lg-center {\n align-content: center !important;\n }\n .align-content-lg-between {\n align-content: space-between !important;\n }\n .align-content-lg-around {\n align-content: space-around !important;\n }\n .align-content-lg-stretch {\n align-content: stretch !important;\n }\n .align-self-lg-auto {\n align-self: auto !important;\n }\n .align-self-lg-start {\n align-self: flex-start !important;\n }\n .align-self-lg-end {\n align-self: flex-end !important;\n }\n .align-self-lg-center {\n align-self: center !important;\n }\n .align-self-lg-baseline {\n align-self: baseline !important;\n }\n .align-self-lg-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 1200px) {\n .flex-xl-row {\n flex-direction: row !important;\n }\n .flex-xl-column {\n flex-direction: column !important;\n }\n .flex-xl-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-xl-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-xl-wrap {\n flex-wrap: wrap !important;\n }\n .flex-xl-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-xl-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-xl-fill {\n flex: 1 1 auto !important;\n }\n .flex-xl-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-xl-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-xl-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-xl-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-xl-start {\n justify-content: flex-start !important;\n }\n .justify-content-xl-end {\n justify-content: flex-end !important;\n }\n .justify-content-xl-center {\n justify-content: center !important;\n }\n .justify-content-xl-between {\n justify-content: space-between !important;\n }\n .justify-content-xl-around {\n justify-content: space-around !important;\n }\n .align-items-xl-start {\n align-items: flex-start !important;\n }\n .align-items-xl-end {\n align-items: flex-end !important;\n }\n .align-items-xl-center {\n align-items: center !important;\n }\n .align-items-xl-baseline {\n align-items: baseline !important;\n }\n .align-items-xl-stretch {\n align-items: stretch !important;\n }\n .align-content-xl-start {\n align-content: flex-start !important;\n }\n .align-content-xl-end {\n align-content: flex-end !important;\n }\n .align-content-xl-center {\n align-content: center !important;\n }\n .align-content-xl-between {\n align-content: space-between !important;\n }\n .align-content-xl-around {\n align-content: space-around !important;\n }\n .align-content-xl-stretch {\n align-content: stretch !important;\n }\n .align-self-xl-auto {\n align-self: auto !important;\n }\n .align-self-xl-start {\n align-self: flex-start !important;\n }\n .align-self-xl-end {\n align-self: flex-end !important;\n }\n .align-self-xl-center {\n align-self: center !important;\n }\n .align-self-xl-baseline {\n align-self: baseline !important;\n }\n .align-self-xl-stretch {\n align-self: stretch !important;\n }\n}\n\n.m-0 {\n margin: 0 !important;\n}\n\n.mt-0,\n.my-0 {\n margin-top: 0 !important;\n}\n\n.mr-0,\n.mx-0 {\n margin-right: 0 !important;\n}\n\n.mb-0,\n.my-0 {\n margin-bottom: 0 !important;\n}\n\n.ml-0,\n.mx-0 {\n margin-left: 0 !important;\n}\n\n.m-1 {\n margin: 0.25rem !important;\n}\n\n.mt-1,\n.my-1 {\n margin-top: 0.25rem !important;\n}\n\n.mr-1,\n.mx-1 {\n margin-right: 0.25rem !important;\n}\n\n.mb-1,\n.my-1 {\n margin-bottom: 0.25rem !important;\n}\n\n.ml-1,\n.mx-1 {\n margin-left: 0.25rem !important;\n}\n\n.m-2 {\n margin: 0.5rem !important;\n}\n\n.mt-2,\n.my-2 {\n margin-top: 0.5rem !important;\n}\n\n.mr-2,\n.mx-2 {\n margin-right: 0.5rem !important;\n}\n\n.mb-2,\n.my-2 {\n margin-bottom: 0.5rem !important;\n}\n\n.ml-2,\n.mx-2 {\n margin-left: 0.5rem !important;\n}\n\n.m-3 {\n margin: 1rem !important;\n}\n\n.mt-3,\n.my-3 {\n margin-top: 1rem !important;\n}\n\n.mr-3,\n.mx-3 {\n margin-right: 1rem !important;\n}\n\n.mb-3,\n.my-3 {\n margin-bottom: 1rem !important;\n}\n\n.ml-3,\n.mx-3 {\n margin-left: 1rem !important;\n}\n\n.m-4 {\n margin: 1.5rem !important;\n}\n\n.mt-4,\n.my-4 {\n margin-top: 1.5rem !important;\n}\n\n.mr-4,\n.mx-4 {\n margin-right: 1.5rem !important;\n}\n\n.mb-4,\n.my-4 {\n margin-bottom: 1.5rem !important;\n}\n\n.ml-4,\n.mx-4 {\n margin-left: 1.5rem !important;\n}\n\n.m-5 {\n margin: 3rem !important;\n}\n\n.mt-5,\n.my-5 {\n margin-top: 3rem !important;\n}\n\n.mr-5,\n.mx-5 {\n margin-right: 3rem !important;\n}\n\n.mb-5,\n.my-5 {\n margin-bottom: 3rem !important;\n}\n\n.ml-5,\n.mx-5 {\n margin-left: 3rem !important;\n}\n\n.p-0 {\n padding: 0 !important;\n}\n\n.pt-0,\n.py-0 {\n padding-top: 0 !important;\n}\n\n.pr-0,\n.px-0 {\n padding-right: 0 !important;\n}\n\n.pb-0,\n.py-0 {\n padding-bottom: 0 !important;\n}\n\n.pl-0,\n.px-0 {\n padding-left: 0 !important;\n}\n\n.p-1 {\n padding: 0.25rem !important;\n}\n\n.pt-1,\n.py-1 {\n padding-top: 0.25rem !important;\n}\n\n.pr-1,\n.px-1 {\n padding-right: 0.25rem !important;\n}\n\n.pb-1,\n.py-1 {\n padding-bottom: 0.25rem !important;\n}\n\n.pl-1,\n.px-1 {\n padding-left: 0.25rem !important;\n}\n\n.p-2 {\n padding: 0.5rem !important;\n}\n\n.pt-2,\n.py-2 {\n padding-top: 0.5rem !important;\n}\n\n.pr-2,\n.px-2 {\n padding-right: 0.5rem !important;\n}\n\n.pb-2,\n.py-2 {\n padding-bottom: 0.5rem !important;\n}\n\n.pl-2,\n.px-2 {\n padding-left: 0.5rem !important;\n}\n\n.p-3 {\n padding: 1rem !important;\n}\n\n.pt-3,\n.py-3 {\n padding-top: 1rem !important;\n}\n\n.pr-3,\n.px-3 {\n padding-right: 1rem !important;\n}\n\n.pb-3,\n.py-3 {\n padding-bottom: 1rem !important;\n}\n\n.pl-3,\n.px-3 {\n padding-left: 1rem !important;\n}\n\n.p-4 {\n padding: 1.5rem !important;\n}\n\n.pt-4,\n.py-4 {\n padding-top: 1.5rem !important;\n}\n\n.pr-4,\n.px-4 {\n padding-right: 1.5rem !important;\n}\n\n.pb-4,\n.py-4 {\n padding-bottom: 1.5rem !important;\n}\n\n.pl-4,\n.px-4 {\n padding-left: 1.5rem !important;\n}\n\n.p-5 {\n padding: 3rem !important;\n}\n\n.pt-5,\n.py-5 {\n padding-top: 3rem !important;\n}\n\n.pr-5,\n.px-5 {\n padding-right: 3rem !important;\n}\n\n.pb-5,\n.py-5 {\n padding-bottom: 3rem !important;\n}\n\n.pl-5,\n.px-5 {\n padding-left: 3rem !important;\n}\n\n.m-n1 {\n margin: -0.25rem !important;\n}\n\n.mt-n1,\n.my-n1 {\n margin-top: -0.25rem !important;\n}\n\n.mr-n1,\n.mx-n1 {\n margin-right: -0.25rem !important;\n}\n\n.mb-n1,\n.my-n1 {\n margin-bottom: -0.25rem !important;\n}\n\n.ml-n1,\n.mx-n1 {\n margin-left: -0.25rem !important;\n}\n\n.m-n2 {\n margin: -0.5rem !important;\n}\n\n.mt-n2,\n.my-n2 {\n margin-top: -0.5rem !important;\n}\n\n.mr-n2,\n.mx-n2 {\n margin-right: -0.5rem !important;\n}\n\n.mb-n2,\n.my-n2 {\n margin-bottom: -0.5rem !important;\n}\n\n.ml-n2,\n.mx-n2 {\n margin-left: -0.5rem !important;\n}\n\n.m-n3 {\n margin: -1rem !important;\n}\n\n.mt-n3,\n.my-n3 {\n margin-top: -1rem !important;\n}\n\n.mr-n3,\n.mx-n3 {\n margin-right: -1rem !important;\n}\n\n.mb-n3,\n.my-n3 {\n margin-bottom: -1rem !important;\n}\n\n.ml-n3,\n.mx-n3 {\n margin-left: -1rem !important;\n}\n\n.m-n4 {\n margin: -1.5rem !important;\n}\n\n.mt-n4,\n.my-n4 {\n margin-top: -1.5rem !important;\n}\n\n.mr-n4,\n.mx-n4 {\n margin-right: -1.5rem !important;\n}\n\n.mb-n4,\n.my-n4 {\n margin-bottom: -1.5rem !important;\n}\n\n.ml-n4,\n.mx-n4 {\n margin-left: -1.5rem !important;\n}\n\n.m-n5 {\n margin: -3rem !important;\n}\n\n.mt-n5,\n.my-n5 {\n margin-top: -3rem !important;\n}\n\n.mr-n5,\n.mx-n5 {\n margin-right: -3rem !important;\n}\n\n.mb-n5,\n.my-n5 {\n margin-bottom: -3rem !important;\n}\n\n.ml-n5,\n.mx-n5 {\n margin-left: -3rem !important;\n}\n\n.m-auto {\n margin: auto !important;\n}\n\n.mt-auto,\n.my-auto {\n margin-top: auto !important;\n}\n\n.mr-auto,\n.mx-auto {\n margin-right: auto !important;\n}\n\n.mb-auto,\n.my-auto {\n margin-bottom: auto !important;\n}\n\n.ml-auto,\n.mx-auto {\n margin-left: auto !important;\n}\n\n@media (min-width: 576px) {\n .m-sm-0 {\n margin: 0 !important;\n }\n .mt-sm-0,\n .my-sm-0 {\n margin-top: 0 !important;\n }\n .mr-sm-0,\n .mx-sm-0 {\n margin-right: 0 !important;\n }\n .mb-sm-0,\n .my-sm-0 {\n margin-bottom: 0 !important;\n }\n .ml-sm-0,\n .mx-sm-0 {\n margin-left: 0 !important;\n }\n .m-sm-1 {\n margin: 0.25rem !important;\n }\n .mt-sm-1,\n .my-sm-1 {\n margin-top: 0.25rem !important;\n }\n .mr-sm-1,\n .mx-sm-1 {\n margin-right: 0.25rem !important;\n }\n .mb-sm-1,\n .my-sm-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-sm-1,\n .mx-sm-1 {\n margin-left: 0.25rem !important;\n }\n .m-sm-2 {\n margin: 0.5rem !important;\n }\n .mt-sm-2,\n .my-sm-2 {\n margin-top: 0.5rem !important;\n }\n .mr-sm-2,\n .mx-sm-2 {\n margin-right: 0.5rem !important;\n }\n .mb-sm-2,\n .my-sm-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-sm-2,\n .mx-sm-2 {\n margin-left: 0.5rem !important;\n }\n .m-sm-3 {\n margin: 1rem !important;\n }\n .mt-sm-3,\n .my-sm-3 {\n margin-top: 1rem !important;\n }\n .mr-sm-3,\n .mx-sm-3 {\n margin-right: 1rem !important;\n }\n .mb-sm-3,\n .my-sm-3 {\n margin-bottom: 1rem !important;\n }\n .ml-sm-3,\n .mx-sm-3 {\n margin-left: 1rem !important;\n }\n .m-sm-4 {\n margin: 1.5rem !important;\n }\n .mt-sm-4,\n .my-sm-4 {\n margin-top: 1.5rem !important;\n }\n .mr-sm-4,\n .mx-sm-4 {\n margin-right: 1.5rem !important;\n }\n .mb-sm-4,\n .my-sm-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-sm-4,\n .mx-sm-4 {\n margin-left: 1.5rem !important;\n }\n .m-sm-5 {\n margin: 3rem !important;\n }\n .mt-sm-5,\n .my-sm-5 {\n margin-top: 3rem !important;\n }\n .mr-sm-5,\n .mx-sm-5 {\n margin-right: 3rem !important;\n }\n .mb-sm-5,\n .my-sm-5 {\n margin-bottom: 3rem !important;\n }\n .ml-sm-5,\n .mx-sm-5 {\n margin-left: 3rem !important;\n }\n .p-sm-0 {\n padding: 0 !important;\n }\n .pt-sm-0,\n .py-sm-0 {\n padding-top: 0 !important;\n }\n .pr-sm-0,\n .px-sm-0 {\n padding-right: 0 !important;\n }\n .pb-sm-0,\n .py-sm-0 {\n padding-bottom: 0 !important;\n }\n .pl-sm-0,\n .px-sm-0 {\n padding-left: 0 !important;\n }\n .p-sm-1 {\n padding: 0.25rem !important;\n }\n .pt-sm-1,\n .py-sm-1 {\n padding-top: 0.25rem !important;\n }\n .pr-sm-1,\n .px-sm-1 {\n padding-right: 0.25rem !important;\n }\n .pb-sm-1,\n .py-sm-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-sm-1,\n .px-sm-1 {\n padding-left: 0.25rem !important;\n }\n .p-sm-2 {\n padding: 0.5rem !important;\n }\n .pt-sm-2,\n .py-sm-2 {\n padding-top: 0.5rem !important;\n }\n .pr-sm-2,\n .px-sm-2 {\n padding-right: 0.5rem !important;\n }\n .pb-sm-2,\n .py-sm-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-sm-2,\n .px-sm-2 {\n padding-left: 0.5rem !important;\n }\n .p-sm-3 {\n padding: 1rem !important;\n }\n .pt-sm-3,\n .py-sm-3 {\n padding-top: 1rem !important;\n }\n .pr-sm-3,\n .px-sm-3 {\n padding-right: 1rem !important;\n }\n .pb-sm-3,\n .py-sm-3 {\n padding-bottom: 1rem !important;\n }\n .pl-sm-3,\n .px-sm-3 {\n padding-left: 1rem !important;\n }\n .p-sm-4 {\n padding: 1.5rem !important;\n }\n .pt-sm-4,\n .py-sm-4 {\n padding-top: 1.5rem !important;\n }\n .pr-sm-4,\n .px-sm-4 {\n padding-right: 1.5rem !important;\n }\n .pb-sm-4,\n .py-sm-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-sm-4,\n .px-sm-4 {\n padding-left: 1.5rem !important;\n }\n .p-sm-5 {\n padding: 3rem !important;\n }\n .pt-sm-5,\n .py-sm-5 {\n padding-top: 3rem !important;\n }\n .pr-sm-5,\n .px-sm-5 {\n padding-right: 3rem !important;\n }\n .pb-sm-5,\n .py-sm-5 {\n padding-bottom: 3rem !important;\n }\n .pl-sm-5,\n .px-sm-5 {\n padding-left: 3rem !important;\n }\n .m-sm-n1 {\n margin: -0.25rem !important;\n }\n .mt-sm-n1,\n .my-sm-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-sm-n1,\n .mx-sm-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-sm-n1,\n .my-sm-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-sm-n1,\n .mx-sm-n1 {\n margin-left: -0.25rem !important;\n }\n .m-sm-n2 {\n margin: -0.5rem !important;\n }\n .mt-sm-n2,\n .my-sm-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-sm-n2,\n .mx-sm-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-sm-n2,\n .my-sm-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-sm-n2,\n .mx-sm-n2 {\n margin-left: -0.5rem !important;\n }\n .m-sm-n3 {\n margin: -1rem !important;\n }\n .mt-sm-n3,\n .my-sm-n3 {\n margin-top: -1rem !important;\n }\n .mr-sm-n3,\n .mx-sm-n3 {\n margin-right: -1rem !important;\n }\n .mb-sm-n3,\n .my-sm-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-sm-n3,\n .mx-sm-n3 {\n margin-left: -1rem !important;\n }\n .m-sm-n4 {\n margin: -1.5rem !important;\n }\n .mt-sm-n4,\n .my-sm-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-sm-n4,\n .mx-sm-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-sm-n4,\n .my-sm-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-sm-n4,\n .mx-sm-n4 {\n margin-left: -1.5rem !important;\n }\n .m-sm-n5 {\n margin: -3rem !important;\n }\n .mt-sm-n5,\n .my-sm-n5 {\n margin-top: -3rem !important;\n }\n .mr-sm-n5,\n .mx-sm-n5 {\n margin-right: -3rem !important;\n }\n .mb-sm-n5,\n .my-sm-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-sm-n5,\n .mx-sm-n5 {\n margin-left: -3rem !important;\n }\n .m-sm-auto {\n margin: auto !important;\n }\n .mt-sm-auto,\n .my-sm-auto {\n margin-top: auto !important;\n }\n .mr-sm-auto,\n .mx-sm-auto {\n margin-right: auto !important;\n }\n .mb-sm-auto,\n .my-sm-auto {\n margin-bottom: auto !important;\n }\n .ml-sm-auto,\n .mx-sm-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 768px) {\n .m-md-0 {\n margin: 0 !important;\n }\n .mt-md-0,\n .my-md-0 {\n margin-top: 0 !important;\n }\n .mr-md-0,\n .mx-md-0 {\n margin-right: 0 !important;\n }\n .mb-md-0,\n .my-md-0 {\n margin-bottom: 0 !important;\n }\n .ml-md-0,\n .mx-md-0 {\n margin-left: 0 !important;\n }\n .m-md-1 {\n margin: 0.25rem !important;\n }\n .mt-md-1,\n .my-md-1 {\n margin-top: 0.25rem !important;\n }\n .mr-md-1,\n .mx-md-1 {\n margin-right: 0.25rem !important;\n }\n .mb-md-1,\n .my-md-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-md-1,\n .mx-md-1 {\n margin-left: 0.25rem !important;\n }\n .m-md-2 {\n margin: 0.5rem !important;\n }\n .mt-md-2,\n .my-md-2 {\n margin-top: 0.5rem !important;\n }\n .mr-md-2,\n .mx-md-2 {\n margin-right: 0.5rem !important;\n }\n .mb-md-2,\n .my-md-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-md-2,\n .mx-md-2 {\n margin-left: 0.5rem !important;\n }\n .m-md-3 {\n margin: 1rem !important;\n }\n .mt-md-3,\n .my-md-3 {\n margin-top: 1rem !important;\n }\n .mr-md-3,\n .mx-md-3 {\n margin-right: 1rem !important;\n }\n .mb-md-3,\n .my-md-3 {\n margin-bottom: 1rem !important;\n }\n .ml-md-3,\n .mx-md-3 {\n margin-left: 1rem !important;\n }\n .m-md-4 {\n margin: 1.5rem !important;\n }\n .mt-md-4,\n .my-md-4 {\n margin-top: 1.5rem !important;\n }\n .mr-md-4,\n .mx-md-4 {\n margin-right: 1.5rem !important;\n }\n .mb-md-4,\n .my-md-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-md-4,\n .mx-md-4 {\n margin-left: 1.5rem !important;\n }\n .m-md-5 {\n margin: 3rem !important;\n }\n .mt-md-5,\n .my-md-5 {\n margin-top: 3rem !important;\n }\n .mr-md-5,\n .mx-md-5 {\n margin-right: 3rem !important;\n }\n .mb-md-5,\n .my-md-5 {\n margin-bottom: 3rem !important;\n }\n .ml-md-5,\n .mx-md-5 {\n margin-left: 3rem !important;\n }\n .p-md-0 {\n padding: 0 !important;\n }\n .pt-md-0,\n .py-md-0 {\n padding-top: 0 !important;\n }\n .pr-md-0,\n .px-md-0 {\n padding-right: 0 !important;\n }\n .pb-md-0,\n .py-md-0 {\n padding-bottom: 0 !important;\n }\n .pl-md-0,\n .px-md-0 {\n padding-left: 0 !important;\n }\n .p-md-1 {\n padding: 0.25rem !important;\n }\n .pt-md-1,\n .py-md-1 {\n padding-top: 0.25rem !important;\n }\n .pr-md-1,\n .px-md-1 {\n padding-right: 0.25rem !important;\n }\n .pb-md-1,\n .py-md-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-md-1,\n .px-md-1 {\n padding-left: 0.25rem !important;\n }\n .p-md-2 {\n padding: 0.5rem !important;\n }\n .pt-md-2,\n .py-md-2 {\n padding-top: 0.5rem !important;\n }\n .pr-md-2,\n .px-md-2 {\n padding-right: 0.5rem !important;\n }\n .pb-md-2,\n .py-md-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-md-2,\n .px-md-2 {\n padding-left: 0.5rem !important;\n }\n .p-md-3 {\n padding: 1rem !important;\n }\n .pt-md-3,\n .py-md-3 {\n padding-top: 1rem !important;\n }\n .pr-md-3,\n .px-md-3 {\n padding-right: 1rem !important;\n }\n .pb-md-3,\n .py-md-3 {\n padding-bottom: 1rem !important;\n }\n .pl-md-3,\n .px-md-3 {\n padding-left: 1rem !important;\n }\n .p-md-4 {\n padding: 1.5rem !important;\n }\n .pt-md-4,\n .py-md-4 {\n padding-top: 1.5rem !important;\n }\n .pr-md-4,\n .px-md-4 {\n padding-right: 1.5rem !important;\n }\n .pb-md-4,\n .py-md-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-md-4,\n .px-md-4 {\n padding-left: 1.5rem !important;\n }\n .p-md-5 {\n padding: 3rem !important;\n }\n .pt-md-5,\n .py-md-5 {\n padding-top: 3rem !important;\n }\n .pr-md-5,\n .px-md-5 {\n padding-right: 3rem !important;\n }\n .pb-md-5,\n .py-md-5 {\n padding-bottom: 3rem !important;\n }\n .pl-md-5,\n .px-md-5 {\n padding-left: 3rem !important;\n }\n .m-md-n1 {\n margin: -0.25rem !important;\n }\n .mt-md-n1,\n .my-md-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-md-n1,\n .mx-md-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-md-n1,\n .my-md-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-md-n1,\n .mx-md-n1 {\n margin-left: -0.25rem !important;\n }\n .m-md-n2 {\n margin: -0.5rem !important;\n }\n .mt-md-n2,\n .my-md-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-md-n2,\n .mx-md-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-md-n2,\n .my-md-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-md-n2,\n .mx-md-n2 {\n margin-left: -0.5rem !important;\n }\n .m-md-n3 {\n margin: -1rem !important;\n }\n .mt-md-n3,\n .my-md-n3 {\n margin-top: -1rem !important;\n }\n .mr-md-n3,\n .mx-md-n3 {\n margin-right: -1rem !important;\n }\n .mb-md-n3,\n .my-md-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-md-n3,\n .mx-md-n3 {\n margin-left: -1rem !important;\n }\n .m-md-n4 {\n margin: -1.5rem !important;\n }\n .mt-md-n4,\n .my-md-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-md-n4,\n .mx-md-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-md-n4,\n .my-md-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-md-n4,\n .mx-md-n4 {\n margin-left: -1.5rem !important;\n }\n .m-md-n5 {\n margin: -3rem !important;\n }\n .mt-md-n5,\n .my-md-n5 {\n margin-top: -3rem !important;\n }\n .mr-md-n5,\n .mx-md-n5 {\n margin-right: -3rem !important;\n }\n .mb-md-n5,\n .my-md-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-md-n5,\n .mx-md-n5 {\n margin-left: -3rem !important;\n }\n .m-md-auto {\n margin: auto !important;\n }\n .mt-md-auto,\n .my-md-auto {\n margin-top: auto !important;\n }\n .mr-md-auto,\n .mx-md-auto {\n margin-right: auto !important;\n }\n .mb-md-auto,\n .my-md-auto {\n margin-bottom: auto !important;\n }\n .ml-md-auto,\n .mx-md-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 992px) {\n .m-lg-0 {\n margin: 0 !important;\n }\n .mt-lg-0,\n .my-lg-0 {\n margin-top: 0 !important;\n }\n .mr-lg-0,\n .mx-lg-0 {\n margin-right: 0 !important;\n }\n .mb-lg-0,\n .my-lg-0 {\n margin-bottom: 0 !important;\n }\n .ml-lg-0,\n .mx-lg-0 {\n margin-left: 0 !important;\n }\n .m-lg-1 {\n margin: 0.25rem !important;\n }\n .mt-lg-1,\n .my-lg-1 {\n margin-top: 0.25rem !important;\n }\n .mr-lg-1,\n .mx-lg-1 {\n margin-right: 0.25rem !important;\n }\n .mb-lg-1,\n .my-lg-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-lg-1,\n .mx-lg-1 {\n margin-left: 0.25rem !important;\n }\n .m-lg-2 {\n margin: 0.5rem !important;\n }\n .mt-lg-2,\n .my-lg-2 {\n margin-top: 0.5rem !important;\n }\n .mr-lg-2,\n .mx-lg-2 {\n margin-right: 0.5rem !important;\n }\n .mb-lg-2,\n .my-lg-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-lg-2,\n .mx-lg-2 {\n margin-left: 0.5rem !important;\n }\n .m-lg-3 {\n margin: 1rem !important;\n }\n .mt-lg-3,\n .my-lg-3 {\n margin-top: 1rem !important;\n }\n .mr-lg-3,\n .mx-lg-3 {\n margin-right: 1rem !important;\n }\n .mb-lg-3,\n .my-lg-3 {\n margin-bottom: 1rem !important;\n }\n .ml-lg-3,\n .mx-lg-3 {\n margin-left: 1rem !important;\n }\n .m-lg-4 {\n margin: 1.5rem !important;\n }\n .mt-lg-4,\n .my-lg-4 {\n margin-top: 1.5rem !important;\n }\n .mr-lg-4,\n .mx-lg-4 {\n margin-right: 1.5rem !important;\n }\n .mb-lg-4,\n .my-lg-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-lg-4,\n .mx-lg-4 {\n margin-left: 1.5rem !important;\n }\n .m-lg-5 {\n margin: 3rem !important;\n }\n .mt-lg-5,\n .my-lg-5 {\n margin-top: 3rem !important;\n }\n .mr-lg-5,\n .mx-lg-5 {\n margin-right: 3rem !important;\n }\n .mb-lg-5,\n .my-lg-5 {\n margin-bottom: 3rem !important;\n }\n .ml-lg-5,\n .mx-lg-5 {\n margin-left: 3rem !important;\n }\n .p-lg-0 {\n padding: 0 !important;\n }\n .pt-lg-0,\n .py-lg-0 {\n padding-top: 0 !important;\n }\n .pr-lg-0,\n .px-lg-0 {\n padding-right: 0 !important;\n }\n .pb-lg-0,\n .py-lg-0 {\n padding-bottom: 0 !important;\n }\n .pl-lg-0,\n .px-lg-0 {\n padding-left: 0 !important;\n }\n .p-lg-1 {\n padding: 0.25rem !important;\n }\n .pt-lg-1,\n .py-lg-1 {\n padding-top: 0.25rem !important;\n }\n .pr-lg-1,\n .px-lg-1 {\n padding-right: 0.25rem !important;\n }\n .pb-lg-1,\n .py-lg-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-lg-1,\n .px-lg-1 {\n padding-left: 0.25rem !important;\n }\n .p-lg-2 {\n padding: 0.5rem !important;\n }\n .pt-lg-2,\n .py-lg-2 {\n padding-top: 0.5rem !important;\n }\n .pr-lg-2,\n .px-lg-2 {\n padding-right: 0.5rem !important;\n }\n .pb-lg-2,\n .py-lg-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-lg-2,\n .px-lg-2 {\n padding-left: 0.5rem !important;\n }\n .p-lg-3 {\n padding: 1rem !important;\n }\n .pt-lg-3,\n .py-lg-3 {\n padding-top: 1rem !important;\n }\n .pr-lg-3,\n .px-lg-3 {\n padding-right: 1rem !important;\n }\n .pb-lg-3,\n .py-lg-3 {\n padding-bottom: 1rem !important;\n }\n .pl-lg-3,\n .px-lg-3 {\n padding-left: 1rem !important;\n }\n .p-lg-4 {\n padding: 1.5rem !important;\n }\n .pt-lg-4,\n .py-lg-4 {\n padding-top: 1.5rem !important;\n }\n .pr-lg-4,\n .px-lg-4 {\n padding-right: 1.5rem !important;\n }\n .pb-lg-4,\n .py-lg-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-lg-4,\n .px-lg-4 {\n padding-left: 1.5rem !important;\n }\n .p-lg-5 {\n padding: 3rem !important;\n }\n .pt-lg-5,\n .py-lg-5 {\n padding-top: 3rem !important;\n }\n .pr-lg-5,\n .px-lg-5 {\n padding-right: 3rem !important;\n }\n .pb-lg-5,\n .py-lg-5 {\n padding-bottom: 3rem !important;\n }\n .pl-lg-5,\n .px-lg-5 {\n padding-left: 3rem !important;\n }\n .m-lg-n1 {\n margin: -0.25rem !important;\n }\n .mt-lg-n1,\n .my-lg-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-lg-n1,\n .mx-lg-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-lg-n1,\n .my-lg-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-lg-n1,\n .mx-lg-n1 {\n margin-left: -0.25rem !important;\n }\n .m-lg-n2 {\n margin: -0.5rem !important;\n }\n .mt-lg-n2,\n .my-lg-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-lg-n2,\n .mx-lg-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-lg-n2,\n .my-lg-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-lg-n2,\n .mx-lg-n2 {\n margin-left: -0.5rem !important;\n }\n .m-lg-n3 {\n margin: -1rem !important;\n }\n .mt-lg-n3,\n .my-lg-n3 {\n margin-top: -1rem !important;\n }\n .mr-lg-n3,\n .mx-lg-n3 {\n margin-right: -1rem !important;\n }\n .mb-lg-n3,\n .my-lg-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-lg-n3,\n .mx-lg-n3 {\n margin-left: -1rem !important;\n }\n .m-lg-n4 {\n margin: -1.5rem !important;\n }\n .mt-lg-n4,\n .my-lg-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-lg-n4,\n .mx-lg-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-lg-n4,\n .my-lg-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-lg-n4,\n .mx-lg-n4 {\n margin-left: -1.5rem !important;\n }\n .m-lg-n5 {\n margin: -3rem !important;\n }\n .mt-lg-n5,\n .my-lg-n5 {\n margin-top: -3rem !important;\n }\n .mr-lg-n5,\n .mx-lg-n5 {\n margin-right: -3rem !important;\n }\n .mb-lg-n5,\n .my-lg-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-lg-n5,\n .mx-lg-n5 {\n margin-left: -3rem !important;\n }\n .m-lg-auto {\n margin: auto !important;\n }\n .mt-lg-auto,\n .my-lg-auto {\n margin-top: auto !important;\n }\n .mr-lg-auto,\n .mx-lg-auto {\n margin-right: auto !important;\n }\n .mb-lg-auto,\n .my-lg-auto {\n margin-bottom: auto !important;\n }\n .ml-lg-auto,\n .mx-lg-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 1200px) {\n .m-xl-0 {\n margin: 0 !important;\n }\n .mt-xl-0,\n .my-xl-0 {\n margin-top: 0 !important;\n }\n .mr-xl-0,\n .mx-xl-0 {\n margin-right: 0 !important;\n }\n .mb-xl-0,\n .my-xl-0 {\n margin-bottom: 0 !important;\n }\n .ml-xl-0,\n .mx-xl-0 {\n margin-left: 0 !important;\n }\n .m-xl-1 {\n margin: 0.25rem !important;\n }\n .mt-xl-1,\n .my-xl-1 {\n margin-top: 0.25rem !important;\n }\n .mr-xl-1,\n .mx-xl-1 {\n margin-right: 0.25rem !important;\n }\n .mb-xl-1,\n .my-xl-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-xl-1,\n .mx-xl-1 {\n margin-left: 0.25rem !important;\n }\n .m-xl-2 {\n margin: 0.5rem !important;\n }\n .mt-xl-2,\n .my-xl-2 {\n margin-top: 0.5rem !important;\n }\n .mr-xl-2,\n .mx-xl-2 {\n margin-right: 0.5rem !important;\n }\n .mb-xl-2,\n .my-xl-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-xl-2,\n .mx-xl-2 {\n margin-left: 0.5rem !important;\n }\n .m-xl-3 {\n margin: 1rem !important;\n }\n .mt-xl-3,\n .my-xl-3 {\n margin-top: 1rem !important;\n }\n .mr-xl-3,\n .mx-xl-3 {\n margin-right: 1rem !important;\n }\n .mb-xl-3,\n .my-xl-3 {\n margin-bottom: 1rem !important;\n }\n .ml-xl-3,\n .mx-xl-3 {\n margin-left: 1rem !important;\n }\n .m-xl-4 {\n margin: 1.5rem !important;\n }\n .mt-xl-4,\n .my-xl-4 {\n margin-top: 1.5rem !important;\n }\n .mr-xl-4,\n .mx-xl-4 {\n margin-right: 1.5rem !important;\n }\n .mb-xl-4,\n .my-xl-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-xl-4,\n .mx-xl-4 {\n margin-left: 1.5rem !important;\n }\n .m-xl-5 {\n margin: 3rem !important;\n }\n .mt-xl-5,\n .my-xl-5 {\n margin-top: 3rem !important;\n }\n .mr-xl-5,\n .mx-xl-5 {\n margin-right: 3rem !important;\n }\n .mb-xl-5,\n .my-xl-5 {\n margin-bottom: 3rem !important;\n }\n .ml-xl-5,\n .mx-xl-5 {\n margin-left: 3rem !important;\n }\n .p-xl-0 {\n padding: 0 !important;\n }\n .pt-xl-0,\n .py-xl-0 {\n padding-top: 0 !important;\n }\n .pr-xl-0,\n .px-xl-0 {\n padding-right: 0 !important;\n }\n .pb-xl-0,\n .py-xl-0 {\n padding-bottom: 0 !important;\n }\n .pl-xl-0,\n .px-xl-0 {\n padding-left: 0 !important;\n }\n .p-xl-1 {\n padding: 0.25rem !important;\n }\n .pt-xl-1,\n .py-xl-1 {\n padding-top: 0.25rem !important;\n }\n .pr-xl-1,\n .px-xl-1 {\n padding-right: 0.25rem !important;\n }\n .pb-xl-1,\n .py-xl-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-xl-1,\n .px-xl-1 {\n padding-left: 0.25rem !important;\n }\n .p-xl-2 {\n padding: 0.5rem !important;\n }\n .pt-xl-2,\n .py-xl-2 {\n padding-top: 0.5rem !important;\n }\n .pr-xl-2,\n .px-xl-2 {\n padding-right: 0.5rem !important;\n }\n .pb-xl-2,\n .py-xl-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-xl-2,\n .px-xl-2 {\n padding-left: 0.5rem !important;\n }\n .p-xl-3 {\n padding: 1rem !important;\n }\n .pt-xl-3,\n .py-xl-3 {\n padding-top: 1rem !important;\n }\n .pr-xl-3,\n .px-xl-3 {\n padding-right: 1rem !important;\n }\n .pb-xl-3,\n .py-xl-3 {\n padding-bottom: 1rem !important;\n }\n .pl-xl-3,\n .px-xl-3 {\n padding-left: 1rem !important;\n }\n .p-xl-4 {\n padding: 1.5rem !important;\n }\n .pt-xl-4,\n .py-xl-4 {\n padding-top: 1.5rem !important;\n }\n .pr-xl-4,\n .px-xl-4 {\n padding-right: 1.5rem !important;\n }\n .pb-xl-4,\n .py-xl-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-xl-4,\n .px-xl-4 {\n padding-left: 1.5rem !important;\n }\n .p-xl-5 {\n padding: 3rem !important;\n }\n .pt-xl-5,\n .py-xl-5 {\n padding-top: 3rem !important;\n }\n .pr-xl-5,\n .px-xl-5 {\n padding-right: 3rem !important;\n }\n .pb-xl-5,\n .py-xl-5 {\n padding-bottom: 3rem !important;\n }\n .pl-xl-5,\n .px-xl-5 {\n padding-left: 3rem !important;\n }\n .m-xl-n1 {\n margin: -0.25rem !important;\n }\n .mt-xl-n1,\n .my-xl-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-xl-n1,\n .mx-xl-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-xl-n1,\n .my-xl-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-xl-n1,\n .mx-xl-n1 {\n margin-left: -0.25rem !important;\n }\n .m-xl-n2 {\n margin: -0.5rem !important;\n }\n .mt-xl-n2,\n .my-xl-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-xl-n2,\n .mx-xl-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-xl-n2,\n .my-xl-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-xl-n2,\n .mx-xl-n2 {\n margin-left: -0.5rem !important;\n }\n .m-xl-n3 {\n margin: -1rem !important;\n }\n .mt-xl-n3,\n .my-xl-n3 {\n margin-top: -1rem !important;\n }\n .mr-xl-n3,\n .mx-xl-n3 {\n margin-right: -1rem !important;\n }\n .mb-xl-n3,\n .my-xl-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-xl-n3,\n .mx-xl-n3 {\n margin-left: -1rem !important;\n }\n .m-xl-n4 {\n margin: -1.5rem !important;\n }\n .mt-xl-n4,\n .my-xl-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-xl-n4,\n .mx-xl-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-xl-n4,\n .my-xl-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-xl-n4,\n .mx-xl-n4 {\n margin-left: -1.5rem !important;\n }\n .m-xl-n5 {\n margin: -3rem !important;\n }\n .mt-xl-n5,\n .my-xl-n5 {\n margin-top: -3rem !important;\n }\n .mr-xl-n5,\n .mx-xl-n5 {\n margin-right: -3rem !important;\n }\n .mb-xl-n5,\n .my-xl-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-xl-n5,\n .mx-xl-n5 {\n margin-left: -3rem !important;\n }\n .m-xl-auto {\n margin: auto !important;\n }\n .mt-xl-auto,\n .my-xl-auto {\n margin-top: auto !important;\n }\n .mr-xl-auto,\n .mx-xl-auto {\n margin-right: auto !important;\n }\n .mb-xl-auto,\n .my-xl-auto {\n margin-bottom: auto !important;\n }\n .ml-xl-auto,\n .mx-xl-auto {\n margin-left: auto !important;\n }\n}\n\n/*# sourceMappingURL=bootstrap-grid.css.map */","// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n@if $enable-grid-classes {\n .container {\n @include make-container();\n @include make-container-max-widths();\n }\n}\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but with 100% width for\n// fluid, full width layouts.\n\n@if $enable-grid-classes {\n .container-fluid {\n @include make-container();\n }\n}\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n@if $enable-grid-classes {\n .row {\n @include make-row();\n }\n\n // Remove the negative margin from default .row, then the horizontal padding\n // from all immediate children columns (to prevent runaway style inheritance).\n .no-gutters {\n margin-right: 0;\n margin-left: 0;\n\n > .col,\n > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n }\n }\n}\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n@if $enable-grid-classes {\n @include make-grid-columns();\n}\n","/// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n@mixin make-container($gutter: $grid-gutter-width) {\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n margin-right: auto;\n margin-left: auto;\n}\n\n\n// For each breakpoint, define the maximum width of the container in a media query\n@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) {\n @each $breakpoint, $container-max-width in $max-widths {\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n max-width: $container-max-width;\n }\n }\n}\n\n@mixin make-row($gutter: $grid-gutter-width) {\n display: flex;\n flex-wrap: wrap;\n margin-right: -$gutter / 2;\n margin-left: -$gutter / 2;\n}\n\n@mixin make-col-ready($gutter: $grid-gutter-width) {\n position: relative;\n // Prevent columns from becoming too narrow when at smaller grid tiers by\n // always setting `width: 100%;`. This works because we use `flex` values\n // later on to override this initial width.\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n}\n\n@mixin make-col($size, $columns: $grid-columns) {\n flex: 0 0 percentage($size / $columns);\n // Add a `max-width` to ensure content within each column does not blow out\n // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari\n // do not appear to require this.\n max-width: percentage($size / $columns);\n}\n\n@mixin make-col-offset($size, $columns: $grid-columns) {\n $num: $size / $columns;\n margin-left: if($num == 0, 0, percentage($num));\n}\n","// Breakpoint viewport sizes and media queries.\n//\n// Breakpoints are defined as a map of (name: minimum width), order from small to large:\n//\n// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)\n//\n// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.\n\n// Name of the next breakpoint, or null for the last breakpoint.\n//\n// >> breakpoint-next(sm)\n// md\n// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// md\n// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))\n// md\n@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {\n $n: index($breakpoint-names, $name);\n @return if($n != null and $n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);\n}\n\n// Minimum breakpoint width. Null for the smallest (first) breakpoint.\n//\n// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 576px\n@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {\n $min: map-get($breakpoints, $name);\n @return if($min != 0, $min, null);\n}\n\n// Maximum breakpoint width. Null for the largest (last) breakpoint.\n// The maximum value is calculated as the minimum of the next one less 0.02px\n// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths.\n// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max\n// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.\n// See https://bugs.webkit.org/show_bug.cgi?id=178261\n//\n// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 767.98px\n@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {\n $next: breakpoint-next($name, $breakpoints);\n @return if($next, breakpoint-min($next, $breakpoints) - .02, null);\n}\n\n// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.\n// Useful for making responsive utilities.\n//\n// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"\" (Returns a blank string)\n// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"-sm\"\n@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {\n @return if(breakpoint-min($name, $breakpoints) == null, \"\", \"-#{$name}\");\n}\n\n// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.\n// Makes the @content apply to the given breakpoint and wider.\n@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n @if $min {\n @media (min-width: $min) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media of at most the maximum breakpoint width. No query for the largest breakpoint.\n// Makes the @content apply to the given breakpoint and narrower.\n@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {\n $max: breakpoint-max($name, $breakpoints);\n @if $max {\n @media (max-width: $max) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media that spans multiple breakpoint widths.\n// Makes the @content apply between the min and max breakpoints\n@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($lower, $breakpoints);\n $max: breakpoint-max($upper, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($lower, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($upper, $breakpoints) {\n @content;\n }\n }\n}\n\n// Media between the breakpoint's minimum and maximum widths.\n// No minimum for the smallest breakpoint, and no maximum for the largest one.\n// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.\n@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n $max: breakpoint-max($name, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($name, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($name, $breakpoints) {\n @content;\n }\n }\n}\n","// Variables\n//\n// Variables should follow the `$component-state-property-size` formula for\n// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs.\n\n// Color system\n\n$white: #fff !default;\n$gray-100: #f8f9fa !default;\n$gray-200: #e9ecef !default;\n$gray-300: #dee2e6 !default;\n$gray-400: #ced4da !default;\n$gray-500: #adb5bd !default;\n$gray-600: #6c757d !default;\n$gray-700: #495057 !default;\n$gray-800: #343a40 !default;\n$gray-900: #212529 !default;\n$black: #000 !default;\n\n$grays: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$grays: map-merge(\n (\n \"100\": $gray-100,\n \"200\": $gray-200,\n \"300\": $gray-300,\n \"400\": $gray-400,\n \"500\": $gray-500,\n \"600\": $gray-600,\n \"700\": $gray-700,\n \"800\": $gray-800,\n \"900\": $gray-900\n ),\n $grays\n);\n\n$blue: #007bff !default;\n$indigo: #6610f2 !default;\n$purple: #6f42c1 !default;\n$pink: #e83e8c !default;\n$red: #dc3545 !default;\n$orange: #fd7e14 !default;\n$yellow: #ffc107 !default;\n$green: #28a745 !default;\n$teal: #20c997 !default;\n$cyan: #17a2b8 !default;\n\n$colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$colors: map-merge(\n (\n \"blue\": $blue,\n \"indigo\": $indigo,\n \"purple\": $purple,\n \"pink\": $pink,\n \"red\": $red,\n \"orange\": $orange,\n \"yellow\": $yellow,\n \"green\": $green,\n \"teal\": $teal,\n \"cyan\": $cyan,\n \"white\": $white,\n \"gray\": $gray-600,\n \"gray-dark\": $gray-800\n ),\n $colors\n);\n\n$primary: $blue !default;\n$secondary: $gray-600 !default;\n$success: $green !default;\n$info: $cyan !default;\n$warning: $yellow !default;\n$danger: $red !default;\n$light: $gray-100 !default;\n$dark: $gray-800 !default;\n\n$theme-colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$theme-colors: map-merge(\n (\n \"primary\": $primary,\n \"secondary\": $secondary,\n \"success\": $success,\n \"info\": $info,\n \"warning\": $warning,\n \"danger\": $danger,\n \"light\": $light,\n \"dark\": $dark\n ),\n $theme-colors\n);\n\n// Set a specific jump point for requesting color jumps\n$theme-color-interval: 8% !default;\n\n// The yiq lightness value that determines when the lightness of color changes from \"dark\" to \"light\". Acceptable values are between 0 and 255.\n$yiq-contrasted-threshold: 150 !default;\n\n// Customize the light and dark text colors for use in our YIQ color contrast function.\n$yiq-text-dark: $gray-900 !default;\n$yiq-text-light: $white !default;\n\n\n// Options\n//\n// Quickly modify global styling by enabling or disabling optional features.\n\n$enable-caret: true !default;\n$enable-rounded: true !default;\n$enable-shadows: false !default;\n$enable-gradients: false !default;\n$enable-transitions: true !default;\n$enable-prefers-reduced-motion-media-query: true !default;\n$enable-hover-media-query: false !default; // Deprecated, no longer affects any compiled CSS\n$enable-grid-classes: true !default;\n$enable-pointer-cursor-for-buttons: true !default;\n$enable-print-styles: true !default;\n$enable-responsive-font-sizes: false !default;\n$enable-validation-icons: true !default;\n$enable-deprecation-messages: true !default;\n\n\n// Spacing\n//\n// Control the default styling of most Bootstrap elements by modifying these\n// variables. Mostly focused on spacing.\n// You can add more entries to the $spacers map, should you need more variation.\n\n$spacer: 1rem !default;\n$spacers: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$spacers: map-merge(\n (\n 0: 0,\n 1: ($spacer * .25),\n 2: ($spacer * .5),\n 3: $spacer,\n 4: ($spacer * 1.5),\n 5: ($spacer * 3)\n ),\n $spacers\n);\n\n// This variable affects the `.h-*` and `.w-*` classes.\n$sizes: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$sizes: map-merge(\n (\n 25: 25%,\n 50: 50%,\n 75: 75%,\n 100: 100%,\n auto: auto\n ),\n $sizes\n);\n\n\n// Body\n//\n// Settings for the `` element.\n\n$body-bg: $white !default;\n$body-color: $gray-900 !default;\n\n\n// Links\n//\n// Style anchor elements.\n\n$link-color: theme-color(\"primary\") !default;\n$link-decoration: none !default;\n$link-hover-color: darken($link-color, 15%) !default;\n$link-hover-decoration: underline !default;\n// Darken percentage for links with `.text-*` class (e.g. `.text-success`)\n$emphasized-link-hover-darken-percentage: 15% !default;\n\n// Paragraphs\n//\n// Style p element.\n\n$paragraph-margin-bottom: 1rem !default;\n\n\n// Grid breakpoints\n//\n// Define the minimum dimensions at which your layout will change,\n// adapting to different screen sizes, for use in media queries.\n\n$grid-breakpoints: (\n xs: 0,\n sm: 576px,\n md: 768px,\n lg: 992px,\n xl: 1200px\n) !default;\n\n@include _assert-ascending($grid-breakpoints, \"$grid-breakpoints\");\n@include _assert-starts-at-zero($grid-breakpoints, \"$grid-breakpoints\");\n\n\n// Grid containers\n//\n// Define the maximum width of `.container` for different screen sizes.\n\n$container-max-widths: (\n sm: 540px,\n md: 720px,\n lg: 960px,\n xl: 1140px\n) !default;\n\n@include _assert-ascending($container-max-widths, \"$container-max-widths\");\n\n\n// Grid columns\n//\n// Set the number of columns and specify the width of the gutters.\n\n$grid-columns: 12 !default;\n$grid-gutter-width: 30px !default;\n\n\n// Components\n//\n// Define common padding and border radius sizes and more.\n\n$line-height-lg: 1.5 !default;\n$line-height-sm: 1.5 !default;\n\n$border-width: 1px !default;\n$border-color: $gray-300 !default;\n\n$border-radius: .25rem !default;\n$border-radius-lg: .3rem !default;\n$border-radius-sm: .2rem !default;\n\n$rounded-pill: 50rem !default;\n\n$box-shadow-sm: 0 .125rem .25rem rgba($black, .075) !default;\n$box-shadow: 0 .5rem 1rem rgba($black, .15) !default;\n$box-shadow-lg: 0 1rem 3rem rgba($black, .175) !default;\n\n$component-active-color: $white !default;\n$component-active-bg: theme-color(\"primary\") !default;\n\n$caret-width: .3em !default;\n$caret-vertical-align: $caret-width * .85 !default;\n$caret-spacing: $caret-width * .85 !default;\n\n$transition-base: all .2s ease-in-out !default;\n$transition-fade: opacity .15s linear !default;\n$transition-collapse: height .35s ease !default;\n\n$embed-responsive-aspect-ratios: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$embed-responsive-aspect-ratios: join(\n (\n (21 9),\n (16 9),\n (4 3),\n (1 1),\n ),\n $embed-responsive-aspect-ratios\n);\n\n// Typography\n//\n// Font, line-height, and color for body text, headings, and more.\n\n// stylelint-disable value-keyword-case\n$font-family-sans-serif: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\" !default;\n$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace !default;\n$font-family-base: $font-family-sans-serif !default;\n// stylelint-enable value-keyword-case\n\n$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`\n$font-size-lg: $font-size-base * 1.25 !default;\n$font-size-sm: $font-size-base * .875 !default;\n\n$font-weight-lighter: lighter !default;\n$font-weight-light: 300 !default;\n$font-weight-normal: 400 !default;\n$font-weight-bold: 700 !default;\n$font-weight-bolder: bolder !default;\n\n$font-weight-base: $font-weight-normal !default;\n$line-height-base: 1.5 !default;\n\n$h1-font-size: $font-size-base * 2.5 !default;\n$h2-font-size: $font-size-base * 2 !default;\n$h3-font-size: $font-size-base * 1.75 !default;\n$h4-font-size: $font-size-base * 1.5 !default;\n$h5-font-size: $font-size-base * 1.25 !default;\n$h6-font-size: $font-size-base !default;\n\n$headings-margin-bottom: $spacer / 2 !default;\n$headings-font-family: null !default;\n$headings-font-weight: 500 !default;\n$headings-line-height: 1.2 !default;\n$headings-color: null !default;\n\n$display1-size: 6rem !default;\n$display2-size: 5.5rem !default;\n$display3-size: 4.5rem !default;\n$display4-size: 3.5rem !default;\n\n$display1-weight: 300 !default;\n$display2-weight: 300 !default;\n$display3-weight: 300 !default;\n$display4-weight: 300 !default;\n$display-line-height: $headings-line-height !default;\n\n$lead-font-size: $font-size-base * 1.25 !default;\n$lead-font-weight: 300 !default;\n\n$small-font-size: 80% !default;\n\n$text-muted: $gray-600 !default;\n\n$blockquote-small-color: $gray-600 !default;\n$blockquote-small-font-size: $small-font-size !default;\n$blockquote-font-size: $font-size-base * 1.25 !default;\n\n$hr-border-color: rgba($black, .1) !default;\n$hr-border-width: $border-width !default;\n\n$mark-padding: .2em !default;\n\n$dt-font-weight: $font-weight-bold !default;\n\n$kbd-box-shadow: inset 0 -.1rem 0 rgba($black, .25) !default;\n$nested-kbd-font-weight: $font-weight-bold !default;\n\n$list-inline-padding: .5rem !default;\n\n$mark-bg: #fcf8e3 !default;\n\n$hr-margin-y: $spacer !default;\n\n\n// Tables\n//\n// Customizes the `.table` component with basic values, each used across all table variations.\n\n$table-cell-padding: .75rem !default;\n$table-cell-padding-sm: .3rem !default;\n\n$table-color: $body-color !default;\n$table-bg: null !default;\n$table-accent-bg: rgba($black, .05) !default;\n$table-hover-color: $table-color !default;\n$table-hover-bg: rgba($black, .075) !default;\n$table-active-bg: $table-hover-bg !default;\n\n$table-border-width: $border-width !default;\n$table-border-color: $border-color !default;\n\n$table-head-bg: $gray-200 !default;\n$table-head-color: $gray-700 !default;\n\n$table-dark-color: $white !default;\n$table-dark-bg: $gray-800 !default;\n$table-dark-accent-bg: rgba($white, .05) !default;\n$table-dark-hover-color: $table-dark-color !default;\n$table-dark-hover-bg: rgba($white, .075) !default;\n$table-dark-border-color: lighten($table-dark-bg, 7.5%) !default;\n$table-dark-color: $white !default;\n\n$table-striped-order: odd !default;\n\n$table-caption-color: $text-muted !default;\n\n$table-bg-level: -9 !default;\n$table-border-level: -6 !default;\n\n\n// Buttons + Forms\n//\n// Shared variables that are reassigned to `$input-` and `$btn-` specific variables.\n\n$input-btn-padding-y: .375rem !default;\n$input-btn-padding-x: .75rem !default;\n$input-btn-font-family: null !default;\n$input-btn-font-size: $font-size-base !default;\n$input-btn-line-height: $line-height-base !default;\n\n$input-btn-focus-width: .2rem !default;\n$input-btn-focus-color: rgba($component-active-bg, .25) !default;\n$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default;\n\n$input-btn-padding-y-sm: .25rem !default;\n$input-btn-padding-x-sm: .5rem !default;\n$input-btn-font-size-sm: $font-size-sm !default;\n$input-btn-line-height-sm: $line-height-sm !default;\n\n$input-btn-padding-y-lg: .5rem !default;\n$input-btn-padding-x-lg: 1rem !default;\n$input-btn-font-size-lg: $font-size-lg !default;\n$input-btn-line-height-lg: $line-height-lg !default;\n\n$input-btn-border-width: $border-width !default;\n\n\n// Buttons\n//\n// For each of Bootstrap's buttons, define text, background, and border color.\n\n$btn-padding-y: $input-btn-padding-y !default;\n$btn-padding-x: $input-btn-padding-x !default;\n$btn-font-family: $input-btn-font-family !default;\n$btn-font-size: $input-btn-font-size !default;\n$btn-line-height: $input-btn-line-height !default;\n\n$btn-padding-y-sm: $input-btn-padding-y-sm !default;\n$btn-padding-x-sm: $input-btn-padding-x-sm !default;\n$btn-font-size-sm: $input-btn-font-size-sm !default;\n$btn-line-height-sm: $input-btn-line-height-sm !default;\n\n$btn-padding-y-lg: $input-btn-padding-y-lg !default;\n$btn-padding-x-lg: $input-btn-padding-x-lg !default;\n$btn-font-size-lg: $input-btn-font-size-lg !default;\n$btn-line-height-lg: $input-btn-line-height-lg !default;\n\n$btn-border-width: $input-btn-border-width !default;\n\n$btn-font-weight: $font-weight-normal !default;\n$btn-box-shadow: inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default;\n$btn-focus-width: $input-btn-focus-width !default;\n$btn-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$btn-disabled-opacity: .65 !default;\n$btn-active-box-shadow: inset 0 3px 5px rgba($black, .125) !default;\n\n$btn-link-disabled-color: $gray-600 !default;\n\n$btn-block-spacing-y: .5rem !default;\n\n// Allows for customizing button radius independently from global border radius\n$btn-border-radius: $border-radius !default;\n$btn-border-radius-lg: $border-radius-lg !default;\n$btn-border-radius-sm: $border-radius-sm !default;\n\n$btn-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n\n// Forms\n\n$label-margin-bottom: .5rem !default;\n\n$input-padding-y: $input-btn-padding-y !default;\n$input-padding-x: $input-btn-padding-x !default;\n$input-font-family: $input-btn-font-family !default;\n$input-font-size: $input-btn-font-size !default;\n$input-font-weight: $font-weight-base !default;\n$input-line-height: $input-btn-line-height !default;\n\n$input-padding-y-sm: $input-btn-padding-y-sm !default;\n$input-padding-x-sm: $input-btn-padding-x-sm !default;\n$input-font-size-sm: $input-btn-font-size-sm !default;\n$input-line-height-sm: $input-btn-line-height-sm !default;\n\n$input-padding-y-lg: $input-btn-padding-y-lg !default;\n$input-padding-x-lg: $input-btn-padding-x-lg !default;\n$input-font-size-lg: $input-btn-font-size-lg !default;\n$input-line-height-lg: $input-btn-line-height-lg !default;\n\n$input-bg: $white !default;\n$input-disabled-bg: $gray-200 !default;\n\n$input-color: $gray-700 !default;\n$input-border-color: $gray-400 !default;\n$input-border-width: $input-btn-border-width !default;\n$input-box-shadow: inset 0 1px 1px rgba($black, .075) !default;\n\n$input-border-radius: $border-radius !default;\n$input-border-radius-lg: $border-radius-lg !default;\n$input-border-radius-sm: $border-radius-sm !default;\n\n$input-focus-bg: $input-bg !default;\n$input-focus-border-color: lighten($component-active-bg, 25%) !default;\n$input-focus-color: $input-color !default;\n$input-focus-width: $input-btn-focus-width !default;\n$input-focus-box-shadow: $input-btn-focus-box-shadow !default;\n\n$input-placeholder-color: $gray-600 !default;\n$input-plaintext-color: $body-color !default;\n\n$input-height-border: $input-border-width * 2 !default;\n\n$input-height-inner: calc(#{$input-line-height * 1em} + #{$input-padding-y * 2}) !default;\n$input-height-inner-half: calc(#{$input-line-height * .5em} + #{$input-padding-y}) !default;\n$input-height-inner-quarter: calc(#{$input-line-height * .25em} + #{$input-padding-y / 2}) !default;\n\n$input-height: calc(#{$input-line-height * 1em} + #{$input-padding-y * 2} + #{$input-height-border}) !default;\n$input-height-sm: calc(#{$input-line-height-sm * 1em} + #{$input-btn-padding-y-sm * 2} + #{$input-height-border}) !default;\n$input-height-lg: calc(#{$input-line-height-lg * 1em} + #{$input-btn-padding-y-lg * 2} + #{$input-height-border}) !default;\n\n$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$form-text-margin-top: .25rem !default;\n\n$form-check-input-gutter: 1.25rem !default;\n$form-check-input-margin-y: .3rem !default;\n$form-check-input-margin-x: .25rem !default;\n\n$form-check-inline-margin-x: .75rem !default;\n$form-check-inline-input-margin-x: .3125rem !default;\n\n$form-grid-gutter-width: 10px !default;\n$form-group-margin-bottom: 1rem !default;\n\n$input-group-addon-color: $input-color !default;\n$input-group-addon-bg: $gray-200 !default;\n$input-group-addon-border-color: $input-border-color !default;\n\n$custom-forms-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$custom-control-gutter: .5rem !default;\n$custom-control-spacer-x: 1rem !default;\n\n$custom-control-indicator-size: 1rem !default;\n$custom-control-indicator-bg: $input-bg !default;\n\n$custom-control-indicator-bg-size: 50% 50% !default;\n$custom-control-indicator-box-shadow: $input-box-shadow !default;\n$custom-control-indicator-border-color: $gray-500 !default;\n$custom-control-indicator-border-width: $input-border-width !default;\n\n$custom-control-indicator-disabled-bg: $input-disabled-bg !default;\n$custom-control-label-disabled-color: $gray-600 !default;\n\n$custom-control-indicator-checked-color: $component-active-color !default;\n$custom-control-indicator-checked-bg: $component-active-bg !default;\n$custom-control-indicator-checked-disabled-bg: rgba(theme-color(\"primary\"), .5) !default;\n$custom-control-indicator-checked-box-shadow: none !default;\n$custom-control-indicator-checked-border-color: $custom-control-indicator-checked-bg !default;\n\n$custom-control-indicator-focus-box-shadow: $input-focus-box-shadow !default;\n$custom-control-indicator-focus-border-color: $input-focus-border-color !default;\n\n$custom-control-indicator-active-color: $component-active-color !default;\n$custom-control-indicator-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-control-indicator-active-box-shadow: none !default;\n$custom-control-indicator-active-border-color: $custom-control-indicator-active-bg !default;\n\n$custom-checkbox-indicator-border-radius: $border-radius !default;\n$custom-checkbox-indicator-icon-checked: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n\n$custom-checkbox-indicator-indeterminate-bg: $component-active-bg !default;\n$custom-checkbox-indicator-indeterminate-color: $custom-control-indicator-checked-color !default;\n$custom-checkbox-indicator-icon-indeterminate: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3e%3cpath stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$custom-checkbox-indicator-indeterminate-box-shadow: none !default;\n$custom-checkbox-indicator-indeterminate-border-color: $custom-checkbox-indicator-indeterminate-bg !default;\n\n$custom-radio-indicator-border-radius: 50% !default;\n$custom-radio-indicator-icon-checked: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='#{$custom-control-indicator-checked-color}'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n\n$custom-switch-width: $custom-control-indicator-size * 1.75 !default;\n$custom-switch-indicator-border-radius: $custom-control-indicator-size / 2 !default;\n$custom-switch-indicator-size: calc(#{$custom-control-indicator-size} - #{$custom-control-indicator-border-width * 4}) !default;\n\n$custom-select-padding-y: $input-padding-y !default;\n$custom-select-padding-x: $input-padding-x !default;\n$custom-select-font-family: $input-font-family !default;\n$custom-select-font-size: $input-font-size !default;\n$custom-select-height: $input-height !default;\n$custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator\n$custom-select-font-weight: $input-font-weight !default;\n$custom-select-line-height: $input-line-height !default;\n$custom-select-color: $input-color !default;\n$custom-select-disabled-color: $gray-600 !default;\n$custom-select-bg: $input-bg !default;\n$custom-select-disabled-bg: $gray-200 !default;\n$custom-select-bg-size: 8px 10px !default; // In pixels because image dimensions\n$custom-select-indicator-color: $gray-800 !default;\n$custom-select-indicator: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$custom-select-background: $custom-select-indicator no-repeat right $custom-select-padding-x center / $custom-select-bg-size !default; // Used so we can have multiple background elements (e.g., arrow and feedback icon)\n\n$custom-select-feedback-icon-padding-right: calc((1em + #{2 * $custom-select-padding-y}) * 3 / 4 + #{$custom-select-padding-x + $custom-select-indicator-padding}) !default;\n$custom-select-feedback-icon-position: center right ($custom-select-padding-x + $custom-select-indicator-padding) !default;\n$custom-select-feedback-icon-size: $input-height-inner-half $input-height-inner-half !default;\n\n$custom-select-border-width: $input-border-width !default;\n$custom-select-border-color: $input-border-color !default;\n$custom-select-border-radius: $border-radius !default;\n$custom-select-box-shadow: inset 0 1px 2px rgba($black, .075) !default;\n\n$custom-select-focus-border-color: $input-focus-border-color !default;\n$custom-select-focus-width: $input-focus-width !default;\n$custom-select-focus-box-shadow: 0 0 0 $custom-select-focus-width $input-btn-focus-color !default;\n\n$custom-select-padding-y-sm: $input-padding-y-sm !default;\n$custom-select-padding-x-sm: $input-padding-x-sm !default;\n$custom-select-font-size-sm: $input-font-size-sm !default;\n$custom-select-height-sm: $input-height-sm !default;\n\n$custom-select-padding-y-lg: $input-padding-y-lg !default;\n$custom-select-padding-x-lg: $input-padding-x-lg !default;\n$custom-select-font-size-lg: $input-font-size-lg !default;\n$custom-select-height-lg: $input-height-lg !default;\n\n$custom-range-track-width: 100% !default;\n$custom-range-track-height: .5rem !default;\n$custom-range-track-cursor: pointer !default;\n$custom-range-track-bg: $gray-300 !default;\n$custom-range-track-border-radius: 1rem !default;\n$custom-range-track-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;\n\n$custom-range-thumb-width: 1rem !default;\n$custom-range-thumb-height: $custom-range-thumb-width !default;\n$custom-range-thumb-bg: $component-active-bg !default;\n$custom-range-thumb-border: 0 !default;\n$custom-range-thumb-border-radius: 1rem !default;\n$custom-range-thumb-box-shadow: 0 .1rem .25rem rgba($black, .1) !default;\n$custom-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-focus-box-shadow !default;\n$custom-range-thumb-focus-box-shadow-width: $input-focus-width !default; // For focus box shadow issue in IE/Edge\n$custom-range-thumb-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-range-thumb-disabled-bg: $gray-500 !default;\n\n$custom-file-height: $input-height !default;\n$custom-file-height-inner: $input-height-inner !default;\n$custom-file-focus-border-color: $input-focus-border-color !default;\n$custom-file-focus-box-shadow: $input-focus-box-shadow !default;\n$custom-file-disabled-bg: $input-disabled-bg !default;\n\n$custom-file-padding-y: $input-padding-y !default;\n$custom-file-padding-x: $input-padding-x !default;\n$custom-file-line-height: $input-line-height !default;\n$custom-file-font-family: $input-font-family !default;\n$custom-file-font-weight: $input-font-weight !default;\n$custom-file-color: $input-color !default;\n$custom-file-bg: $input-bg !default;\n$custom-file-border-width: $input-border-width !default;\n$custom-file-border-color: $input-border-color !default;\n$custom-file-border-radius: $input-border-radius !default;\n$custom-file-box-shadow: $input-box-shadow !default;\n$custom-file-button-color: $custom-file-color !default;\n$custom-file-button-bg: $input-group-addon-bg !default;\n$custom-file-text: (\n en: \"Browse\"\n) !default;\n\n\n// Form validation\n\n$form-feedback-margin-top: $form-text-margin-top !default;\n$form-feedback-font-size: $small-font-size !default;\n$form-feedback-valid-color: theme-color(\"success\") !default;\n$form-feedback-invalid-color: theme-color(\"danger\") !default;\n\n$form-feedback-icon-valid-color: $form-feedback-valid-color !default;\n$form-feedback-icon-valid: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='#{$form-feedback-icon-valid-color}' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$form-feedback-icon-invalid-color: $form-feedback-invalid-color !default;\n$form-feedback-icon-invalid: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$form-feedback-icon-invalid-color}' viewBox='-2 -2 7 7'%3e%3cpath stroke='#{$form-feedback-icon-invalid-color}' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E\"), \"#\", \"%23\") !default;\n\n$form-validation-states: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$form-validation-states: map-merge(\n (\n \"valid\": (\n \"color\": $form-feedback-valid-color,\n \"icon\": $form-feedback-icon-valid\n ),\n \"invalid\": (\n \"color\": $form-feedback-invalid-color,\n \"icon\": $form-feedback-icon-invalid\n ),\n ),\n $form-validation-states\n);\n\n// Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n\n$zindex-dropdown: 1000 !default;\n$zindex-sticky: 1020 !default;\n$zindex-fixed: 1030 !default;\n$zindex-modal-backdrop: 1040 !default;\n$zindex-modal: 1050 !default;\n$zindex-popover: 1060 !default;\n$zindex-tooltip: 1070 !default;\n\n\n// Navs\n\n$nav-link-padding-y: .5rem !default;\n$nav-link-padding-x: 1rem !default;\n$nav-link-disabled-color: $gray-600 !default;\n\n$nav-tabs-border-color: $gray-300 !default;\n$nav-tabs-border-width: $border-width !default;\n$nav-tabs-border-radius: $border-radius !default;\n$nav-tabs-link-hover-border-color: $gray-200 $gray-200 $nav-tabs-border-color !default;\n$nav-tabs-link-active-color: $gray-700 !default;\n$nav-tabs-link-active-bg: $body-bg !default;\n$nav-tabs-link-active-border-color: $gray-300 $gray-300 $nav-tabs-link-active-bg !default;\n\n$nav-pills-border-radius: $border-radius !default;\n$nav-pills-link-active-color: $component-active-color !default;\n$nav-pills-link-active-bg: $component-active-bg !default;\n\n$nav-divider-color: $gray-200 !default;\n$nav-divider-margin-y: $spacer / 2 !default;\n\n\n// Navbar\n\n$navbar-padding-y: $spacer / 2 !default;\n$navbar-padding-x: $spacer !default;\n\n$navbar-nav-link-padding-x: .5rem !default;\n\n$navbar-brand-font-size: $font-size-lg !default;\n// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link\n$nav-link-height: $font-size-base * $line-height-base + $nav-link-padding-y * 2 !default;\n$navbar-brand-height: $navbar-brand-font-size * $line-height-base !default;\n$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) / 2 !default;\n\n$navbar-toggler-padding-y: .25rem !default;\n$navbar-toggler-padding-x: .75rem !default;\n$navbar-toggler-font-size: $font-size-lg !default;\n$navbar-toggler-border-radius: $btn-border-radius !default;\n\n$navbar-dark-color: rgba($white, .5) !default;\n$navbar-dark-hover-color: rgba($white, .75) !default;\n$navbar-dark-active-color: $white !default;\n$navbar-dark-disabled-color: rgba($white, .25) !default;\n$navbar-dark-toggler-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$navbar-dark-toggler-border-color: rgba($white, .1) !default;\n\n$navbar-light-color: rgba($black, .5) !default;\n$navbar-light-hover-color: rgba($black, .7) !default;\n$navbar-light-active-color: rgba($black, .9) !default;\n$navbar-light-disabled-color: rgba($black, .3) !default;\n$navbar-light-toggler-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$navbar-light-toggler-border-color: rgba($black, .1) !default;\n\n$navbar-light-brand-color: $navbar-light-active-color !default;\n$navbar-light-brand-hover-color: $navbar-light-active-color !default;\n$navbar-dark-brand-color: $navbar-dark-active-color !default;\n$navbar-dark-brand-hover-color: $navbar-dark-active-color !default;\n\n\n// Dropdowns\n//\n// Dropdown menu container and contents.\n\n$dropdown-min-width: 10rem !default;\n$dropdown-padding-y: .5rem !default;\n$dropdown-spacer: .125rem !default;\n$dropdown-font-size: $font-size-base !default;\n$dropdown-color: $body-color !default;\n$dropdown-bg: $white !default;\n$dropdown-border-color: rgba($black, .15) !default;\n$dropdown-border-radius: $border-radius !default;\n$dropdown-border-width: $border-width !default;\n$dropdown-inner-border-radius: calc(#{$dropdown-border-radius} - #{$dropdown-border-width}) !default;\n$dropdown-divider-bg: $gray-200 !default;\n$dropdown-divider-margin-y: $nav-divider-margin-y !default;\n$dropdown-box-shadow: 0 .5rem 1rem rgba($black, .175) !default;\n\n$dropdown-link-color: $gray-900 !default;\n$dropdown-link-hover-color: darken($gray-900, 5%) !default;\n$dropdown-link-hover-bg: $gray-100 !default;\n\n$dropdown-link-active-color: $component-active-color !default;\n$dropdown-link-active-bg: $component-active-bg !default;\n\n$dropdown-link-disabled-color: $gray-600 !default;\n\n$dropdown-item-padding-y: .25rem !default;\n$dropdown-item-padding-x: 1.5rem !default;\n\n$dropdown-header-color: $gray-600 !default;\n\n\n// Pagination\n\n$pagination-padding-y: .5rem !default;\n$pagination-padding-x: .75rem !default;\n$pagination-padding-y-sm: .25rem !default;\n$pagination-padding-x-sm: .5rem !default;\n$pagination-padding-y-lg: .75rem !default;\n$pagination-padding-x-lg: 1.5rem !default;\n$pagination-line-height: 1.25 !default;\n\n$pagination-color: $link-color !default;\n$pagination-bg: $white !default;\n$pagination-border-width: $border-width !default;\n$pagination-border-color: $gray-300 !default;\n\n$pagination-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$pagination-focus-outline: 0 !default;\n\n$pagination-hover-color: $link-hover-color !default;\n$pagination-hover-bg: $gray-200 !default;\n$pagination-hover-border-color: $gray-300 !default;\n\n$pagination-active-color: $component-active-color !default;\n$pagination-active-bg: $component-active-bg !default;\n$pagination-active-border-color: $pagination-active-bg !default;\n\n$pagination-disabled-color: $gray-600 !default;\n$pagination-disabled-bg: $white !default;\n$pagination-disabled-border-color: $gray-300 !default;\n\n\n// Jumbotron\n\n$jumbotron-padding: 2rem !default;\n$jumbotron-color: null !default;\n$jumbotron-bg: $gray-200 !default;\n\n\n// Cards\n\n$card-spacer-y: .75rem !default;\n$card-spacer-x: 1.25rem !default;\n$card-border-width: $border-width !default;\n$card-border-radius: $border-radius !default;\n$card-border-color: rgba($black, .125) !default;\n$card-inner-border-radius: calc(#{$card-border-radius} - #{$card-border-width}) !default;\n$card-cap-bg: rgba($black, .03) !default;\n$card-cap-color: null !default;\n$card-color: null !default;\n$card-bg: $white !default;\n\n$card-img-overlay-padding: 1.25rem !default;\n\n$card-group-margin: $grid-gutter-width / 2 !default;\n$card-deck-margin: $card-group-margin !default;\n\n$card-columns-count: 3 !default;\n$card-columns-gap: 1.25rem !default;\n$card-columns-margin: $card-spacer-y !default;\n\n\n// Tooltips\n\n$tooltip-font-size: $font-size-sm !default;\n$tooltip-max-width: 200px !default;\n$tooltip-color: $white !default;\n$tooltip-bg: $black !default;\n$tooltip-border-radius: $border-radius !default;\n$tooltip-opacity: .9 !default;\n$tooltip-padding-y: .25rem !default;\n$tooltip-padding-x: .5rem !default;\n$tooltip-margin: 0 !default;\n\n$tooltip-arrow-width: .8rem !default;\n$tooltip-arrow-height: .4rem !default;\n$tooltip-arrow-color: $tooltip-bg !default;\n\n// Form tooltips must come after regular tooltips\n$form-feedback-tooltip-padding-y: $tooltip-padding-y !default;\n$form-feedback-tooltip-padding-x: $tooltip-padding-x !default;\n$form-feedback-tooltip-font-size: $tooltip-font-size !default;\n$form-feedback-tooltip-line-height: $line-height-base !default;\n$form-feedback-tooltip-opacity: $tooltip-opacity !default;\n$form-feedback-tooltip-border-radius: $tooltip-border-radius !default;\n\n\n// Popovers\n\n$popover-font-size: $font-size-sm !default;\n$popover-bg: $white !default;\n$popover-max-width: 276px !default;\n$popover-border-width: $border-width !default;\n$popover-border-color: rgba($black, .2) !default;\n$popover-border-radius: $border-radius-lg !default;\n$popover-box-shadow: 0 .25rem .5rem rgba($black, .2) !default;\n\n$popover-header-bg: darken($popover-bg, 3%) !default;\n$popover-header-color: $headings-color !default;\n$popover-header-padding-y: .5rem !default;\n$popover-header-padding-x: .75rem !default;\n\n$popover-body-color: $body-color !default;\n$popover-body-padding-y: $popover-header-padding-y !default;\n$popover-body-padding-x: $popover-header-padding-x !default;\n\n$popover-arrow-width: 1rem !default;\n$popover-arrow-height: .5rem !default;\n$popover-arrow-color: $popover-bg !default;\n\n$popover-arrow-outer-color: fade-in($popover-border-color, .05) !default;\n\n\n// Toasts\n\n$toast-max-width: 350px !default;\n$toast-padding-x: .75rem !default;\n$toast-padding-y: .25rem !default;\n$toast-font-size: .875rem !default;\n$toast-color: null !default;\n$toast-background-color: rgba($white, .85) !default;\n$toast-border-width: 1px !default;\n$toast-border-color: rgba(0, 0, 0, .1) !default;\n$toast-border-radius: .25rem !default;\n$toast-box-shadow: 0 .25rem .75rem rgba($black, .1) !default;\n\n$toast-header-color: $gray-600 !default;\n$toast-header-background-color: rgba($white, .85) !default;\n$toast-header-border-color: rgba(0, 0, 0, .05) !default;\n\n\n// Badges\n\n$badge-font-size: 75% !default;\n$badge-font-weight: $font-weight-bold !default;\n$badge-padding-y: .25em !default;\n$badge-padding-x: .4em !default;\n$badge-border-radius: $border-radius !default;\n\n$badge-transition: $btn-transition !default;\n$badge-focus-width: $input-btn-focus-width !default;\n\n$badge-pill-padding-x: .6em !default;\n// Use a higher than normal value to ensure completely rounded edges when\n// customizing padding or font-size on labels.\n$badge-pill-border-radius: 10rem !default;\n\n\n// Modals\n\n// Padding applied to the modal body\n$modal-inner-padding: 1rem !default;\n\n$modal-dialog-margin: .5rem !default;\n$modal-dialog-margin-y-sm-up: 1.75rem !default;\n\n$modal-title-line-height: $line-height-base !default;\n\n$modal-content-color: null !default;\n$modal-content-bg: $white !default;\n$modal-content-border-color: rgba($black, .2) !default;\n$modal-content-border-width: $border-width !default;\n$modal-content-border-radius: $border-radius-lg !default;\n$modal-content-box-shadow-xs: 0 .25rem .5rem rgba($black, .5) !default;\n$modal-content-box-shadow-sm-up: 0 .5rem 1rem rgba($black, .5) !default;\n\n$modal-backdrop-bg: $black !default;\n$modal-backdrop-opacity: .5 !default;\n$modal-header-border-color: $border-color !default;\n$modal-footer-border-color: $modal-header-border-color !default;\n$modal-header-border-width: $modal-content-border-width !default;\n$modal-footer-border-width: $modal-header-border-width !default;\n$modal-header-padding-y: 1rem !default;\n$modal-header-padding-x: 1rem !default;\n$modal-header-padding: $modal-header-padding-y $modal-header-padding-x !default; // Keep this for backwards compatibility\n\n$modal-xl: 1140px !default;\n$modal-lg: 800px !default;\n$modal-md: 500px !default;\n$modal-sm: 300px !default;\n\n$modal-fade-transform: translate(0, -50px) !default;\n$modal-show-transform: none !default;\n$modal-transition: transform .3s ease-out !default;\n\n\n// Alerts\n//\n// Define alert colors, border radius, and padding.\n\n$alert-padding-y: .75rem !default;\n$alert-padding-x: 1.25rem !default;\n$alert-margin-bottom: 1rem !default;\n$alert-border-radius: $border-radius !default;\n$alert-link-font-weight: $font-weight-bold !default;\n$alert-border-width: $border-width !default;\n\n$alert-bg-level: -10 !default;\n$alert-border-level: -9 !default;\n$alert-color-level: 6 !default;\n\n\n// Progress bars\n\n$progress-height: 1rem !default;\n$progress-font-size: $font-size-base * .75 !default;\n$progress-bg: $gray-200 !default;\n$progress-border-radius: $border-radius !default;\n$progress-box-shadow: inset 0 .1rem .1rem rgba($black, .1) !default;\n$progress-bar-color: $white !default;\n$progress-bar-bg: theme-color(\"primary\") !default;\n$progress-bar-animation-timing: 1s linear infinite !default;\n$progress-bar-transition: width .6s ease !default;\n\n\n// List group\n\n$list-group-color: null !default;\n$list-group-bg: $white !default;\n$list-group-border-color: rgba($black, .125) !default;\n$list-group-border-width: $border-width !default;\n$list-group-border-radius: $border-radius !default;\n\n$list-group-item-padding-y: .75rem !default;\n$list-group-item-padding-x: 1.25rem !default;\n\n$list-group-hover-bg: $gray-100 !default;\n$list-group-active-color: $component-active-color !default;\n$list-group-active-bg: $component-active-bg !default;\n$list-group-active-border-color: $list-group-active-bg !default;\n\n$list-group-disabled-color: $gray-600 !default;\n$list-group-disabled-bg: $list-group-bg !default;\n\n$list-group-action-color: $gray-700 !default;\n$list-group-action-hover-color: $list-group-action-color !default;\n\n$list-group-action-active-color: $body-color !default;\n$list-group-action-active-bg: $gray-200 !default;\n\n\n// Image thumbnails\n\n$thumbnail-padding: .25rem !default;\n$thumbnail-bg: $body-bg !default;\n$thumbnail-border-width: $border-width !default;\n$thumbnail-border-color: $gray-300 !default;\n$thumbnail-border-radius: $border-radius !default;\n$thumbnail-box-shadow: 0 1px 2px rgba($black, .075) !default;\n\n\n// Figures\n\n$figure-caption-font-size: 90% !default;\n$figure-caption-color: $gray-600 !default;\n\n\n// Breadcrumbs\n\n$breadcrumb-padding-y: .75rem !default;\n$breadcrumb-padding-x: 1rem !default;\n$breadcrumb-item-padding: .5rem !default;\n\n$breadcrumb-margin-bottom: 1rem !default;\n\n$breadcrumb-bg: $gray-200 !default;\n$breadcrumb-divider-color: $gray-600 !default;\n$breadcrumb-active-color: $gray-600 !default;\n$breadcrumb-divider: quote(\"/\") !default;\n\n$breadcrumb-border-radius: $border-radius !default;\n\n\n// Carousel\n\n$carousel-control-color: $white !default;\n$carousel-control-width: 15% !default;\n$carousel-control-opacity: .5 !default;\n$carousel-control-hover-opacity: .9 !default;\n$carousel-control-transition: opacity .15s ease !default;\n\n$carousel-indicator-width: 30px !default;\n$carousel-indicator-height: 3px !default;\n$carousel-indicator-hit-area-height: 10px !default;\n$carousel-indicator-spacer: 3px !default;\n$carousel-indicator-active-bg: $white !default;\n$carousel-indicator-transition: opacity .6s ease !default;\n\n$carousel-caption-width: 70% !default;\n$carousel-caption-color: $white !default;\n\n$carousel-control-icon-width: 20px !default;\n\n$carousel-control-prev-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$carousel-control-next-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n\n$carousel-transition-duration: .6s !default;\n$carousel-transition: transform $carousel-transition-duration ease-in-out !default; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)\n\n\n// Spinners\n\n$spinner-width: 2rem !default;\n$spinner-height: $spinner-width !default;\n$spinner-border-width: .25em !default;\n\n$spinner-width-sm: 1rem !default;\n$spinner-height-sm: $spinner-width-sm !default;\n$spinner-border-width-sm: .2em !default;\n\n\n// Close\n\n$close-font-size: $font-size-base * 1.5 !default;\n$close-font-weight: $font-weight-bold !default;\n$close-color: $black !default;\n$close-text-shadow: 0 1px 0 $white !default;\n\n\n// Code\n\n$code-font-size: 87.5% !default;\n$code-color: $pink !default;\n\n$kbd-padding-y: .2rem !default;\n$kbd-padding-x: .4rem !default;\n$kbd-font-size: $code-font-size !default;\n$kbd-color: $white !default;\n$kbd-bg: $gray-900 !default;\n\n$pre-color: $gray-900 !default;\n$pre-scrollable-max-height: 340px !default;\n\n\n// Utilities\n\n$displays: none, inline, inline-block, block, table, table-row, table-cell, flex, inline-flex !default;\n$overflows: auto, hidden !default;\n$positions: static, relative, absolute, fixed, sticky !default;\n\n\n// Printing\n\n$print-page-size: a3 !default;\n$print-body-min-width: map-get($grid-breakpoints, \"lg\") !default;\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `$grid-columns`.\n\n@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {\n // Common properties for all breakpoints\n %grid-column {\n position: relative;\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n }\n\n @each $breakpoint in map-keys($breakpoints) {\n $infix: breakpoint-infix($breakpoint, $breakpoints);\n\n // Allow columns to stretch full width below their breakpoints\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @extend %grid-column;\n }\n }\n .col#{$infix},\n .col#{$infix}-auto {\n @extend %grid-column;\n }\n\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n // Provide basic `.col-{bp}` classes for equal-width flexbox columns\n .col#{$infix} {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col#{$infix}-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%; // Reset earlier grid tiers\n }\n\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @include make-col($i, $columns);\n }\n }\n\n .order#{$infix}-first { order: -1; }\n\n .order#{$infix}-last { order: $columns + 1; }\n\n @for $i from 0 through $columns {\n .order#{$infix}-#{$i} { order: $i; }\n }\n\n // `$columns - 1` because offsetting by the width of an entire row isn't possible\n @for $i from 0 through ($columns - 1) {\n @if not ($infix == \"\" and $i == 0) { // Avoid emitting useless .offset-0\n .offset#{$infix}-#{$i} {\n @include make-col-offset($i, $columns);\n }\n }\n }\n }\n }\n}\n","// stylelint-disable declaration-no-important\n\n//\n// Utilities for common `display` values\n//\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n @each $value in $displays {\n .d#{$infix}-#{$value} { display: $value !important; }\n }\n }\n}\n\n\n//\n// Utilities for toggling `display` in print\n//\n\n@media print {\n @each $value in $displays {\n .d-print-#{$value} { display: $value !important; }\n }\n}\n","// stylelint-disable declaration-no-important\n\n// Flex variation\n//\n// Custom styles for additional flex alignment options.\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n .flex#{$infix}-row { flex-direction: row !important; }\n .flex#{$infix}-column { flex-direction: column !important; }\n .flex#{$infix}-row-reverse { flex-direction: row-reverse !important; }\n .flex#{$infix}-column-reverse { flex-direction: column-reverse !important; }\n\n .flex#{$infix}-wrap { flex-wrap: wrap !important; }\n .flex#{$infix}-nowrap { flex-wrap: nowrap !important; }\n .flex#{$infix}-wrap-reverse { flex-wrap: wrap-reverse !important; }\n .flex#{$infix}-fill { flex: 1 1 auto !important; }\n .flex#{$infix}-grow-0 { flex-grow: 0 !important; }\n .flex#{$infix}-grow-1 { flex-grow: 1 !important; }\n .flex#{$infix}-shrink-0 { flex-shrink: 0 !important; }\n .flex#{$infix}-shrink-1 { flex-shrink: 1 !important; }\n\n .justify-content#{$infix}-start { justify-content: flex-start !important; }\n .justify-content#{$infix}-end { justify-content: flex-end !important; }\n .justify-content#{$infix}-center { justify-content: center !important; }\n .justify-content#{$infix}-between { justify-content: space-between !important; }\n .justify-content#{$infix}-around { justify-content: space-around !important; }\n\n .align-items#{$infix}-start { align-items: flex-start !important; }\n .align-items#{$infix}-end { align-items: flex-end !important; }\n .align-items#{$infix}-center { align-items: center !important; }\n .align-items#{$infix}-baseline { align-items: baseline !important; }\n .align-items#{$infix}-stretch { align-items: stretch !important; }\n\n .align-content#{$infix}-start { align-content: flex-start !important; }\n .align-content#{$infix}-end { align-content: flex-end !important; }\n .align-content#{$infix}-center { align-content: center !important; }\n .align-content#{$infix}-between { align-content: space-between !important; }\n .align-content#{$infix}-around { align-content: space-around !important; }\n .align-content#{$infix}-stretch { align-content: stretch !important; }\n\n .align-self#{$infix}-auto { align-self: auto !important; }\n .align-self#{$infix}-start { align-self: flex-start !important; }\n .align-self#{$infix}-end { align-self: flex-end !important; }\n .align-self#{$infix}-center { align-self: center !important; }\n .align-self#{$infix}-baseline { align-self: baseline !important; }\n .align-self#{$infix}-stretch { align-self: stretch !important; }\n }\n}\n","// stylelint-disable declaration-no-important\n\n// Margin and Padding\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n @each $prop, $abbrev in (margin: m, padding: p) {\n @each $size, $length in $spacers {\n .#{$abbrev}#{$infix}-#{$size} { #{$prop}: $length !important; }\n .#{$abbrev}t#{$infix}-#{$size},\n .#{$abbrev}y#{$infix}-#{$size} {\n #{$prop}-top: $length !important;\n }\n .#{$abbrev}r#{$infix}-#{$size},\n .#{$abbrev}x#{$infix}-#{$size} {\n #{$prop}-right: $length !important;\n }\n .#{$abbrev}b#{$infix}-#{$size},\n .#{$abbrev}y#{$infix}-#{$size} {\n #{$prop}-bottom: $length !important;\n }\n .#{$abbrev}l#{$infix}-#{$size},\n .#{$abbrev}x#{$infix}-#{$size} {\n #{$prop}-left: $length !important;\n }\n }\n }\n\n // Negative margins (e.g., where `.mb-n1` is negative version of `.mb-1`)\n @each $size, $length in $spacers {\n @if $size != 0 {\n .m#{$infix}-n#{$size} { margin: -$length !important; }\n .mt#{$infix}-n#{$size},\n .my#{$infix}-n#{$size} {\n margin-top: -$length !important;\n }\n .mr#{$infix}-n#{$size},\n .mx#{$infix}-n#{$size} {\n margin-right: -$length !important;\n }\n .mb#{$infix}-n#{$size},\n .my#{$infix}-n#{$size} {\n margin-bottom: -$length !important;\n }\n .ml#{$infix}-n#{$size},\n .mx#{$infix}-n#{$size} {\n margin-left: -$length !important;\n }\n }\n }\n\n // Some special margin utils\n .m#{$infix}-auto { margin: auto !important; }\n .mt#{$infix}-auto,\n .my#{$infix}-auto {\n margin-top: auto !important;\n }\n .mr#{$infix}-auto,\n .mx#{$infix}-auto {\n margin-right: auto !important;\n }\n .mb#{$infix}-auto,\n .my#{$infix}-auto {\n margin-bottom: auto !important;\n }\n .ml#{$infix}-auto,\n .mx#{$infix}-auto {\n margin-left: auto !important;\n }\n }\n}\n"]} \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css index 63e1bc6b..e5e74f7f 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css @@ -1,7 +1,7 @@ /*! - * Bootstrap Grid v4.1.3 (https://getbootstrap.com/) - * Copyright 2011-2018 The Bootstrap Authors - * Copyright 2011-2018 Twitter, Inc. + * Bootstrap Grid v4.3.1 (https://getbootstrap.com/) + * Copyright 2011-2019 The Bootstrap Authors + * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */@-ms-viewport{width:device-width}html{box-sizing:border-box;-ms-overflow-style:scrollbar}*,::after,::before{box-sizing:inherit}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.container-fluid{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;min-height:1px;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}} + */html{box-sizing:border-box;-ms-overflow-style:scrollbar}*,::after,::before{box-sizing:inherit}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.container-fluid{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}} /*# sourceMappingURL=bootstrap-grid.min.css.map */ \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map index 4cc3aa65..13e33dbc 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map @@ -1 +1 @@ -{"version":3,"sources":["../../scss/bootstrap-grid.scss","dist/css/bootstrap-grid.css","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_breakpoints.scss","../../scss/mixins/_grid-framework.scss","../../scss/utilities/_display.scss","../../scss/utilities/_flex.scss"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Bootstrap Grid v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n@at-root {\n @-ms-viewport { width: device-width; } // stylelint-disable-line at-rule-no-vendor-prefix\n}\n\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n@import \"functions\";\n@import \"variables\";\n\n@import \"mixins/breakpoints\";\n@import \"mixins/grid-framework\";\n@import \"mixins/grid\";\n\n@import \"grid\";\n@import \"utilities/display\";\n@import \"utilities/flex\";\n","/*!\n * Bootstrap Grid v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n@-ms-viewport {\n width: device-width;\n}\n\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n.container {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n@media (min-width: 576px) {\n .container {\n max-width: 540px;\n }\n}\n\n@media (min-width: 768px) {\n .container {\n max-width: 720px;\n }\n}\n\n@media (min-width: 992px) {\n .container {\n max-width: 960px;\n }\n}\n\n@media (min-width: 1200px) {\n .container {\n max-width: 1140px;\n }\n}\n\n.container-fluid {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n.row {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-wrap: wrap;\n flex-wrap: wrap;\n margin-right: -15px;\n margin-left: -15px;\n}\n\n.no-gutters {\n margin-right: 0;\n margin-left: 0;\n}\n\n.no-gutters > .col,\n.no-gutters > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n}\n\n.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n position: relative;\n width: 100%;\n min-height: 1px;\n padding-right: 15px;\n padding-left: 15px;\n}\n\n.col {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n}\n\n.col-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n}\n\n.col-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n}\n\n.col-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n}\n\n.col-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n}\n\n.col-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n}\n\n.col-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n}\n\n.col-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n}\n\n.col-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n}\n\n.col-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n}\n\n.col-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n}\n\n.col-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n}\n\n.col-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n}\n\n.col-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n}\n\n.order-first {\n -ms-flex-order: -1;\n order: -1;\n}\n\n.order-last {\n -ms-flex-order: 13;\n order: 13;\n}\n\n.order-0 {\n -ms-flex-order: 0;\n order: 0;\n}\n\n.order-1 {\n -ms-flex-order: 1;\n order: 1;\n}\n\n.order-2 {\n -ms-flex-order: 2;\n order: 2;\n}\n\n.order-3 {\n -ms-flex-order: 3;\n order: 3;\n}\n\n.order-4 {\n -ms-flex-order: 4;\n order: 4;\n}\n\n.order-5 {\n -ms-flex-order: 5;\n order: 5;\n}\n\n.order-6 {\n -ms-flex-order: 6;\n order: 6;\n}\n\n.order-7 {\n -ms-flex-order: 7;\n order: 7;\n}\n\n.order-8 {\n -ms-flex-order: 8;\n order: 8;\n}\n\n.order-9 {\n -ms-flex-order: 9;\n order: 9;\n}\n\n.order-10 {\n -ms-flex-order: 10;\n order: 10;\n}\n\n.order-11 {\n -ms-flex-order: 11;\n order: 11;\n}\n\n.order-12 {\n -ms-flex-order: 12;\n order: 12;\n}\n\n.offset-1 {\n margin-left: 8.333333%;\n}\n\n.offset-2 {\n margin-left: 16.666667%;\n}\n\n.offset-3 {\n margin-left: 25%;\n}\n\n.offset-4 {\n margin-left: 33.333333%;\n}\n\n.offset-5 {\n margin-left: 41.666667%;\n}\n\n.offset-6 {\n margin-left: 50%;\n}\n\n.offset-7 {\n margin-left: 58.333333%;\n}\n\n.offset-8 {\n margin-left: 66.666667%;\n}\n\n.offset-9 {\n margin-left: 75%;\n}\n\n.offset-10 {\n margin-left: 83.333333%;\n}\n\n.offset-11 {\n margin-left: 91.666667%;\n}\n\n@media (min-width: 576px) {\n .col-sm {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-sm-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-sm-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-sm-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-sm-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-sm-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-sm-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-sm-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-sm-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-sm-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-sm-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-sm-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-sm-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-sm-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-sm-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-sm-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-sm-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-sm-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-sm-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-sm-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-sm-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-sm-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-sm-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-sm-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-sm-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-sm-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-sm-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-sm-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-sm-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-sm-0 {\n margin-left: 0;\n }\n .offset-sm-1 {\n margin-left: 8.333333%;\n }\n .offset-sm-2 {\n margin-left: 16.666667%;\n }\n .offset-sm-3 {\n margin-left: 25%;\n }\n .offset-sm-4 {\n margin-left: 33.333333%;\n }\n .offset-sm-5 {\n margin-left: 41.666667%;\n }\n .offset-sm-6 {\n margin-left: 50%;\n }\n .offset-sm-7 {\n margin-left: 58.333333%;\n }\n .offset-sm-8 {\n margin-left: 66.666667%;\n }\n .offset-sm-9 {\n margin-left: 75%;\n }\n .offset-sm-10 {\n margin-left: 83.333333%;\n }\n .offset-sm-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 768px) {\n .col-md {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-md-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-md-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-md-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-md-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-md-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-md-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-md-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-md-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-md-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-md-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-md-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-md-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-md-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-md-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-md-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-md-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-md-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-md-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-md-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-md-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-md-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-md-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-md-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-md-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-md-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-md-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-md-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-md-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-md-0 {\n margin-left: 0;\n }\n .offset-md-1 {\n margin-left: 8.333333%;\n }\n .offset-md-2 {\n margin-left: 16.666667%;\n }\n .offset-md-3 {\n margin-left: 25%;\n }\n .offset-md-4 {\n margin-left: 33.333333%;\n }\n .offset-md-5 {\n margin-left: 41.666667%;\n }\n .offset-md-6 {\n margin-left: 50%;\n }\n .offset-md-7 {\n margin-left: 58.333333%;\n }\n .offset-md-8 {\n margin-left: 66.666667%;\n }\n .offset-md-9 {\n margin-left: 75%;\n }\n .offset-md-10 {\n margin-left: 83.333333%;\n }\n .offset-md-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 992px) {\n .col-lg {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-lg-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-lg-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-lg-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-lg-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-lg-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-lg-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-lg-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-lg-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-lg-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-lg-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-lg-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-lg-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-lg-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-lg-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-lg-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-lg-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-lg-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-lg-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-lg-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-lg-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-lg-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-lg-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-lg-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-lg-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-lg-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-lg-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-lg-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-lg-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-lg-0 {\n margin-left: 0;\n }\n .offset-lg-1 {\n margin-left: 8.333333%;\n }\n .offset-lg-2 {\n margin-left: 16.666667%;\n }\n .offset-lg-3 {\n margin-left: 25%;\n }\n .offset-lg-4 {\n margin-left: 33.333333%;\n }\n .offset-lg-5 {\n margin-left: 41.666667%;\n }\n .offset-lg-6 {\n margin-left: 50%;\n }\n .offset-lg-7 {\n margin-left: 58.333333%;\n }\n .offset-lg-8 {\n margin-left: 66.666667%;\n }\n .offset-lg-9 {\n margin-left: 75%;\n }\n .offset-lg-10 {\n margin-left: 83.333333%;\n }\n .offset-lg-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 1200px) {\n .col-xl {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-xl-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-xl-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-xl-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-xl-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-xl-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-xl-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-xl-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-xl-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-xl-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-xl-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-xl-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-xl-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-xl-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-xl-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-xl-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-xl-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-xl-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-xl-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-xl-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-xl-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-xl-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-xl-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-xl-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-xl-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-xl-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-xl-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-xl-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-xl-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-xl-0 {\n margin-left: 0;\n }\n .offset-xl-1 {\n margin-left: 8.333333%;\n }\n .offset-xl-2 {\n margin-left: 16.666667%;\n }\n .offset-xl-3 {\n margin-left: 25%;\n }\n .offset-xl-4 {\n margin-left: 33.333333%;\n }\n .offset-xl-5 {\n margin-left: 41.666667%;\n }\n .offset-xl-6 {\n margin-left: 50%;\n }\n .offset-xl-7 {\n margin-left: 58.333333%;\n }\n .offset-xl-8 {\n margin-left: 66.666667%;\n }\n .offset-xl-9 {\n margin-left: 75%;\n }\n .offset-xl-10 {\n margin-left: 83.333333%;\n }\n .offset-xl-11 {\n margin-left: 91.666667%;\n }\n}\n\n.d-none {\n display: none !important;\n}\n\n.d-inline {\n display: inline !important;\n}\n\n.d-inline-block {\n display: inline-block !important;\n}\n\n.d-block {\n display: block !important;\n}\n\n.d-table {\n display: table !important;\n}\n\n.d-table-row {\n display: table-row !important;\n}\n\n.d-table-cell {\n display: table-cell !important;\n}\n\n.d-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n}\n\n.d-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n}\n\n@media (min-width: 576px) {\n .d-sm-none {\n display: none !important;\n }\n .d-sm-inline {\n display: inline !important;\n }\n .d-sm-inline-block {\n display: inline-block !important;\n }\n .d-sm-block {\n display: block !important;\n }\n .d-sm-table {\n display: table !important;\n }\n .d-sm-table-row {\n display: table-row !important;\n }\n .d-sm-table-cell {\n display: table-cell !important;\n }\n .d-sm-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-sm-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 768px) {\n .d-md-none {\n display: none !important;\n }\n .d-md-inline {\n display: inline !important;\n }\n .d-md-inline-block {\n display: inline-block !important;\n }\n .d-md-block {\n display: block !important;\n }\n .d-md-table {\n display: table !important;\n }\n .d-md-table-row {\n display: table-row !important;\n }\n .d-md-table-cell {\n display: table-cell !important;\n }\n .d-md-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-md-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 992px) {\n .d-lg-none {\n display: none !important;\n }\n .d-lg-inline {\n display: inline !important;\n }\n .d-lg-inline-block {\n display: inline-block !important;\n }\n .d-lg-block {\n display: block !important;\n }\n .d-lg-table {\n display: table !important;\n }\n .d-lg-table-row {\n display: table-row !important;\n }\n .d-lg-table-cell {\n display: table-cell !important;\n }\n .d-lg-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-lg-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 1200px) {\n .d-xl-none {\n display: none !important;\n }\n .d-xl-inline {\n display: inline !important;\n }\n .d-xl-inline-block {\n display: inline-block !important;\n }\n .d-xl-block {\n display: block !important;\n }\n .d-xl-table {\n display: table !important;\n }\n .d-xl-table-row {\n display: table-row !important;\n }\n .d-xl-table-cell {\n display: table-cell !important;\n }\n .d-xl-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-xl-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media print {\n .d-print-none {\n display: none !important;\n }\n .d-print-inline {\n display: inline !important;\n }\n .d-print-inline-block {\n display: inline-block !important;\n }\n .d-print-block {\n display: block !important;\n }\n .d-print-table {\n display: table !important;\n }\n .d-print-table-row {\n display: table-row !important;\n }\n .d-print-table-cell {\n display: table-cell !important;\n }\n .d-print-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-print-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n.flex-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n}\n\n.flex-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n}\n\n.flex-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n}\n\n.flex-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n}\n\n.flex-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n}\n\n.flex-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n}\n\n.flex-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n}\n\n.flex-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n}\n\n.flex-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n}\n\n.flex-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n}\n\n.flex-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n}\n\n.flex-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n}\n\n.justify-content-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n}\n\n.justify-content-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n}\n\n.justify-content-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n}\n\n.justify-content-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n}\n\n.justify-content-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n}\n\n.align-items-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n}\n\n.align-items-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n}\n\n.align-items-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n}\n\n.align-items-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n}\n\n.align-items-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n}\n\n.align-content-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n}\n\n.align-content-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n}\n\n.align-content-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n}\n\n.align-content-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n}\n\n.align-content-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n}\n\n.align-content-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n}\n\n.align-self-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n}\n\n.align-self-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n}\n\n.align-self-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n}\n\n.align-self-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n}\n\n.align-self-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n}\n\n.align-self-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n}\n\n@media (min-width: 576px) {\n .flex-sm-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-sm-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-sm-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-sm-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-sm-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-sm-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-sm-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-sm-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-sm-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-sm-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-sm-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-sm-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-sm-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-sm-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-sm-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-sm-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-sm-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-sm-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-sm-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-sm-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-sm-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-sm-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-sm-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-sm-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-sm-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-sm-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-sm-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-sm-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-sm-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-sm-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-sm-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-sm-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-sm-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-sm-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 768px) {\n .flex-md-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-md-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-md-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-md-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-md-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-md-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-md-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-md-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-md-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-md-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-md-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-md-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-md-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-md-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-md-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-md-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-md-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-md-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-md-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-md-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-md-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-md-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-md-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-md-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-md-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-md-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-md-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-md-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-md-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-md-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-md-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-md-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-md-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-md-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 992px) {\n .flex-lg-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-lg-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-lg-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-lg-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-lg-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-lg-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-lg-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-lg-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-lg-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-lg-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-lg-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-lg-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-lg-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-lg-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-lg-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-lg-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-lg-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-lg-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-lg-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-lg-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-lg-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-lg-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-lg-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-lg-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-lg-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-lg-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-lg-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-lg-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-lg-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-lg-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-lg-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-lg-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-lg-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-lg-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 1200px) {\n .flex-xl-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-xl-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-xl-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-xl-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-xl-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-xl-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-xl-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-xl-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-xl-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-xl-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-xl-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-xl-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-xl-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-xl-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-xl-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-xl-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-xl-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-xl-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-xl-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-xl-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-xl-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-xl-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-xl-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-xl-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-xl-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-xl-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-xl-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-xl-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-xl-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-xl-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-xl-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-xl-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-xl-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-xl-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n/*# sourceMappingURL=bootstrap-grid.css.map */","// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n@if $enable-grid-classes {\n .container {\n @include make-container();\n @include make-container-max-widths();\n }\n}\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but with 100% width for\n// fluid, full width layouts.\n\n@if $enable-grid-classes {\n .container-fluid {\n @include make-container();\n }\n}\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n@if $enable-grid-classes {\n .row {\n @include make-row();\n }\n\n // Remove the negative margin from default .row, then the horizontal padding\n // from all immediate children columns (to prevent runaway style inheritance).\n .no-gutters {\n margin-right: 0;\n margin-left: 0;\n\n > .col,\n > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n }\n }\n}\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n@if $enable-grid-classes {\n @include make-grid-columns();\n}\n","/// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n@mixin make-container() {\n width: 100%;\n padding-right: ($grid-gutter-width / 2);\n padding-left: ($grid-gutter-width / 2);\n margin-right: auto;\n margin-left: auto;\n}\n\n\n// For each breakpoint, define the maximum width of the container in a media query\n@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) {\n @each $breakpoint, $container-max-width in $max-widths {\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n max-width: $container-max-width;\n }\n }\n}\n\n@mixin make-row() {\n display: flex;\n flex-wrap: wrap;\n margin-right: ($grid-gutter-width / -2);\n margin-left: ($grid-gutter-width / -2);\n}\n\n@mixin make-col-ready() {\n position: relative;\n // Prevent columns from becoming too narrow when at smaller grid tiers by\n // always setting `width: 100%;`. This works because we use `flex` values\n // later on to override this initial width.\n width: 100%;\n min-height: 1px; // Prevent collapsing\n padding-right: ($grid-gutter-width / 2);\n padding-left: ($grid-gutter-width / 2);\n}\n\n@mixin make-col($size, $columns: $grid-columns) {\n flex: 0 0 percentage($size / $columns);\n // Add a `max-width` to ensure content within each column does not blow out\n // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari\n // do not appear to require this.\n max-width: percentage($size / $columns);\n}\n\n@mixin make-col-offset($size, $columns: $grid-columns) {\n $num: $size / $columns;\n margin-left: if($num == 0, 0, percentage($num));\n}\n","// Breakpoint viewport sizes and media queries.\n//\n// Breakpoints are defined as a map of (name: minimum width), order from small to large:\n//\n// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)\n//\n// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.\n\n// Name of the next breakpoint, or null for the last breakpoint.\n//\n// >> breakpoint-next(sm)\n// md\n// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// md\n// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))\n// md\n@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {\n $n: index($breakpoint-names, $name);\n @return if($n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);\n}\n\n// Minimum breakpoint width. Null for the smallest (first) breakpoint.\n//\n// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 576px\n@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {\n $min: map-get($breakpoints, $name);\n @return if($min != 0, $min, null);\n}\n\n// Maximum breakpoint width. Null for the largest (last) breakpoint.\n// The maximum value is calculated as the minimum of the next one less 0.02px\n// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths.\n// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max\n// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.\n// See https://bugs.webkit.org/show_bug.cgi?id=178261\n//\n// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 767.98px\n@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {\n $next: breakpoint-next($name, $breakpoints);\n @return if($next, breakpoint-min($next, $breakpoints) - .02px, null);\n}\n\n// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.\n// Useful for making responsive utilities.\n//\n// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"\" (Returns a blank string)\n// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"-sm\"\n@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {\n @return if(breakpoint-min($name, $breakpoints) == null, \"\", \"-#{$name}\");\n}\n\n// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.\n// Makes the @content apply to the given breakpoint and wider.\n@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n @if $min {\n @media (min-width: $min) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media of at most the maximum breakpoint width. No query for the largest breakpoint.\n// Makes the @content apply to the given breakpoint and narrower.\n@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {\n $max: breakpoint-max($name, $breakpoints);\n @if $max {\n @media (max-width: $max) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media that spans multiple breakpoint widths.\n// Makes the @content apply between the min and max breakpoints\n@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($lower, $breakpoints);\n $max: breakpoint-max($upper, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($lower, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($upper, $breakpoints) {\n @content;\n }\n }\n}\n\n// Media between the breakpoint's minimum and maximum widths.\n// No minimum for the smallest breakpoint, and no maximum for the largest one.\n// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.\n@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n $max: breakpoint-max($name, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($name, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($name, $breakpoints) {\n @content;\n }\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `$grid-columns`.\n\n@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {\n // Common properties for all breakpoints\n %grid-column {\n position: relative;\n width: 100%;\n min-height: 1px; // Prevent columns from collapsing when empty\n padding-right: ($gutter / 2);\n padding-left: ($gutter / 2);\n }\n\n @each $breakpoint in map-keys($breakpoints) {\n $infix: breakpoint-infix($breakpoint, $breakpoints);\n\n // Allow columns to stretch full width below their breakpoints\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @extend %grid-column;\n }\n }\n .col#{$infix},\n .col#{$infix}-auto {\n @extend %grid-column;\n }\n\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n // Provide basic `.col-{bp}` classes for equal-width flexbox columns\n .col#{$infix} {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col#{$infix}-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none; // Reset earlier grid tiers\n }\n\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @include make-col($i, $columns);\n }\n }\n\n .order#{$infix}-first { order: -1; }\n\n .order#{$infix}-last { order: $columns + 1; }\n\n @for $i from 0 through $columns {\n .order#{$infix}-#{$i} { order: $i; }\n }\n\n // `$columns - 1` because offsetting by the width of an entire row isn't possible\n @for $i from 0 through ($columns - 1) {\n @if not ($infix == \"\" and $i == 0) { // Avoid emitting useless .offset-0\n .offset#{$infix}-#{$i} {\n @include make-col-offset($i, $columns);\n }\n }\n }\n }\n }\n}\n","// stylelint-disable declaration-no-important\n\n//\n// Utilities for common `display` values\n//\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n .d#{$infix}-none { display: none !important; }\n .d#{$infix}-inline { display: inline !important; }\n .d#{$infix}-inline-block { display: inline-block !important; }\n .d#{$infix}-block { display: block !important; }\n .d#{$infix}-table { display: table !important; }\n .d#{$infix}-table-row { display: table-row !important; }\n .d#{$infix}-table-cell { display: table-cell !important; }\n .d#{$infix}-flex { display: flex !important; }\n .d#{$infix}-inline-flex { display: inline-flex !important; }\n }\n}\n\n\n//\n// Utilities for toggling `display` in print\n//\n\n@media print {\n .d-print-none { display: none !important; }\n .d-print-inline { display: inline !important; }\n .d-print-inline-block { display: inline-block !important; }\n .d-print-block { display: block !important; }\n .d-print-table { display: table !important; }\n .d-print-table-row { display: table-row !important; }\n .d-print-table-cell { display: table-cell !important; }\n .d-print-flex { display: flex !important; }\n .d-print-inline-flex { display: inline-flex !important; }\n}\n","// stylelint-disable declaration-no-important\n\n// Flex variation\n//\n// Custom styles for additional flex alignment options.\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n .flex#{$infix}-row { flex-direction: row !important; }\n .flex#{$infix}-column { flex-direction: column !important; }\n .flex#{$infix}-row-reverse { flex-direction: row-reverse !important; }\n .flex#{$infix}-column-reverse { flex-direction: column-reverse !important; }\n\n .flex#{$infix}-wrap { flex-wrap: wrap !important; }\n .flex#{$infix}-nowrap { flex-wrap: nowrap !important; }\n .flex#{$infix}-wrap-reverse { flex-wrap: wrap-reverse !important; }\n .flex#{$infix}-fill { flex: 1 1 auto !important; }\n .flex#{$infix}-grow-0 { flex-grow: 0 !important; }\n .flex#{$infix}-grow-1 { flex-grow: 1 !important; }\n .flex#{$infix}-shrink-0 { flex-shrink: 0 !important; }\n .flex#{$infix}-shrink-1 { flex-shrink: 1 !important; }\n\n .justify-content#{$infix}-start { justify-content: flex-start !important; }\n .justify-content#{$infix}-end { justify-content: flex-end !important; }\n .justify-content#{$infix}-center { justify-content: center !important; }\n .justify-content#{$infix}-between { justify-content: space-between !important; }\n .justify-content#{$infix}-around { justify-content: space-around !important; }\n\n .align-items#{$infix}-start { align-items: flex-start !important; }\n .align-items#{$infix}-end { align-items: flex-end !important; }\n .align-items#{$infix}-center { align-items: center !important; }\n .align-items#{$infix}-baseline { align-items: baseline !important; }\n .align-items#{$infix}-stretch { align-items: stretch !important; }\n\n .align-content#{$infix}-start { align-content: flex-start !important; }\n .align-content#{$infix}-end { align-content: flex-end !important; }\n .align-content#{$infix}-center { align-content: center !important; }\n .align-content#{$infix}-between { align-content: space-between !important; }\n .align-content#{$infix}-around { align-content: space-around !important; }\n .align-content#{$infix}-stretch { align-content: stretch !important; }\n\n .align-self#{$infix}-auto { align-self: auto !important; }\n .align-self#{$infix}-start { align-self: flex-start !important; }\n .align-self#{$infix}-end { align-self: flex-end !important; }\n .align-self#{$infix}-center { align-self: center !important; }\n .align-self#{$infix}-baseline { align-self: baseline !important; }\n .align-self#{$infix}-stretch { align-self: stretch !important; }\n }\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../../scss/bootstrap-grid.scss","dist/css/bootstrap-grid.css","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_breakpoints.scss","../../scss/mixins/_grid-framework.scss","../../scss/utilities/_display.scss","../../scss/utilities/_flex.scss","../../scss/utilities/_spacing.scss"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Bootstrap Grid v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n@import \"functions\";\n@import \"variables\";\n\n@import \"mixins/breakpoints\";\n@import \"mixins/grid-framework\";\n@import \"mixins/grid\";\n\n@import \"grid\";\n@import \"utilities/display\";\n@import \"utilities/flex\";\n@import \"utilities/spacing\";\n","/*!\n * Bootstrap Grid v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n.container {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n@media (min-width: 576px) {\n .container {\n max-width: 540px;\n }\n}\n\n@media (min-width: 768px) {\n .container {\n max-width: 720px;\n }\n}\n\n@media (min-width: 992px) {\n .container {\n max-width: 960px;\n }\n}\n\n@media (min-width: 1200px) {\n .container {\n max-width: 1140px;\n }\n}\n\n.container-fluid {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n.row {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-wrap: wrap;\n flex-wrap: wrap;\n margin-right: -15px;\n margin-left: -15px;\n}\n\n.no-gutters {\n margin-right: 0;\n margin-left: 0;\n}\n\n.no-gutters > .col,\n.no-gutters > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n}\n\n.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n position: relative;\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n}\n\n.col {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n}\n\n.col-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n}\n\n.col-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n}\n\n.col-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n}\n\n.col-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n}\n\n.col-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n}\n\n.col-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n}\n\n.col-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n}\n\n.col-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n}\n\n.col-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n}\n\n.col-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n}\n\n.col-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n}\n\n.col-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n}\n\n.col-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n}\n\n.order-first {\n -ms-flex-order: -1;\n order: -1;\n}\n\n.order-last {\n -ms-flex-order: 13;\n order: 13;\n}\n\n.order-0 {\n -ms-flex-order: 0;\n order: 0;\n}\n\n.order-1 {\n -ms-flex-order: 1;\n order: 1;\n}\n\n.order-2 {\n -ms-flex-order: 2;\n order: 2;\n}\n\n.order-3 {\n -ms-flex-order: 3;\n order: 3;\n}\n\n.order-4 {\n -ms-flex-order: 4;\n order: 4;\n}\n\n.order-5 {\n -ms-flex-order: 5;\n order: 5;\n}\n\n.order-6 {\n -ms-flex-order: 6;\n order: 6;\n}\n\n.order-7 {\n -ms-flex-order: 7;\n order: 7;\n}\n\n.order-8 {\n -ms-flex-order: 8;\n order: 8;\n}\n\n.order-9 {\n -ms-flex-order: 9;\n order: 9;\n}\n\n.order-10 {\n -ms-flex-order: 10;\n order: 10;\n}\n\n.order-11 {\n -ms-flex-order: 11;\n order: 11;\n}\n\n.order-12 {\n -ms-flex-order: 12;\n order: 12;\n}\n\n.offset-1 {\n margin-left: 8.333333%;\n}\n\n.offset-2 {\n margin-left: 16.666667%;\n}\n\n.offset-3 {\n margin-left: 25%;\n}\n\n.offset-4 {\n margin-left: 33.333333%;\n}\n\n.offset-5 {\n margin-left: 41.666667%;\n}\n\n.offset-6 {\n margin-left: 50%;\n}\n\n.offset-7 {\n margin-left: 58.333333%;\n}\n\n.offset-8 {\n margin-left: 66.666667%;\n}\n\n.offset-9 {\n margin-left: 75%;\n}\n\n.offset-10 {\n margin-left: 83.333333%;\n}\n\n.offset-11 {\n margin-left: 91.666667%;\n}\n\n@media (min-width: 576px) {\n .col-sm {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-sm-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-sm-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-sm-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-sm-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-sm-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-sm-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-sm-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-sm-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-sm-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-sm-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-sm-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-sm-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-sm-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-sm-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-sm-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-sm-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-sm-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-sm-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-sm-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-sm-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-sm-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-sm-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-sm-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-sm-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-sm-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-sm-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-sm-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-sm-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-sm-0 {\n margin-left: 0;\n }\n .offset-sm-1 {\n margin-left: 8.333333%;\n }\n .offset-sm-2 {\n margin-left: 16.666667%;\n }\n .offset-sm-3 {\n margin-left: 25%;\n }\n .offset-sm-4 {\n margin-left: 33.333333%;\n }\n .offset-sm-5 {\n margin-left: 41.666667%;\n }\n .offset-sm-6 {\n margin-left: 50%;\n }\n .offset-sm-7 {\n margin-left: 58.333333%;\n }\n .offset-sm-8 {\n margin-left: 66.666667%;\n }\n .offset-sm-9 {\n margin-left: 75%;\n }\n .offset-sm-10 {\n margin-left: 83.333333%;\n }\n .offset-sm-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 768px) {\n .col-md {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-md-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-md-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-md-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-md-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-md-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-md-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-md-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-md-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-md-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-md-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-md-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-md-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-md-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-md-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-md-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-md-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-md-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-md-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-md-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-md-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-md-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-md-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-md-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-md-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-md-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-md-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-md-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-md-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-md-0 {\n margin-left: 0;\n }\n .offset-md-1 {\n margin-left: 8.333333%;\n }\n .offset-md-2 {\n margin-left: 16.666667%;\n }\n .offset-md-3 {\n margin-left: 25%;\n }\n .offset-md-4 {\n margin-left: 33.333333%;\n }\n .offset-md-5 {\n margin-left: 41.666667%;\n }\n .offset-md-6 {\n margin-left: 50%;\n }\n .offset-md-7 {\n margin-left: 58.333333%;\n }\n .offset-md-8 {\n margin-left: 66.666667%;\n }\n .offset-md-9 {\n margin-left: 75%;\n }\n .offset-md-10 {\n margin-left: 83.333333%;\n }\n .offset-md-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 992px) {\n .col-lg {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-lg-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-lg-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-lg-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-lg-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-lg-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-lg-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-lg-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-lg-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-lg-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-lg-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-lg-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-lg-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-lg-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-lg-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-lg-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-lg-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-lg-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-lg-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-lg-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-lg-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-lg-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-lg-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-lg-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-lg-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-lg-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-lg-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-lg-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-lg-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-lg-0 {\n margin-left: 0;\n }\n .offset-lg-1 {\n margin-left: 8.333333%;\n }\n .offset-lg-2 {\n margin-left: 16.666667%;\n }\n .offset-lg-3 {\n margin-left: 25%;\n }\n .offset-lg-4 {\n margin-left: 33.333333%;\n }\n .offset-lg-5 {\n margin-left: 41.666667%;\n }\n .offset-lg-6 {\n margin-left: 50%;\n }\n .offset-lg-7 {\n margin-left: 58.333333%;\n }\n .offset-lg-8 {\n margin-left: 66.666667%;\n }\n .offset-lg-9 {\n margin-left: 75%;\n }\n .offset-lg-10 {\n margin-left: 83.333333%;\n }\n .offset-lg-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 1200px) {\n .col-xl {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-xl-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-xl-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-xl-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-xl-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-xl-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-xl-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-xl-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-xl-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-xl-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-xl-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-xl-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-xl-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-xl-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-xl-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-xl-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-xl-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-xl-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-xl-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-xl-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-xl-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-xl-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-xl-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-xl-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-xl-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-xl-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-xl-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-xl-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-xl-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-xl-0 {\n margin-left: 0;\n }\n .offset-xl-1 {\n margin-left: 8.333333%;\n }\n .offset-xl-2 {\n margin-left: 16.666667%;\n }\n .offset-xl-3 {\n margin-left: 25%;\n }\n .offset-xl-4 {\n margin-left: 33.333333%;\n }\n .offset-xl-5 {\n margin-left: 41.666667%;\n }\n .offset-xl-6 {\n margin-left: 50%;\n }\n .offset-xl-7 {\n margin-left: 58.333333%;\n }\n .offset-xl-8 {\n margin-left: 66.666667%;\n }\n .offset-xl-9 {\n margin-left: 75%;\n }\n .offset-xl-10 {\n margin-left: 83.333333%;\n }\n .offset-xl-11 {\n margin-left: 91.666667%;\n }\n}\n\n.d-none {\n display: none !important;\n}\n\n.d-inline {\n display: inline !important;\n}\n\n.d-inline-block {\n display: inline-block !important;\n}\n\n.d-block {\n display: block !important;\n}\n\n.d-table {\n display: table !important;\n}\n\n.d-table-row {\n display: table-row !important;\n}\n\n.d-table-cell {\n display: table-cell !important;\n}\n\n.d-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n}\n\n.d-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n}\n\n@media (min-width: 576px) {\n .d-sm-none {\n display: none !important;\n }\n .d-sm-inline {\n display: inline !important;\n }\n .d-sm-inline-block {\n display: inline-block !important;\n }\n .d-sm-block {\n display: block !important;\n }\n .d-sm-table {\n display: table !important;\n }\n .d-sm-table-row {\n display: table-row !important;\n }\n .d-sm-table-cell {\n display: table-cell !important;\n }\n .d-sm-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-sm-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 768px) {\n .d-md-none {\n display: none !important;\n }\n .d-md-inline {\n display: inline !important;\n }\n .d-md-inline-block {\n display: inline-block !important;\n }\n .d-md-block {\n display: block !important;\n }\n .d-md-table {\n display: table !important;\n }\n .d-md-table-row {\n display: table-row !important;\n }\n .d-md-table-cell {\n display: table-cell !important;\n }\n .d-md-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-md-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 992px) {\n .d-lg-none {\n display: none !important;\n }\n .d-lg-inline {\n display: inline !important;\n }\n .d-lg-inline-block {\n display: inline-block !important;\n }\n .d-lg-block {\n display: block !important;\n }\n .d-lg-table {\n display: table !important;\n }\n .d-lg-table-row {\n display: table-row !important;\n }\n .d-lg-table-cell {\n display: table-cell !important;\n }\n .d-lg-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-lg-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 1200px) {\n .d-xl-none {\n display: none !important;\n }\n .d-xl-inline {\n display: inline !important;\n }\n .d-xl-inline-block {\n display: inline-block !important;\n }\n .d-xl-block {\n display: block !important;\n }\n .d-xl-table {\n display: table !important;\n }\n .d-xl-table-row {\n display: table-row !important;\n }\n .d-xl-table-cell {\n display: table-cell !important;\n }\n .d-xl-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-xl-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media print {\n .d-print-none {\n display: none !important;\n }\n .d-print-inline {\n display: inline !important;\n }\n .d-print-inline-block {\n display: inline-block !important;\n }\n .d-print-block {\n display: block !important;\n }\n .d-print-table {\n display: table !important;\n }\n .d-print-table-row {\n display: table-row !important;\n }\n .d-print-table-cell {\n display: table-cell !important;\n }\n .d-print-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-print-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n.flex-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n}\n\n.flex-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n}\n\n.flex-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n}\n\n.flex-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n}\n\n.flex-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n}\n\n.flex-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n}\n\n.flex-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n}\n\n.flex-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n}\n\n.flex-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n}\n\n.flex-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n}\n\n.flex-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n}\n\n.flex-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n}\n\n.justify-content-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n}\n\n.justify-content-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n}\n\n.justify-content-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n}\n\n.justify-content-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n}\n\n.justify-content-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n}\n\n.align-items-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n}\n\n.align-items-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n}\n\n.align-items-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n}\n\n.align-items-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n}\n\n.align-items-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n}\n\n.align-content-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n}\n\n.align-content-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n}\n\n.align-content-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n}\n\n.align-content-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n}\n\n.align-content-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n}\n\n.align-content-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n}\n\n.align-self-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n}\n\n.align-self-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n}\n\n.align-self-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n}\n\n.align-self-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n}\n\n.align-self-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n}\n\n.align-self-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n}\n\n@media (min-width: 576px) {\n .flex-sm-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-sm-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-sm-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-sm-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-sm-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-sm-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-sm-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-sm-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-sm-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-sm-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-sm-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-sm-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-sm-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-sm-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-sm-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-sm-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-sm-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-sm-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-sm-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-sm-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-sm-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-sm-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-sm-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-sm-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-sm-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-sm-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-sm-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-sm-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-sm-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-sm-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-sm-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-sm-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-sm-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-sm-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 768px) {\n .flex-md-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-md-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-md-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-md-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-md-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-md-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-md-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-md-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-md-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-md-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-md-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-md-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-md-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-md-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-md-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-md-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-md-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-md-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-md-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-md-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-md-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-md-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-md-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-md-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-md-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-md-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-md-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-md-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-md-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-md-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-md-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-md-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-md-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-md-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 992px) {\n .flex-lg-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-lg-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-lg-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-lg-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-lg-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-lg-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-lg-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-lg-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-lg-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-lg-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-lg-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-lg-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-lg-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-lg-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-lg-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-lg-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-lg-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-lg-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-lg-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-lg-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-lg-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-lg-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-lg-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-lg-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-lg-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-lg-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-lg-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-lg-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-lg-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-lg-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-lg-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-lg-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-lg-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-lg-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 1200px) {\n .flex-xl-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-xl-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-xl-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-xl-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-xl-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-xl-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-xl-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-xl-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-xl-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-xl-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-xl-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-xl-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-xl-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-xl-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-xl-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-xl-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-xl-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-xl-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-xl-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-xl-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-xl-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-xl-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-xl-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-xl-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-xl-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-xl-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-xl-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-xl-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-xl-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-xl-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-xl-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-xl-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-xl-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-xl-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n.m-0 {\n margin: 0 !important;\n}\n\n.mt-0,\n.my-0 {\n margin-top: 0 !important;\n}\n\n.mr-0,\n.mx-0 {\n margin-right: 0 !important;\n}\n\n.mb-0,\n.my-0 {\n margin-bottom: 0 !important;\n}\n\n.ml-0,\n.mx-0 {\n margin-left: 0 !important;\n}\n\n.m-1 {\n margin: 0.25rem !important;\n}\n\n.mt-1,\n.my-1 {\n margin-top: 0.25rem !important;\n}\n\n.mr-1,\n.mx-1 {\n margin-right: 0.25rem !important;\n}\n\n.mb-1,\n.my-1 {\n margin-bottom: 0.25rem !important;\n}\n\n.ml-1,\n.mx-1 {\n margin-left: 0.25rem !important;\n}\n\n.m-2 {\n margin: 0.5rem !important;\n}\n\n.mt-2,\n.my-2 {\n margin-top: 0.5rem !important;\n}\n\n.mr-2,\n.mx-2 {\n margin-right: 0.5rem !important;\n}\n\n.mb-2,\n.my-2 {\n margin-bottom: 0.5rem !important;\n}\n\n.ml-2,\n.mx-2 {\n margin-left: 0.5rem !important;\n}\n\n.m-3 {\n margin: 1rem !important;\n}\n\n.mt-3,\n.my-3 {\n margin-top: 1rem !important;\n}\n\n.mr-3,\n.mx-3 {\n margin-right: 1rem !important;\n}\n\n.mb-3,\n.my-3 {\n margin-bottom: 1rem !important;\n}\n\n.ml-3,\n.mx-3 {\n margin-left: 1rem !important;\n}\n\n.m-4 {\n margin: 1.5rem !important;\n}\n\n.mt-4,\n.my-4 {\n margin-top: 1.5rem !important;\n}\n\n.mr-4,\n.mx-4 {\n margin-right: 1.5rem !important;\n}\n\n.mb-4,\n.my-4 {\n margin-bottom: 1.5rem !important;\n}\n\n.ml-4,\n.mx-4 {\n margin-left: 1.5rem !important;\n}\n\n.m-5 {\n margin: 3rem !important;\n}\n\n.mt-5,\n.my-5 {\n margin-top: 3rem !important;\n}\n\n.mr-5,\n.mx-5 {\n margin-right: 3rem !important;\n}\n\n.mb-5,\n.my-5 {\n margin-bottom: 3rem !important;\n}\n\n.ml-5,\n.mx-5 {\n margin-left: 3rem !important;\n}\n\n.p-0 {\n padding: 0 !important;\n}\n\n.pt-0,\n.py-0 {\n padding-top: 0 !important;\n}\n\n.pr-0,\n.px-0 {\n padding-right: 0 !important;\n}\n\n.pb-0,\n.py-0 {\n padding-bottom: 0 !important;\n}\n\n.pl-0,\n.px-0 {\n padding-left: 0 !important;\n}\n\n.p-1 {\n padding: 0.25rem !important;\n}\n\n.pt-1,\n.py-1 {\n padding-top: 0.25rem !important;\n}\n\n.pr-1,\n.px-1 {\n padding-right: 0.25rem !important;\n}\n\n.pb-1,\n.py-1 {\n padding-bottom: 0.25rem !important;\n}\n\n.pl-1,\n.px-1 {\n padding-left: 0.25rem !important;\n}\n\n.p-2 {\n padding: 0.5rem !important;\n}\n\n.pt-2,\n.py-2 {\n padding-top: 0.5rem !important;\n}\n\n.pr-2,\n.px-2 {\n padding-right: 0.5rem !important;\n}\n\n.pb-2,\n.py-2 {\n padding-bottom: 0.5rem !important;\n}\n\n.pl-2,\n.px-2 {\n padding-left: 0.5rem !important;\n}\n\n.p-3 {\n padding: 1rem !important;\n}\n\n.pt-3,\n.py-3 {\n padding-top: 1rem !important;\n}\n\n.pr-3,\n.px-3 {\n padding-right: 1rem !important;\n}\n\n.pb-3,\n.py-3 {\n padding-bottom: 1rem !important;\n}\n\n.pl-3,\n.px-3 {\n padding-left: 1rem !important;\n}\n\n.p-4 {\n padding: 1.5rem !important;\n}\n\n.pt-4,\n.py-4 {\n padding-top: 1.5rem !important;\n}\n\n.pr-4,\n.px-4 {\n padding-right: 1.5rem !important;\n}\n\n.pb-4,\n.py-4 {\n padding-bottom: 1.5rem !important;\n}\n\n.pl-4,\n.px-4 {\n padding-left: 1.5rem !important;\n}\n\n.p-5 {\n padding: 3rem !important;\n}\n\n.pt-5,\n.py-5 {\n padding-top: 3rem !important;\n}\n\n.pr-5,\n.px-5 {\n padding-right: 3rem !important;\n}\n\n.pb-5,\n.py-5 {\n padding-bottom: 3rem !important;\n}\n\n.pl-5,\n.px-5 {\n padding-left: 3rem !important;\n}\n\n.m-n1 {\n margin: -0.25rem !important;\n}\n\n.mt-n1,\n.my-n1 {\n margin-top: -0.25rem !important;\n}\n\n.mr-n1,\n.mx-n1 {\n margin-right: -0.25rem !important;\n}\n\n.mb-n1,\n.my-n1 {\n margin-bottom: -0.25rem !important;\n}\n\n.ml-n1,\n.mx-n1 {\n margin-left: -0.25rem !important;\n}\n\n.m-n2 {\n margin: -0.5rem !important;\n}\n\n.mt-n2,\n.my-n2 {\n margin-top: -0.5rem !important;\n}\n\n.mr-n2,\n.mx-n2 {\n margin-right: -0.5rem !important;\n}\n\n.mb-n2,\n.my-n2 {\n margin-bottom: -0.5rem !important;\n}\n\n.ml-n2,\n.mx-n2 {\n margin-left: -0.5rem !important;\n}\n\n.m-n3 {\n margin: -1rem !important;\n}\n\n.mt-n3,\n.my-n3 {\n margin-top: -1rem !important;\n}\n\n.mr-n3,\n.mx-n3 {\n margin-right: -1rem !important;\n}\n\n.mb-n3,\n.my-n3 {\n margin-bottom: -1rem !important;\n}\n\n.ml-n3,\n.mx-n3 {\n margin-left: -1rem !important;\n}\n\n.m-n4 {\n margin: -1.5rem !important;\n}\n\n.mt-n4,\n.my-n4 {\n margin-top: -1.5rem !important;\n}\n\n.mr-n4,\n.mx-n4 {\n margin-right: -1.5rem !important;\n}\n\n.mb-n4,\n.my-n4 {\n margin-bottom: -1.5rem !important;\n}\n\n.ml-n4,\n.mx-n4 {\n margin-left: -1.5rem !important;\n}\n\n.m-n5 {\n margin: -3rem !important;\n}\n\n.mt-n5,\n.my-n5 {\n margin-top: -3rem !important;\n}\n\n.mr-n5,\n.mx-n5 {\n margin-right: -3rem !important;\n}\n\n.mb-n5,\n.my-n5 {\n margin-bottom: -3rem !important;\n}\n\n.ml-n5,\n.mx-n5 {\n margin-left: -3rem !important;\n}\n\n.m-auto {\n margin: auto !important;\n}\n\n.mt-auto,\n.my-auto {\n margin-top: auto !important;\n}\n\n.mr-auto,\n.mx-auto {\n margin-right: auto !important;\n}\n\n.mb-auto,\n.my-auto {\n margin-bottom: auto !important;\n}\n\n.ml-auto,\n.mx-auto {\n margin-left: auto !important;\n}\n\n@media (min-width: 576px) {\n .m-sm-0 {\n margin: 0 !important;\n }\n .mt-sm-0,\n .my-sm-0 {\n margin-top: 0 !important;\n }\n .mr-sm-0,\n .mx-sm-0 {\n margin-right: 0 !important;\n }\n .mb-sm-0,\n .my-sm-0 {\n margin-bottom: 0 !important;\n }\n .ml-sm-0,\n .mx-sm-0 {\n margin-left: 0 !important;\n }\n .m-sm-1 {\n margin: 0.25rem !important;\n }\n .mt-sm-1,\n .my-sm-1 {\n margin-top: 0.25rem !important;\n }\n .mr-sm-1,\n .mx-sm-1 {\n margin-right: 0.25rem !important;\n }\n .mb-sm-1,\n .my-sm-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-sm-1,\n .mx-sm-1 {\n margin-left: 0.25rem !important;\n }\n .m-sm-2 {\n margin: 0.5rem !important;\n }\n .mt-sm-2,\n .my-sm-2 {\n margin-top: 0.5rem !important;\n }\n .mr-sm-2,\n .mx-sm-2 {\n margin-right: 0.5rem !important;\n }\n .mb-sm-2,\n .my-sm-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-sm-2,\n .mx-sm-2 {\n margin-left: 0.5rem !important;\n }\n .m-sm-3 {\n margin: 1rem !important;\n }\n .mt-sm-3,\n .my-sm-3 {\n margin-top: 1rem !important;\n }\n .mr-sm-3,\n .mx-sm-3 {\n margin-right: 1rem !important;\n }\n .mb-sm-3,\n .my-sm-3 {\n margin-bottom: 1rem !important;\n }\n .ml-sm-3,\n .mx-sm-3 {\n margin-left: 1rem !important;\n }\n .m-sm-4 {\n margin: 1.5rem !important;\n }\n .mt-sm-4,\n .my-sm-4 {\n margin-top: 1.5rem !important;\n }\n .mr-sm-4,\n .mx-sm-4 {\n margin-right: 1.5rem !important;\n }\n .mb-sm-4,\n .my-sm-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-sm-4,\n .mx-sm-4 {\n margin-left: 1.5rem !important;\n }\n .m-sm-5 {\n margin: 3rem !important;\n }\n .mt-sm-5,\n .my-sm-5 {\n margin-top: 3rem !important;\n }\n .mr-sm-5,\n .mx-sm-5 {\n margin-right: 3rem !important;\n }\n .mb-sm-5,\n .my-sm-5 {\n margin-bottom: 3rem !important;\n }\n .ml-sm-5,\n .mx-sm-5 {\n margin-left: 3rem !important;\n }\n .p-sm-0 {\n padding: 0 !important;\n }\n .pt-sm-0,\n .py-sm-0 {\n padding-top: 0 !important;\n }\n .pr-sm-0,\n .px-sm-0 {\n padding-right: 0 !important;\n }\n .pb-sm-0,\n .py-sm-0 {\n padding-bottom: 0 !important;\n }\n .pl-sm-0,\n .px-sm-0 {\n padding-left: 0 !important;\n }\n .p-sm-1 {\n padding: 0.25rem !important;\n }\n .pt-sm-1,\n .py-sm-1 {\n padding-top: 0.25rem !important;\n }\n .pr-sm-1,\n .px-sm-1 {\n padding-right: 0.25rem !important;\n }\n .pb-sm-1,\n .py-sm-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-sm-1,\n .px-sm-1 {\n padding-left: 0.25rem !important;\n }\n .p-sm-2 {\n padding: 0.5rem !important;\n }\n .pt-sm-2,\n .py-sm-2 {\n padding-top: 0.5rem !important;\n }\n .pr-sm-2,\n .px-sm-2 {\n padding-right: 0.5rem !important;\n }\n .pb-sm-2,\n .py-sm-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-sm-2,\n .px-sm-2 {\n padding-left: 0.5rem !important;\n }\n .p-sm-3 {\n padding: 1rem !important;\n }\n .pt-sm-3,\n .py-sm-3 {\n padding-top: 1rem !important;\n }\n .pr-sm-3,\n .px-sm-3 {\n padding-right: 1rem !important;\n }\n .pb-sm-3,\n .py-sm-3 {\n padding-bottom: 1rem !important;\n }\n .pl-sm-3,\n .px-sm-3 {\n padding-left: 1rem !important;\n }\n .p-sm-4 {\n padding: 1.5rem !important;\n }\n .pt-sm-4,\n .py-sm-4 {\n padding-top: 1.5rem !important;\n }\n .pr-sm-4,\n .px-sm-4 {\n padding-right: 1.5rem !important;\n }\n .pb-sm-4,\n .py-sm-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-sm-4,\n .px-sm-4 {\n padding-left: 1.5rem !important;\n }\n .p-sm-5 {\n padding: 3rem !important;\n }\n .pt-sm-5,\n .py-sm-5 {\n padding-top: 3rem !important;\n }\n .pr-sm-5,\n .px-sm-5 {\n padding-right: 3rem !important;\n }\n .pb-sm-5,\n .py-sm-5 {\n padding-bottom: 3rem !important;\n }\n .pl-sm-5,\n .px-sm-5 {\n padding-left: 3rem !important;\n }\n .m-sm-n1 {\n margin: -0.25rem !important;\n }\n .mt-sm-n1,\n .my-sm-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-sm-n1,\n .mx-sm-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-sm-n1,\n .my-sm-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-sm-n1,\n .mx-sm-n1 {\n margin-left: -0.25rem !important;\n }\n .m-sm-n2 {\n margin: -0.5rem !important;\n }\n .mt-sm-n2,\n .my-sm-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-sm-n2,\n .mx-sm-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-sm-n2,\n .my-sm-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-sm-n2,\n .mx-sm-n2 {\n margin-left: -0.5rem !important;\n }\n .m-sm-n3 {\n margin: -1rem !important;\n }\n .mt-sm-n3,\n .my-sm-n3 {\n margin-top: -1rem !important;\n }\n .mr-sm-n3,\n .mx-sm-n3 {\n margin-right: -1rem !important;\n }\n .mb-sm-n3,\n .my-sm-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-sm-n3,\n .mx-sm-n3 {\n margin-left: -1rem !important;\n }\n .m-sm-n4 {\n margin: -1.5rem !important;\n }\n .mt-sm-n4,\n .my-sm-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-sm-n4,\n .mx-sm-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-sm-n4,\n .my-sm-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-sm-n4,\n .mx-sm-n4 {\n margin-left: -1.5rem !important;\n }\n .m-sm-n5 {\n margin: -3rem !important;\n }\n .mt-sm-n5,\n .my-sm-n5 {\n margin-top: -3rem !important;\n }\n .mr-sm-n5,\n .mx-sm-n5 {\n margin-right: -3rem !important;\n }\n .mb-sm-n5,\n .my-sm-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-sm-n5,\n .mx-sm-n5 {\n margin-left: -3rem !important;\n }\n .m-sm-auto {\n margin: auto !important;\n }\n .mt-sm-auto,\n .my-sm-auto {\n margin-top: auto !important;\n }\n .mr-sm-auto,\n .mx-sm-auto {\n margin-right: auto !important;\n }\n .mb-sm-auto,\n .my-sm-auto {\n margin-bottom: auto !important;\n }\n .ml-sm-auto,\n .mx-sm-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 768px) {\n .m-md-0 {\n margin: 0 !important;\n }\n .mt-md-0,\n .my-md-0 {\n margin-top: 0 !important;\n }\n .mr-md-0,\n .mx-md-0 {\n margin-right: 0 !important;\n }\n .mb-md-0,\n .my-md-0 {\n margin-bottom: 0 !important;\n }\n .ml-md-0,\n .mx-md-0 {\n margin-left: 0 !important;\n }\n .m-md-1 {\n margin: 0.25rem !important;\n }\n .mt-md-1,\n .my-md-1 {\n margin-top: 0.25rem !important;\n }\n .mr-md-1,\n .mx-md-1 {\n margin-right: 0.25rem !important;\n }\n .mb-md-1,\n .my-md-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-md-1,\n .mx-md-1 {\n margin-left: 0.25rem !important;\n }\n .m-md-2 {\n margin: 0.5rem !important;\n }\n .mt-md-2,\n .my-md-2 {\n margin-top: 0.5rem !important;\n }\n .mr-md-2,\n .mx-md-2 {\n margin-right: 0.5rem !important;\n }\n .mb-md-2,\n .my-md-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-md-2,\n .mx-md-2 {\n margin-left: 0.5rem !important;\n }\n .m-md-3 {\n margin: 1rem !important;\n }\n .mt-md-3,\n .my-md-3 {\n margin-top: 1rem !important;\n }\n .mr-md-3,\n .mx-md-3 {\n margin-right: 1rem !important;\n }\n .mb-md-3,\n .my-md-3 {\n margin-bottom: 1rem !important;\n }\n .ml-md-3,\n .mx-md-3 {\n margin-left: 1rem !important;\n }\n .m-md-4 {\n margin: 1.5rem !important;\n }\n .mt-md-4,\n .my-md-4 {\n margin-top: 1.5rem !important;\n }\n .mr-md-4,\n .mx-md-4 {\n margin-right: 1.5rem !important;\n }\n .mb-md-4,\n .my-md-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-md-4,\n .mx-md-4 {\n margin-left: 1.5rem !important;\n }\n .m-md-5 {\n margin: 3rem !important;\n }\n .mt-md-5,\n .my-md-5 {\n margin-top: 3rem !important;\n }\n .mr-md-5,\n .mx-md-5 {\n margin-right: 3rem !important;\n }\n .mb-md-5,\n .my-md-5 {\n margin-bottom: 3rem !important;\n }\n .ml-md-5,\n .mx-md-5 {\n margin-left: 3rem !important;\n }\n .p-md-0 {\n padding: 0 !important;\n }\n .pt-md-0,\n .py-md-0 {\n padding-top: 0 !important;\n }\n .pr-md-0,\n .px-md-0 {\n padding-right: 0 !important;\n }\n .pb-md-0,\n .py-md-0 {\n padding-bottom: 0 !important;\n }\n .pl-md-0,\n .px-md-0 {\n padding-left: 0 !important;\n }\n .p-md-1 {\n padding: 0.25rem !important;\n }\n .pt-md-1,\n .py-md-1 {\n padding-top: 0.25rem !important;\n }\n .pr-md-1,\n .px-md-1 {\n padding-right: 0.25rem !important;\n }\n .pb-md-1,\n .py-md-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-md-1,\n .px-md-1 {\n padding-left: 0.25rem !important;\n }\n .p-md-2 {\n padding: 0.5rem !important;\n }\n .pt-md-2,\n .py-md-2 {\n padding-top: 0.5rem !important;\n }\n .pr-md-2,\n .px-md-2 {\n padding-right: 0.5rem !important;\n }\n .pb-md-2,\n .py-md-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-md-2,\n .px-md-2 {\n padding-left: 0.5rem !important;\n }\n .p-md-3 {\n padding: 1rem !important;\n }\n .pt-md-3,\n .py-md-3 {\n padding-top: 1rem !important;\n }\n .pr-md-3,\n .px-md-3 {\n padding-right: 1rem !important;\n }\n .pb-md-3,\n .py-md-3 {\n padding-bottom: 1rem !important;\n }\n .pl-md-3,\n .px-md-3 {\n padding-left: 1rem !important;\n }\n .p-md-4 {\n padding: 1.5rem !important;\n }\n .pt-md-4,\n .py-md-4 {\n padding-top: 1.5rem !important;\n }\n .pr-md-4,\n .px-md-4 {\n padding-right: 1.5rem !important;\n }\n .pb-md-4,\n .py-md-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-md-4,\n .px-md-4 {\n padding-left: 1.5rem !important;\n }\n .p-md-5 {\n padding: 3rem !important;\n }\n .pt-md-5,\n .py-md-5 {\n padding-top: 3rem !important;\n }\n .pr-md-5,\n .px-md-5 {\n padding-right: 3rem !important;\n }\n .pb-md-5,\n .py-md-5 {\n padding-bottom: 3rem !important;\n }\n .pl-md-5,\n .px-md-5 {\n padding-left: 3rem !important;\n }\n .m-md-n1 {\n margin: -0.25rem !important;\n }\n .mt-md-n1,\n .my-md-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-md-n1,\n .mx-md-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-md-n1,\n .my-md-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-md-n1,\n .mx-md-n1 {\n margin-left: -0.25rem !important;\n }\n .m-md-n2 {\n margin: -0.5rem !important;\n }\n .mt-md-n2,\n .my-md-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-md-n2,\n .mx-md-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-md-n2,\n .my-md-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-md-n2,\n .mx-md-n2 {\n margin-left: -0.5rem !important;\n }\n .m-md-n3 {\n margin: -1rem !important;\n }\n .mt-md-n3,\n .my-md-n3 {\n margin-top: -1rem !important;\n }\n .mr-md-n3,\n .mx-md-n3 {\n margin-right: -1rem !important;\n }\n .mb-md-n3,\n .my-md-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-md-n3,\n .mx-md-n3 {\n margin-left: -1rem !important;\n }\n .m-md-n4 {\n margin: -1.5rem !important;\n }\n .mt-md-n4,\n .my-md-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-md-n4,\n .mx-md-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-md-n4,\n .my-md-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-md-n4,\n .mx-md-n4 {\n margin-left: -1.5rem !important;\n }\n .m-md-n5 {\n margin: -3rem !important;\n }\n .mt-md-n5,\n .my-md-n5 {\n margin-top: -3rem !important;\n }\n .mr-md-n5,\n .mx-md-n5 {\n margin-right: -3rem !important;\n }\n .mb-md-n5,\n .my-md-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-md-n5,\n .mx-md-n5 {\n margin-left: -3rem !important;\n }\n .m-md-auto {\n margin: auto !important;\n }\n .mt-md-auto,\n .my-md-auto {\n margin-top: auto !important;\n }\n .mr-md-auto,\n .mx-md-auto {\n margin-right: auto !important;\n }\n .mb-md-auto,\n .my-md-auto {\n margin-bottom: auto !important;\n }\n .ml-md-auto,\n .mx-md-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 992px) {\n .m-lg-0 {\n margin: 0 !important;\n }\n .mt-lg-0,\n .my-lg-0 {\n margin-top: 0 !important;\n }\n .mr-lg-0,\n .mx-lg-0 {\n margin-right: 0 !important;\n }\n .mb-lg-0,\n .my-lg-0 {\n margin-bottom: 0 !important;\n }\n .ml-lg-0,\n .mx-lg-0 {\n margin-left: 0 !important;\n }\n .m-lg-1 {\n margin: 0.25rem !important;\n }\n .mt-lg-1,\n .my-lg-1 {\n margin-top: 0.25rem !important;\n }\n .mr-lg-1,\n .mx-lg-1 {\n margin-right: 0.25rem !important;\n }\n .mb-lg-1,\n .my-lg-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-lg-1,\n .mx-lg-1 {\n margin-left: 0.25rem !important;\n }\n .m-lg-2 {\n margin: 0.5rem !important;\n }\n .mt-lg-2,\n .my-lg-2 {\n margin-top: 0.5rem !important;\n }\n .mr-lg-2,\n .mx-lg-2 {\n margin-right: 0.5rem !important;\n }\n .mb-lg-2,\n .my-lg-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-lg-2,\n .mx-lg-2 {\n margin-left: 0.5rem !important;\n }\n .m-lg-3 {\n margin: 1rem !important;\n }\n .mt-lg-3,\n .my-lg-3 {\n margin-top: 1rem !important;\n }\n .mr-lg-3,\n .mx-lg-3 {\n margin-right: 1rem !important;\n }\n .mb-lg-3,\n .my-lg-3 {\n margin-bottom: 1rem !important;\n }\n .ml-lg-3,\n .mx-lg-3 {\n margin-left: 1rem !important;\n }\n .m-lg-4 {\n margin: 1.5rem !important;\n }\n .mt-lg-4,\n .my-lg-4 {\n margin-top: 1.5rem !important;\n }\n .mr-lg-4,\n .mx-lg-4 {\n margin-right: 1.5rem !important;\n }\n .mb-lg-4,\n .my-lg-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-lg-4,\n .mx-lg-4 {\n margin-left: 1.5rem !important;\n }\n .m-lg-5 {\n margin: 3rem !important;\n }\n .mt-lg-5,\n .my-lg-5 {\n margin-top: 3rem !important;\n }\n .mr-lg-5,\n .mx-lg-5 {\n margin-right: 3rem !important;\n }\n .mb-lg-5,\n .my-lg-5 {\n margin-bottom: 3rem !important;\n }\n .ml-lg-5,\n .mx-lg-5 {\n margin-left: 3rem !important;\n }\n .p-lg-0 {\n padding: 0 !important;\n }\n .pt-lg-0,\n .py-lg-0 {\n padding-top: 0 !important;\n }\n .pr-lg-0,\n .px-lg-0 {\n padding-right: 0 !important;\n }\n .pb-lg-0,\n .py-lg-0 {\n padding-bottom: 0 !important;\n }\n .pl-lg-0,\n .px-lg-0 {\n padding-left: 0 !important;\n }\n .p-lg-1 {\n padding: 0.25rem !important;\n }\n .pt-lg-1,\n .py-lg-1 {\n padding-top: 0.25rem !important;\n }\n .pr-lg-1,\n .px-lg-1 {\n padding-right: 0.25rem !important;\n }\n .pb-lg-1,\n .py-lg-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-lg-1,\n .px-lg-1 {\n padding-left: 0.25rem !important;\n }\n .p-lg-2 {\n padding: 0.5rem !important;\n }\n .pt-lg-2,\n .py-lg-2 {\n padding-top: 0.5rem !important;\n }\n .pr-lg-2,\n .px-lg-2 {\n padding-right: 0.5rem !important;\n }\n .pb-lg-2,\n .py-lg-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-lg-2,\n .px-lg-2 {\n padding-left: 0.5rem !important;\n }\n .p-lg-3 {\n padding: 1rem !important;\n }\n .pt-lg-3,\n .py-lg-3 {\n padding-top: 1rem !important;\n }\n .pr-lg-3,\n .px-lg-3 {\n padding-right: 1rem !important;\n }\n .pb-lg-3,\n .py-lg-3 {\n padding-bottom: 1rem !important;\n }\n .pl-lg-3,\n .px-lg-3 {\n padding-left: 1rem !important;\n }\n .p-lg-4 {\n padding: 1.5rem !important;\n }\n .pt-lg-4,\n .py-lg-4 {\n padding-top: 1.5rem !important;\n }\n .pr-lg-4,\n .px-lg-4 {\n padding-right: 1.5rem !important;\n }\n .pb-lg-4,\n .py-lg-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-lg-4,\n .px-lg-4 {\n padding-left: 1.5rem !important;\n }\n .p-lg-5 {\n padding: 3rem !important;\n }\n .pt-lg-5,\n .py-lg-5 {\n padding-top: 3rem !important;\n }\n .pr-lg-5,\n .px-lg-5 {\n padding-right: 3rem !important;\n }\n .pb-lg-5,\n .py-lg-5 {\n padding-bottom: 3rem !important;\n }\n .pl-lg-5,\n .px-lg-5 {\n padding-left: 3rem !important;\n }\n .m-lg-n1 {\n margin: -0.25rem !important;\n }\n .mt-lg-n1,\n .my-lg-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-lg-n1,\n .mx-lg-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-lg-n1,\n .my-lg-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-lg-n1,\n .mx-lg-n1 {\n margin-left: -0.25rem !important;\n }\n .m-lg-n2 {\n margin: -0.5rem !important;\n }\n .mt-lg-n2,\n .my-lg-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-lg-n2,\n .mx-lg-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-lg-n2,\n .my-lg-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-lg-n2,\n .mx-lg-n2 {\n margin-left: -0.5rem !important;\n }\n .m-lg-n3 {\n margin: -1rem !important;\n }\n .mt-lg-n3,\n .my-lg-n3 {\n margin-top: -1rem !important;\n }\n .mr-lg-n3,\n .mx-lg-n3 {\n margin-right: -1rem !important;\n }\n .mb-lg-n3,\n .my-lg-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-lg-n3,\n .mx-lg-n3 {\n margin-left: -1rem !important;\n }\n .m-lg-n4 {\n margin: -1.5rem !important;\n }\n .mt-lg-n4,\n .my-lg-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-lg-n4,\n .mx-lg-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-lg-n4,\n .my-lg-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-lg-n4,\n .mx-lg-n4 {\n margin-left: -1.5rem !important;\n }\n .m-lg-n5 {\n margin: -3rem !important;\n }\n .mt-lg-n5,\n .my-lg-n5 {\n margin-top: -3rem !important;\n }\n .mr-lg-n5,\n .mx-lg-n5 {\n margin-right: -3rem !important;\n }\n .mb-lg-n5,\n .my-lg-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-lg-n5,\n .mx-lg-n5 {\n margin-left: -3rem !important;\n }\n .m-lg-auto {\n margin: auto !important;\n }\n .mt-lg-auto,\n .my-lg-auto {\n margin-top: auto !important;\n }\n .mr-lg-auto,\n .mx-lg-auto {\n margin-right: auto !important;\n }\n .mb-lg-auto,\n .my-lg-auto {\n margin-bottom: auto !important;\n }\n .ml-lg-auto,\n .mx-lg-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 1200px) {\n .m-xl-0 {\n margin: 0 !important;\n }\n .mt-xl-0,\n .my-xl-0 {\n margin-top: 0 !important;\n }\n .mr-xl-0,\n .mx-xl-0 {\n margin-right: 0 !important;\n }\n .mb-xl-0,\n .my-xl-0 {\n margin-bottom: 0 !important;\n }\n .ml-xl-0,\n .mx-xl-0 {\n margin-left: 0 !important;\n }\n .m-xl-1 {\n margin: 0.25rem !important;\n }\n .mt-xl-1,\n .my-xl-1 {\n margin-top: 0.25rem !important;\n }\n .mr-xl-1,\n .mx-xl-1 {\n margin-right: 0.25rem !important;\n }\n .mb-xl-1,\n .my-xl-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-xl-1,\n .mx-xl-1 {\n margin-left: 0.25rem !important;\n }\n .m-xl-2 {\n margin: 0.5rem !important;\n }\n .mt-xl-2,\n .my-xl-2 {\n margin-top: 0.5rem !important;\n }\n .mr-xl-2,\n .mx-xl-2 {\n margin-right: 0.5rem !important;\n }\n .mb-xl-2,\n .my-xl-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-xl-2,\n .mx-xl-2 {\n margin-left: 0.5rem !important;\n }\n .m-xl-3 {\n margin: 1rem !important;\n }\n .mt-xl-3,\n .my-xl-3 {\n margin-top: 1rem !important;\n }\n .mr-xl-3,\n .mx-xl-3 {\n margin-right: 1rem !important;\n }\n .mb-xl-3,\n .my-xl-3 {\n margin-bottom: 1rem !important;\n }\n .ml-xl-3,\n .mx-xl-3 {\n margin-left: 1rem !important;\n }\n .m-xl-4 {\n margin: 1.5rem !important;\n }\n .mt-xl-4,\n .my-xl-4 {\n margin-top: 1.5rem !important;\n }\n .mr-xl-4,\n .mx-xl-4 {\n margin-right: 1.5rem !important;\n }\n .mb-xl-4,\n .my-xl-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-xl-4,\n .mx-xl-4 {\n margin-left: 1.5rem !important;\n }\n .m-xl-5 {\n margin: 3rem !important;\n }\n .mt-xl-5,\n .my-xl-5 {\n margin-top: 3rem !important;\n }\n .mr-xl-5,\n .mx-xl-5 {\n margin-right: 3rem !important;\n }\n .mb-xl-5,\n .my-xl-5 {\n margin-bottom: 3rem !important;\n }\n .ml-xl-5,\n .mx-xl-5 {\n margin-left: 3rem !important;\n }\n .p-xl-0 {\n padding: 0 !important;\n }\n .pt-xl-0,\n .py-xl-0 {\n padding-top: 0 !important;\n }\n .pr-xl-0,\n .px-xl-0 {\n padding-right: 0 !important;\n }\n .pb-xl-0,\n .py-xl-0 {\n padding-bottom: 0 !important;\n }\n .pl-xl-0,\n .px-xl-0 {\n padding-left: 0 !important;\n }\n .p-xl-1 {\n padding: 0.25rem !important;\n }\n .pt-xl-1,\n .py-xl-1 {\n padding-top: 0.25rem !important;\n }\n .pr-xl-1,\n .px-xl-1 {\n padding-right: 0.25rem !important;\n }\n .pb-xl-1,\n .py-xl-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-xl-1,\n .px-xl-1 {\n padding-left: 0.25rem !important;\n }\n .p-xl-2 {\n padding: 0.5rem !important;\n }\n .pt-xl-2,\n .py-xl-2 {\n padding-top: 0.5rem !important;\n }\n .pr-xl-2,\n .px-xl-2 {\n padding-right: 0.5rem !important;\n }\n .pb-xl-2,\n .py-xl-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-xl-2,\n .px-xl-2 {\n padding-left: 0.5rem !important;\n }\n .p-xl-3 {\n padding: 1rem !important;\n }\n .pt-xl-3,\n .py-xl-3 {\n padding-top: 1rem !important;\n }\n .pr-xl-3,\n .px-xl-3 {\n padding-right: 1rem !important;\n }\n .pb-xl-3,\n .py-xl-3 {\n padding-bottom: 1rem !important;\n }\n .pl-xl-3,\n .px-xl-3 {\n padding-left: 1rem !important;\n }\n .p-xl-4 {\n padding: 1.5rem !important;\n }\n .pt-xl-4,\n .py-xl-4 {\n padding-top: 1.5rem !important;\n }\n .pr-xl-4,\n .px-xl-4 {\n padding-right: 1.5rem !important;\n }\n .pb-xl-4,\n .py-xl-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-xl-4,\n .px-xl-4 {\n padding-left: 1.5rem !important;\n }\n .p-xl-5 {\n padding: 3rem !important;\n }\n .pt-xl-5,\n .py-xl-5 {\n padding-top: 3rem !important;\n }\n .pr-xl-5,\n .px-xl-5 {\n padding-right: 3rem !important;\n }\n .pb-xl-5,\n .py-xl-5 {\n padding-bottom: 3rem !important;\n }\n .pl-xl-5,\n .px-xl-5 {\n padding-left: 3rem !important;\n }\n .m-xl-n1 {\n margin: -0.25rem !important;\n }\n .mt-xl-n1,\n .my-xl-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-xl-n1,\n .mx-xl-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-xl-n1,\n .my-xl-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-xl-n1,\n .mx-xl-n1 {\n margin-left: -0.25rem !important;\n }\n .m-xl-n2 {\n margin: -0.5rem !important;\n }\n .mt-xl-n2,\n .my-xl-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-xl-n2,\n .mx-xl-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-xl-n2,\n .my-xl-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-xl-n2,\n .mx-xl-n2 {\n margin-left: -0.5rem !important;\n }\n .m-xl-n3 {\n margin: -1rem !important;\n }\n .mt-xl-n3,\n .my-xl-n3 {\n margin-top: -1rem !important;\n }\n .mr-xl-n3,\n .mx-xl-n3 {\n margin-right: -1rem !important;\n }\n .mb-xl-n3,\n .my-xl-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-xl-n3,\n .mx-xl-n3 {\n margin-left: -1rem !important;\n }\n .m-xl-n4 {\n margin: -1.5rem !important;\n }\n .mt-xl-n4,\n .my-xl-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-xl-n4,\n .mx-xl-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-xl-n4,\n .my-xl-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-xl-n4,\n .mx-xl-n4 {\n margin-left: -1.5rem !important;\n }\n .m-xl-n5 {\n margin: -3rem !important;\n }\n .mt-xl-n5,\n .my-xl-n5 {\n margin-top: -3rem !important;\n }\n .mr-xl-n5,\n .mx-xl-n5 {\n margin-right: -3rem !important;\n }\n .mb-xl-n5,\n .my-xl-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-xl-n5,\n .mx-xl-n5 {\n margin-left: -3rem !important;\n }\n .m-xl-auto {\n margin: auto !important;\n }\n .mt-xl-auto,\n .my-xl-auto {\n margin-top: auto !important;\n }\n .mr-xl-auto,\n .mx-xl-auto {\n margin-right: auto !important;\n }\n .mb-xl-auto,\n .my-xl-auto {\n margin-bottom: auto !important;\n }\n .ml-xl-auto,\n .mx-xl-auto {\n margin-left: auto !important;\n }\n}\n/*# sourceMappingURL=bootstrap-grid.css.map */","// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n@if $enable-grid-classes {\n .container {\n @include make-container();\n @include make-container-max-widths();\n }\n}\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but with 100% width for\n// fluid, full width layouts.\n\n@if $enable-grid-classes {\n .container-fluid {\n @include make-container();\n }\n}\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n@if $enable-grid-classes {\n .row {\n @include make-row();\n }\n\n // Remove the negative margin from default .row, then the horizontal padding\n // from all immediate children columns (to prevent runaway style inheritance).\n .no-gutters {\n margin-right: 0;\n margin-left: 0;\n\n > .col,\n > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n }\n }\n}\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n@if $enable-grid-classes {\n @include make-grid-columns();\n}\n","/// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n@mixin make-container($gutter: $grid-gutter-width) {\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n margin-right: auto;\n margin-left: auto;\n}\n\n\n// For each breakpoint, define the maximum width of the container in a media query\n@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) {\n @each $breakpoint, $container-max-width in $max-widths {\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n max-width: $container-max-width;\n }\n }\n}\n\n@mixin make-row($gutter: $grid-gutter-width) {\n display: flex;\n flex-wrap: wrap;\n margin-right: -$gutter / 2;\n margin-left: -$gutter / 2;\n}\n\n@mixin make-col-ready($gutter: $grid-gutter-width) {\n position: relative;\n // Prevent columns from becoming too narrow when at smaller grid tiers by\n // always setting `width: 100%;`. This works because we use `flex` values\n // later on to override this initial width.\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n}\n\n@mixin make-col($size, $columns: $grid-columns) {\n flex: 0 0 percentage($size / $columns);\n // Add a `max-width` to ensure content within each column does not blow out\n // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari\n // do not appear to require this.\n max-width: percentage($size / $columns);\n}\n\n@mixin make-col-offset($size, $columns: $grid-columns) {\n $num: $size / $columns;\n margin-left: if($num == 0, 0, percentage($num));\n}\n","// Breakpoint viewport sizes and media queries.\n//\n// Breakpoints are defined as a map of (name: minimum width), order from small to large:\n//\n// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)\n//\n// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.\n\n// Name of the next breakpoint, or null for the last breakpoint.\n//\n// >> breakpoint-next(sm)\n// md\n// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// md\n// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))\n// md\n@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {\n $n: index($breakpoint-names, $name);\n @return if($n != null and $n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);\n}\n\n// Minimum breakpoint width. Null for the smallest (first) breakpoint.\n//\n// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 576px\n@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {\n $min: map-get($breakpoints, $name);\n @return if($min != 0, $min, null);\n}\n\n// Maximum breakpoint width. Null for the largest (last) breakpoint.\n// The maximum value is calculated as the minimum of the next one less 0.02px\n// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths.\n// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max\n// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.\n// See https://bugs.webkit.org/show_bug.cgi?id=178261\n//\n// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 767.98px\n@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {\n $next: breakpoint-next($name, $breakpoints);\n @return if($next, breakpoint-min($next, $breakpoints) - .02, null);\n}\n\n// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.\n// Useful for making responsive utilities.\n//\n// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"\" (Returns a blank string)\n// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"-sm\"\n@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {\n @return if(breakpoint-min($name, $breakpoints) == null, \"\", \"-#{$name}\");\n}\n\n// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.\n// Makes the @content apply to the given breakpoint and wider.\n@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n @if $min {\n @media (min-width: $min) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media of at most the maximum breakpoint width. No query for the largest breakpoint.\n// Makes the @content apply to the given breakpoint and narrower.\n@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {\n $max: breakpoint-max($name, $breakpoints);\n @if $max {\n @media (max-width: $max) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media that spans multiple breakpoint widths.\n// Makes the @content apply between the min and max breakpoints\n@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($lower, $breakpoints);\n $max: breakpoint-max($upper, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($lower, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($upper, $breakpoints) {\n @content;\n }\n }\n}\n\n// Media between the breakpoint's minimum and maximum widths.\n// No minimum for the smallest breakpoint, and no maximum for the largest one.\n// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.\n@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n $max: breakpoint-max($name, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($name, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($name, $breakpoints) {\n @content;\n }\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `$grid-columns`.\n\n@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {\n // Common properties for all breakpoints\n %grid-column {\n position: relative;\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n }\n\n @each $breakpoint in map-keys($breakpoints) {\n $infix: breakpoint-infix($breakpoint, $breakpoints);\n\n // Allow columns to stretch full width below their breakpoints\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @extend %grid-column;\n }\n }\n .col#{$infix},\n .col#{$infix}-auto {\n @extend %grid-column;\n }\n\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n // Provide basic `.col-{bp}` classes for equal-width flexbox columns\n .col#{$infix} {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col#{$infix}-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%; // Reset earlier grid tiers\n }\n\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @include make-col($i, $columns);\n }\n }\n\n .order#{$infix}-first { order: -1; }\n\n .order#{$infix}-last { order: $columns + 1; }\n\n @for $i from 0 through $columns {\n .order#{$infix}-#{$i} { order: $i; }\n }\n\n // `$columns - 1` because offsetting by the width of an entire row isn't possible\n @for $i from 0 through ($columns - 1) {\n @if not ($infix == \"\" and $i == 0) { // Avoid emitting useless .offset-0\n .offset#{$infix}-#{$i} {\n @include make-col-offset($i, $columns);\n }\n }\n }\n }\n }\n}\n","// stylelint-disable declaration-no-important\n\n//\n// Utilities for common `display` values\n//\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n @each $value in $displays {\n .d#{$infix}-#{$value} { display: $value !important; }\n }\n }\n}\n\n\n//\n// Utilities for toggling `display` in print\n//\n\n@media print {\n @each $value in $displays {\n .d-print-#{$value} { display: $value !important; }\n }\n}\n","// stylelint-disable declaration-no-important\n\n// Flex variation\n//\n// Custom styles for additional flex alignment options.\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n .flex#{$infix}-row { flex-direction: row !important; }\n .flex#{$infix}-column { flex-direction: column !important; }\n .flex#{$infix}-row-reverse { flex-direction: row-reverse !important; }\n .flex#{$infix}-column-reverse { flex-direction: column-reverse !important; }\n\n .flex#{$infix}-wrap { flex-wrap: wrap !important; }\n .flex#{$infix}-nowrap { flex-wrap: nowrap !important; }\n .flex#{$infix}-wrap-reverse { flex-wrap: wrap-reverse !important; }\n .flex#{$infix}-fill { flex: 1 1 auto !important; }\n .flex#{$infix}-grow-0 { flex-grow: 0 !important; }\n .flex#{$infix}-grow-1 { flex-grow: 1 !important; }\n .flex#{$infix}-shrink-0 { flex-shrink: 0 !important; }\n .flex#{$infix}-shrink-1 { flex-shrink: 1 !important; }\n\n .justify-content#{$infix}-start { justify-content: flex-start !important; }\n .justify-content#{$infix}-end { justify-content: flex-end !important; }\n .justify-content#{$infix}-center { justify-content: center !important; }\n .justify-content#{$infix}-between { justify-content: space-between !important; }\n .justify-content#{$infix}-around { justify-content: space-around !important; }\n\n .align-items#{$infix}-start { align-items: flex-start !important; }\n .align-items#{$infix}-end { align-items: flex-end !important; }\n .align-items#{$infix}-center { align-items: center !important; }\n .align-items#{$infix}-baseline { align-items: baseline !important; }\n .align-items#{$infix}-stretch { align-items: stretch !important; }\n\n .align-content#{$infix}-start { align-content: flex-start !important; }\n .align-content#{$infix}-end { align-content: flex-end !important; }\n .align-content#{$infix}-center { align-content: center !important; }\n .align-content#{$infix}-between { align-content: space-between !important; }\n .align-content#{$infix}-around { align-content: space-around !important; }\n .align-content#{$infix}-stretch { align-content: stretch !important; }\n\n .align-self#{$infix}-auto { align-self: auto !important; }\n .align-self#{$infix}-start { align-self: flex-start !important; }\n .align-self#{$infix}-end { align-self: flex-end !important; }\n .align-self#{$infix}-center { align-self: center !important; }\n .align-self#{$infix}-baseline { align-self: baseline !important; }\n .align-self#{$infix}-stretch { align-self: stretch !important; }\n }\n}\n","// stylelint-disable declaration-no-important\n\n// Margin and Padding\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n @each $prop, $abbrev in (margin: m, padding: p) {\n @each $size, $length in $spacers {\n .#{$abbrev}#{$infix}-#{$size} { #{$prop}: $length !important; }\n .#{$abbrev}t#{$infix}-#{$size},\n .#{$abbrev}y#{$infix}-#{$size} {\n #{$prop}-top: $length !important;\n }\n .#{$abbrev}r#{$infix}-#{$size},\n .#{$abbrev}x#{$infix}-#{$size} {\n #{$prop}-right: $length !important;\n }\n .#{$abbrev}b#{$infix}-#{$size},\n .#{$abbrev}y#{$infix}-#{$size} {\n #{$prop}-bottom: $length !important;\n }\n .#{$abbrev}l#{$infix}-#{$size},\n .#{$abbrev}x#{$infix}-#{$size} {\n #{$prop}-left: $length !important;\n }\n }\n }\n\n // Negative margins (e.g., where `.mb-n1` is negative version of `.mb-1`)\n @each $size, $length in $spacers {\n @if $size != 0 {\n .m#{$infix}-n#{$size} { margin: -$length !important; }\n .mt#{$infix}-n#{$size},\n .my#{$infix}-n#{$size} {\n margin-top: -$length !important;\n }\n .mr#{$infix}-n#{$size},\n .mx#{$infix}-n#{$size} {\n margin-right: -$length !important;\n }\n .mb#{$infix}-n#{$size},\n .my#{$infix}-n#{$size} {\n margin-bottom: -$length !important;\n }\n .ml#{$infix}-n#{$size},\n .mx#{$infix}-n#{$size} {\n margin-left: -$length !important;\n }\n }\n }\n\n // Some special margin utils\n .m#{$infix}-auto { margin: auto !important; }\n .mt#{$infix}-auto,\n .my#{$infix}-auto {\n margin-top: auto !important;\n }\n .mr#{$infix}-auto,\n .mx#{$infix}-auto {\n margin-right: auto !important;\n }\n .mb#{$infix}-auto,\n .my#{$infix}-auto {\n margin-bottom: auto !important;\n }\n .ml#{$infix}-auto,\n .mx#{$infix}-auto {\n margin-left: auto !important;\n }\n }\n}\n"]} \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css index b3d7f4c6..09cf9869 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css @@ -1,7 +1,7 @@ /*! - * Bootstrap Reboot v4.1.3 (https://getbootstrap.com/) - * Copyright 2011-2018 The Bootstrap Authors - * Copyright 2011-2018 Twitter, Inc. + * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/) + * Copyright 2011-2019 The Bootstrap Authors + * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) */ @@ -15,22 +15,16 @@ html { font-family: sans-serif; line-height: 1.15; -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; - -ms-overflow-style: scrollbar; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } -@-ms-viewport { - width: device-width; -} - article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { display: block; } body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 1rem; font-weight: 400; line-height: 1.5; @@ -66,6 +60,8 @@ abbr[data-original-title] { text-decoration: underline dotted; cursor: help; border-bottom: 0; + -webkit-text-decoration-skip-ink: none; + text-decoration-skip-ink: none; } address { @@ -101,10 +97,6 @@ blockquote { margin: 0 0 1rem; } -dfn { - font-style: italic; -} - b, strong { font-weight: bolder; @@ -134,7 +126,6 @@ a { color: #007bff; text-decoration: none; background-color: transparent; - -webkit-text-decoration-skip: objects; } a:hover { @@ -168,7 +159,6 @@ pre { margin-top: 0; margin-bottom: 1rem; overflow: auto; - -ms-overflow-style: scrollbar; } figure { @@ -236,13 +226,24 @@ select { text-transform: none; } +select { + word-wrap: normal; +} + button, -html [type="button"], +[type="button"], [type="reset"], [type="submit"] { -webkit-appearance: button; } +button:not(:disabled), +[type="button"]:not(:disabled), +[type="reset"]:not(:disabled), +[type="submit"]:not(:disabled) { + cursor: pointer; +} + button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, @@ -302,7 +303,6 @@ progress { -webkit-appearance: none; } -[type="search"]::-webkit-search-cancel-button, [type="search"]::-webkit-search-decoration { -webkit-appearance: none; } diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map index 3a17ed96..d0b0f023 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map @@ -1 +1 @@ -{"version":3,"sources":["../../scss/bootstrap-reboot.scss","../../scss/_reboot.scss","../../scss/_variables.scss","bootstrap-reboot.css","../../scss/mixins/_hover.scss"],"names":[],"mappings":"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","file":"bootstrap-reboot.css","sourcesContent":["/*!\n * Bootstrap Reboot v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n\n@import \"functions\";\n@import \"variables\";\n@import \"mixins\";\n@import \"reboot\";\n","// stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix\n\n// Reboot\n//\n// Normalization of HTML elements, manually forked from Normalize.css to remove\n// styles targeting irrelevant browsers while applying new styles.\n//\n// Normalize is licensed MIT. https://github.com/necolas/normalize.css\n\n\n// Document\n//\n// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.\n// 2. Change the default font family in all browsers.\n// 3. Correct the line height in all browsers.\n// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.\n// 5. Setting @viewport causes scrollbars to overlap content in IE11 and Edge, so\n// we force a non-overlapping, non-auto-hiding scrollbar to counteract.\n// 6. Change the default tap highlight to be completely transparent in iOS.\n\n*,\n*::before,\n*::after {\n box-sizing: border-box; // 1\n}\n\nhtml {\n font-family: sans-serif; // 2\n line-height: 1.15; // 3\n -webkit-text-size-adjust: 100%; // 4\n -ms-text-size-adjust: 100%; // 4\n -ms-overflow-style: scrollbar; // 5\n -webkit-tap-highlight-color: rgba($black, 0); // 6\n}\n\n// IE10+ doesn't honor `` in some cases.\n@at-root {\n @-ms-viewport {\n width: device-width;\n }\n}\n\n// stylelint-disable selector-list-comma-newline-after\n// Shim for \"new\" HTML5 structural elements to display correctly (IE10, older browsers)\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n// stylelint-enable selector-list-comma-newline-after\n\n// Body\n//\n// 1. Remove the margin in all browsers.\n// 2. As a best practice, apply a default `background-color`.\n// 3. Set an explicit initial text-align value so that we can later use the\n// the `inherit` value on things like `` elements.\n\nbody {\n margin: 0; // 1\n font-family: $font-family-base;\n font-size: $font-size-base;\n font-weight: $font-weight-base;\n line-height: $line-height-base;\n color: $body-color;\n text-align: left; // 3\n background-color: $body-bg; // 2\n}\n\n// Suppress the focus outline on elements that cannot be accessed via keyboard.\n// This prevents an unwanted focus outline from appearing around elements that\n// might still respond to pointer events.\n//\n// Credit: https://github.com/suitcss/base\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\n\n// Content grouping\n//\n// 1. Add the correct box sizing in Firefox.\n// 2. Show the overflow in Edge and IE.\n\nhr {\n box-sizing: content-box; // 1\n height: 0; // 1\n overflow: visible; // 2\n}\n\n\n//\n// Typography\n//\n\n// Remove top margins from headings\n//\n// By default, `

    `-`

    ` all receive top and bottom margins. We nuke the top\n// margin for easier control within type scales as it avoids margin collapsing.\n// stylelint-disable selector-list-comma-newline-after\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: $headings-margin-bottom;\n}\n// stylelint-enable selector-list-comma-newline-after\n\n// Reset margins on paragraphs\n//\n// Similarly, the top margin on `

    `s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n// Abbreviations\n//\n// 1. Remove the bottom border in Firefox 39-.\n// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Duplicate behavior to the data-* attribute for our tooltip plugin\n\nabbr[title],\nabbr[data-original-title] { // 4\n text-decoration: underline; // 2\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n border-bottom: 0; // 1\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // Undo browser default\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\ndfn {\n font-style: italic; // Add the correct font style in Android 4.3-\n}\n\n// stylelint-disable font-weight-notation\nb,\nstrong {\n font-weight: bolder; // Add the correct font weight in Chrome, Edge, and Safari\n}\n// stylelint-enable font-weight-notation\n\nsmall {\n font-size: 80%; // Add the correct font size in all browsers\n}\n\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n//\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n//\n// Links\n//\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n background-color: transparent; // Remove the gray background on active links in IE 10.\n -webkit-text-decoration-skip: objects; // Remove gaps in links underline in iOS 8+ and Safari 8+.\n\n @include hover {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href)\n// which have not been made explicitly keyboard-focusable (without tabindex).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n\n @include hover-focus {\n color: inherit;\n text-decoration: none;\n }\n\n &:focus {\n outline: 0;\n }\n}\n\n\n//\n// Code\n//\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-monospace;\n font-size: 1em; // Correct the odd `em` font sizing in all browsers.\n}\n\npre {\n // Remove browser default top margin\n margin-top: 0;\n // Reset browser default of `1em` to use `rem`s\n margin-bottom: 1rem;\n // Don't allow content to break outside\n overflow: auto;\n // We have @viewport set which causes scrollbars to overlap content in IE11 and Edge, so\n // we force a non-overlapping, non-auto-hiding scrollbar to counteract.\n -ms-overflow-style: scrollbar;\n}\n\n\n//\n// Figures\n//\n\nfigure {\n // Apply a consistent margin strategy (matches our type styles).\n margin: 0 0 1rem;\n}\n\n\n//\n// Images and content\n//\n\nimg {\n vertical-align: middle;\n border-style: none; // Remove the border on images inside links in IE 10-.\n}\n\nsvg {\n // Workaround for the SVG overflow bug in IE10/11 is still required.\n // See https://github.com/twbs/bootstrap/issues/26878\n overflow: hidden;\n vertical-align: middle;\n}\n\n\n//\n// Tables\n//\n\ntable {\n border-collapse: collapse; // Prevent double borders\n}\n\ncaption {\n padding-top: $table-cell-padding;\n padding-bottom: $table-cell-padding;\n color: $table-caption-color;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n // Matches default `` alignment by inheriting from the ``, or the\n // closest parent with a set `text-align`.\n text-align: inherit;\n}\n\n\n//\n// Forms\n//\n\nlabel {\n // Allow labels to use `margin` for spacing.\n display: inline-block;\n margin-bottom: $label-margin-bottom;\n}\n\n// Remove the default `border-radius` that macOS Chrome adds.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24093\nbutton {\n border-radius: 0;\n}\n\n// Work around a Firefox/IE bug where the transparent `button` background\n// results in a loss of the default `button` focus styles.\n//\n// Credit: https://github.com/suitcss/base/\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0; // Remove the margin in Firefox and Safari\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible; // Show the overflow in Edge\n}\n\nbutton,\nselect {\n text-transform: none; // Remove the inheritance of text transform in Firefox\n}\n\n// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`\n// controls in Android 4.\n// 2. Correct the inability to style clickable types in iOS and Safari.\nbutton,\nhtml [type=\"button\"], // 1\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button; // 2\n}\n\n// Remove inner border and padding from Firefox, but don't restore the outline like Normalize.\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box; // 1. Add the correct box sizing in IE 10-\n padding: 0; // 2. Remove the padding in IE 10-\n}\n\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n // Remove the default appearance of temporal inputs to avoid a Mobile Safari\n // bug where setting a custom line-height prevents text from being vertically\n // centered within the input.\n // See https://bugs.webkit.org/show_bug.cgi?id=139848\n // and https://github.com/twbs/bootstrap/issues/11266\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto; // Remove the default vertical scrollbar in IE.\n // Textareas should really only resize vertically so they don't break their (horizontal) containers.\n resize: vertical;\n}\n\nfieldset {\n // Browsers set a default `min-width: min-content;` on fieldsets,\n // unlike e.g. `

    `s, which have `min-width: 0;` by default.\n // So we reset that to ensure fieldsets behave more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359\n // and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements\n min-width: 0;\n // Reset the default outline behavior of fieldsets so they don't affect page layout.\n padding: 0;\n margin: 0;\n border: 0;\n}\n\n// 1. Correct the text wrapping in Edge and IE.\n// 2. Correct the color inheritance from `fieldset` elements in IE.\nlegend {\n display: block;\n width: 100%;\n max-width: 100%; // 1\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit; // 2\n white-space: normal; // 1\n}\n\nprogress {\n vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera.\n}\n\n// Correct the cursor style of increment and decrement buttons in Chrome.\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n // This overrides the extra rounded corners on search inputs in iOS so that our\n // `.form-control` class can properly style them. Note that this cannot simply\n // be added to `.form-control` as it's not specific enough. For details, see\n // https://github.com/twbs/bootstrap/issues/11586.\n outline-offset: -2px; // 2. Correct the outline style in Safari.\n -webkit-appearance: none;\n}\n\n//\n// Remove the inner padding and cancel buttons in Chrome and Safari on macOS.\n//\n\n[type=\"search\"]::-webkit-search-cancel-button,\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// 1. Correct the inability to style clickable types in iOS and Safari.\n// 2. Change font properties to `inherit` in Safari.\n//\n\n::-webkit-file-upload-button {\n font: inherit; // 2\n -webkit-appearance: button; // 1\n}\n\n//\n// Correct element displays\n//\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item; // Add the correct display in all browsers\n cursor: pointer;\n}\n\ntemplate {\n display: none; // Add the correct display in IE\n}\n\n// Always hide an element with the `hidden` HTML attribute (from PureCSS).\n// Needed for proper display in IE 10-.\n[hidden] {\n display: none !important;\n}\n","// Variables\n//\n// Variables should follow the `$component-state-property-size` formula for\n// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs.\n\n\n//\n// Color system\n//\n\n$white: #fff !default;\n$gray-100: #f8f9fa !default;\n$gray-200: #e9ecef !default;\n$gray-300: #dee2e6 !default;\n$gray-400: #ced4da !default;\n$gray-500: #adb5bd !default;\n$gray-600: #6c757d !default;\n$gray-700: #495057 !default;\n$gray-800: #343a40 !default;\n$gray-900: #212529 !default;\n$black: #000 !default;\n\n$grays: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$grays: map-merge(\n (\n \"100\": $gray-100,\n \"200\": $gray-200,\n \"300\": $gray-300,\n \"400\": $gray-400,\n \"500\": $gray-500,\n \"600\": $gray-600,\n \"700\": $gray-700,\n \"800\": $gray-800,\n \"900\": $gray-900\n ),\n $grays\n);\n\n\n$blue: #007bff !default;\n$indigo: #6610f2 !default;\n$purple: #6f42c1 !default;\n$pink: #e83e8c !default;\n$red: #dc3545 !default;\n$orange: #fd7e14 !default;\n$yellow: #ffc107 !default;\n$green: #28a745 !default;\n$teal: #20c997 !default;\n$cyan: #17a2b8 !default;\n\n$colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$colors: map-merge(\n (\n \"blue\": $blue,\n \"indigo\": $indigo,\n \"purple\": $purple,\n \"pink\": $pink,\n \"red\": $red,\n \"orange\": $orange,\n \"yellow\": $yellow,\n \"green\": $green,\n \"teal\": $teal,\n \"cyan\": $cyan,\n \"white\": $white,\n \"gray\": $gray-600,\n \"gray-dark\": $gray-800\n ),\n $colors\n);\n\n$primary: $blue !default;\n$secondary: $gray-600 !default;\n$success: $green !default;\n$info: $cyan !default;\n$warning: $yellow !default;\n$danger: $red !default;\n$light: $gray-100 !default;\n$dark: $gray-800 !default;\n\n$theme-colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$theme-colors: map-merge(\n (\n \"primary\": $primary,\n \"secondary\": $secondary,\n \"success\": $success,\n \"info\": $info,\n \"warning\": $warning,\n \"danger\": $danger,\n \"light\": $light,\n \"dark\": $dark\n ),\n $theme-colors\n);\n\n// Set a specific jump point for requesting color jumps\n$theme-color-interval: 8% !default;\n\n// The yiq lightness value that determines when the lightness of color changes from \"dark\" to \"light\". Acceptable values are between 0 and 255.\n$yiq-contrasted-threshold: 150 !default;\n\n// Customize the light and dark text colors for use in our YIQ color contrast function.\n$yiq-text-dark: $gray-900 !default;\n$yiq-text-light: $white !default;\n\n// Options\n//\n// Quickly modify global styling by enabling or disabling optional features.\n\n$enable-caret: true !default;\n$enable-rounded: true !default;\n$enable-shadows: false !default;\n$enable-gradients: false !default;\n$enable-transitions: true !default;\n$enable-hover-media-query: false !default; // Deprecated, no longer affects any compiled CSS\n$enable-grid-classes: true !default;\n$enable-print-styles: true !default;\n\n\n// Spacing\n//\n// Control the default styling of most Bootstrap elements by modifying these\n// variables. Mostly focused on spacing.\n// You can add more entries to the $spacers map, should you need more variation.\n\n$spacer: 1rem !default;\n$spacers: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$spacers: map-merge(\n (\n 0: 0,\n 1: ($spacer * .25),\n 2: ($spacer * .5),\n 3: $spacer,\n 4: ($spacer * 1.5),\n 5: ($spacer * 3)\n ),\n $spacers\n);\n\n// This variable affects the `.h-*` and `.w-*` classes.\n$sizes: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$sizes: map-merge(\n (\n 25: 25%,\n 50: 50%,\n 75: 75%,\n 100: 100%,\n auto: auto\n ),\n $sizes\n);\n\n// Body\n//\n// Settings for the `` element.\n\n$body-bg: $white !default;\n$body-color: $gray-900 !default;\n\n// Links\n//\n// Style anchor elements.\n\n$link-color: theme-color(\"primary\") !default;\n$link-decoration: none !default;\n$link-hover-color: darken($link-color, 15%) !default;\n$link-hover-decoration: underline !default;\n\n// Paragraphs\n//\n// Style p element.\n\n$paragraph-margin-bottom: 1rem !default;\n\n\n// Grid breakpoints\n//\n// Define the minimum dimensions at which your layout will change,\n// adapting to different screen sizes, for use in media queries.\n\n$grid-breakpoints: (\n xs: 0,\n sm: 576px,\n md: 768px,\n lg: 992px,\n xl: 1200px\n) !default;\n\n@include _assert-ascending($grid-breakpoints, \"$grid-breakpoints\");\n@include _assert-starts-at-zero($grid-breakpoints);\n\n\n// Grid containers\n//\n// Define the maximum width of `.container` for different screen sizes.\n\n$container-max-widths: (\n sm: 540px,\n md: 720px,\n lg: 960px,\n xl: 1140px\n) !default;\n\n@include _assert-ascending($container-max-widths, \"$container-max-widths\");\n\n\n// Grid columns\n//\n// Set the number of columns and specify the width of the gutters.\n\n$grid-columns: 12 !default;\n$grid-gutter-width: 30px !default;\n\n// Components\n//\n// Define common padding and border radius sizes and more.\n\n$line-height-lg: 1.5 !default;\n$line-height-sm: 1.5 !default;\n\n$border-width: 1px !default;\n$border-color: $gray-300 !default;\n\n$border-radius: .25rem !default;\n$border-radius-lg: .3rem !default;\n$border-radius-sm: .2rem !default;\n\n$box-shadow-sm: 0 .125rem .25rem rgba($black, .075) !default;\n$box-shadow: 0 .5rem 1rem rgba($black, .15) !default;\n$box-shadow-lg: 0 1rem 3rem rgba($black, .175) !default;\n\n$component-active-color: $white !default;\n$component-active-bg: theme-color(\"primary\") !default;\n\n$caret-width: .3em !default;\n\n$transition-base: all .2s ease-in-out !default;\n$transition-fade: opacity .15s linear !default;\n$transition-collapse: height .35s ease !default;\n\n\n// Fonts\n//\n// Font, line-height, and color for body text, headings, and more.\n\n// stylelint-disable value-keyword-case\n$font-family-sans-serif: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\" !default;\n$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace !default;\n$font-family-base: $font-family-sans-serif !default;\n// stylelint-enable value-keyword-case\n\n$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`\n$font-size-lg: ($font-size-base * 1.25) !default;\n$font-size-sm: ($font-size-base * .875) !default;\n\n$font-weight-light: 300 !default;\n$font-weight-normal: 400 !default;\n$font-weight-bold: 700 !default;\n\n$font-weight-base: $font-weight-normal !default;\n$line-height-base: 1.5 !default;\n\n$h1-font-size: $font-size-base * 2.5 !default;\n$h2-font-size: $font-size-base * 2 !default;\n$h3-font-size: $font-size-base * 1.75 !default;\n$h4-font-size: $font-size-base * 1.5 !default;\n$h5-font-size: $font-size-base * 1.25 !default;\n$h6-font-size: $font-size-base !default;\n\n$headings-margin-bottom: ($spacer / 2) !default;\n$headings-font-family: inherit !default;\n$headings-font-weight: 500 !default;\n$headings-line-height: 1.2 !default;\n$headings-color: inherit !default;\n\n$display1-size: 6rem !default;\n$display2-size: 5.5rem !default;\n$display3-size: 4.5rem !default;\n$display4-size: 3.5rem !default;\n\n$display1-weight: 300 !default;\n$display2-weight: 300 !default;\n$display3-weight: 300 !default;\n$display4-weight: 300 !default;\n$display-line-height: $headings-line-height !default;\n\n$lead-font-size: ($font-size-base * 1.25) !default;\n$lead-font-weight: 300 !default;\n\n$small-font-size: 80% !default;\n\n$text-muted: $gray-600 !default;\n\n$blockquote-small-color: $gray-600 !default;\n$blockquote-font-size: ($font-size-base * 1.25) !default;\n\n$hr-border-color: rgba($black, .1) !default;\n$hr-border-width: $border-width !default;\n\n$mark-padding: .2em !default;\n\n$dt-font-weight: $font-weight-bold !default;\n\n$kbd-box-shadow: inset 0 -.1rem 0 rgba($black, .25) !default;\n$nested-kbd-font-weight: $font-weight-bold !default;\n\n$list-inline-padding: .5rem !default;\n\n$mark-bg: #fcf8e3 !default;\n\n$hr-margin-y: $spacer !default;\n\n\n// Tables\n//\n// Customizes the `.table` component with basic values, each used across all table variations.\n\n$table-cell-padding: .75rem !default;\n$table-cell-padding-sm: .3rem !default;\n\n$table-bg: transparent !default;\n$table-accent-bg: rgba($black, .05) !default;\n$table-hover-bg: rgba($black, .075) !default;\n$table-active-bg: $table-hover-bg !default;\n\n$table-border-width: $border-width !default;\n$table-border-color: $gray-300 !default;\n\n$table-head-bg: $gray-200 !default;\n$table-head-color: $gray-700 !default;\n\n$table-dark-bg: $gray-900 !default;\n$table-dark-accent-bg: rgba($white, .05) !default;\n$table-dark-hover-bg: rgba($white, .075) !default;\n$table-dark-border-color: lighten($gray-900, 7.5%) !default;\n$table-dark-color: $body-bg !default;\n\n$table-striped-order: odd !default;\n\n$table-caption-color: $text-muted !default;\n\n// Buttons + Forms\n//\n// Shared variables that are reassigned to `$input-` and `$btn-` specific variables.\n\n$input-btn-padding-y: .375rem !default;\n$input-btn-padding-x: .75rem !default;\n$input-btn-line-height: $line-height-base !default;\n\n$input-btn-focus-width: .2rem !default;\n$input-btn-focus-color: rgba($component-active-bg, .25) !default;\n$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default;\n\n$input-btn-padding-y-sm: .25rem !default;\n$input-btn-padding-x-sm: .5rem !default;\n$input-btn-line-height-sm: $line-height-sm !default;\n\n$input-btn-padding-y-lg: .5rem !default;\n$input-btn-padding-x-lg: 1rem !default;\n$input-btn-line-height-lg: $line-height-lg !default;\n\n$input-btn-border-width: $border-width !default;\n\n\n// Buttons\n//\n// For each of Bootstrap's buttons, define text, background, and border color.\n\n$btn-padding-y: $input-btn-padding-y !default;\n$btn-padding-x: $input-btn-padding-x !default;\n$btn-line-height: $input-btn-line-height !default;\n\n$btn-padding-y-sm: $input-btn-padding-y-sm !default;\n$btn-padding-x-sm: $input-btn-padding-x-sm !default;\n$btn-line-height-sm: $input-btn-line-height-sm !default;\n\n$btn-padding-y-lg: $input-btn-padding-y-lg !default;\n$btn-padding-x-lg: $input-btn-padding-x-lg !default;\n$btn-line-height-lg: $input-btn-line-height-lg !default;\n\n$btn-border-width: $input-btn-border-width !default;\n\n$btn-font-weight: $font-weight-normal !default;\n$btn-box-shadow: inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default;\n$btn-focus-width: $input-btn-focus-width !default;\n$btn-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$btn-disabled-opacity: .65 !default;\n$btn-active-box-shadow: inset 0 3px 5px rgba($black, .125) !default;\n\n$btn-link-disabled-color: $gray-600 !default;\n\n$btn-block-spacing-y: .5rem !default;\n\n// Allows for customizing button radius independently from global border radius\n$btn-border-radius: $border-radius !default;\n$btn-border-radius-lg: $border-radius-lg !default;\n$btn-border-radius-sm: $border-radius-sm !default;\n\n$btn-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n\n// Forms\n\n$label-margin-bottom: .5rem !default;\n\n$input-padding-y: $input-btn-padding-y !default;\n$input-padding-x: $input-btn-padding-x !default;\n$input-line-height: $input-btn-line-height !default;\n\n$input-padding-y-sm: $input-btn-padding-y-sm !default;\n$input-padding-x-sm: $input-btn-padding-x-sm !default;\n$input-line-height-sm: $input-btn-line-height-sm !default;\n\n$input-padding-y-lg: $input-btn-padding-y-lg !default;\n$input-padding-x-lg: $input-btn-padding-x-lg !default;\n$input-line-height-lg: $input-btn-line-height-lg !default;\n\n$input-bg: $white !default;\n$input-disabled-bg: $gray-200 !default;\n\n$input-color: $gray-700 !default;\n$input-border-color: $gray-400 !default;\n$input-border-width: $input-btn-border-width !default;\n$input-box-shadow: inset 0 1px 1px rgba($black, .075) !default;\n\n$input-border-radius: $border-radius !default;\n$input-border-radius-lg: $border-radius-lg !default;\n$input-border-radius-sm: $border-radius-sm !default;\n\n$input-focus-bg: $input-bg !default;\n$input-focus-border-color: lighten($component-active-bg, 25%) !default;\n$input-focus-color: $input-color !default;\n$input-focus-width: $input-btn-focus-width !default;\n$input-focus-box-shadow: $input-btn-focus-box-shadow !default;\n\n$input-placeholder-color: $gray-600 !default;\n$input-plaintext-color: $body-color !default;\n\n$input-height-border: $input-border-width * 2 !default;\n\n$input-height-inner: ($font-size-base * $input-btn-line-height) + ($input-btn-padding-y * 2) !default;\n$input-height: calc(#{$input-height-inner} + #{$input-height-border}) !default;\n\n$input-height-inner-sm: ($font-size-sm * $input-btn-line-height-sm) + ($input-btn-padding-y-sm * 2) !default;\n$input-height-sm: calc(#{$input-height-inner-sm} + #{$input-height-border}) !default;\n\n$input-height-inner-lg: ($font-size-lg * $input-btn-line-height-lg) + ($input-btn-padding-y-lg * 2) !default;\n$input-height-lg: calc(#{$input-height-inner-lg} + #{$input-height-border}) !default;\n\n$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$form-text-margin-top: .25rem !default;\n\n$form-check-input-gutter: 1.25rem !default;\n$form-check-input-margin-y: .3rem !default;\n$form-check-input-margin-x: .25rem !default;\n\n$form-check-inline-margin-x: .75rem !default;\n$form-check-inline-input-margin-x: .3125rem !default;\n\n$form-group-margin-bottom: 1rem !default;\n\n$input-group-addon-color: $input-color !default;\n$input-group-addon-bg: $gray-200 !default;\n$input-group-addon-border-color: $input-border-color !default;\n\n$custom-forms-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$custom-control-gutter: 1.5rem !default;\n$custom-control-spacer-x: 1rem !default;\n\n$custom-control-indicator-size: 1rem !default;\n$custom-control-indicator-bg: $gray-300 !default;\n$custom-control-indicator-bg-size: 50% 50% !default;\n$custom-control-indicator-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;\n\n$custom-control-indicator-disabled-bg: $gray-200 !default;\n$custom-control-label-disabled-color: $gray-600 !default;\n\n$custom-control-indicator-checked-color: $component-active-color !default;\n$custom-control-indicator-checked-bg: $component-active-bg !default;\n$custom-control-indicator-checked-disabled-bg: rgba(theme-color(\"primary\"), .5) !default;\n$custom-control-indicator-checked-box-shadow: none !default;\n\n$custom-control-indicator-focus-box-shadow: 0 0 0 1px $body-bg, $input-btn-focus-box-shadow !default;\n\n$custom-control-indicator-active-color: $component-active-color !default;\n$custom-control-indicator-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-control-indicator-active-box-shadow: none !default;\n\n$custom-checkbox-indicator-border-radius: $border-radius !default;\n$custom-checkbox-indicator-icon-checked: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n\n$custom-checkbox-indicator-indeterminate-bg: $component-active-bg !default;\n$custom-checkbox-indicator-indeterminate-color: $custom-control-indicator-checked-color !default;\n$custom-checkbox-indicator-icon-indeterminate: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$custom-checkbox-indicator-indeterminate-box-shadow: none !default;\n\n$custom-radio-indicator-border-radius: 50% !default;\n$custom-radio-indicator-icon-checked: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='#{$custom-control-indicator-checked-color}'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n\n$custom-select-padding-y: .375rem !default;\n$custom-select-padding-x: .75rem !default;\n$custom-select-height: $input-height !default;\n$custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator\n$custom-select-line-height: $input-btn-line-height !default;\n$custom-select-color: $input-color !default;\n$custom-select-disabled-color: $gray-600 !default;\n$custom-select-bg: $input-bg !default;\n$custom-select-disabled-bg: $gray-200 !default;\n$custom-select-bg-size: 8px 10px !default; // In pixels because image dimensions\n$custom-select-indicator-color: $gray-800 !default;\n$custom-select-indicator: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$custom-select-border-width: $input-btn-border-width !default;\n$custom-select-border-color: $input-border-color !default;\n$custom-select-border-radius: $border-radius !default;\n$custom-select-box-shadow: inset 0 1px 2px rgba($black, .075) !default;\n\n$custom-select-focus-border-color: $input-focus-border-color !default;\n$custom-select-focus-width: $input-btn-focus-width !default;\n$custom-select-focus-box-shadow: 0 0 0 $custom-select-focus-width rgba($custom-select-focus-border-color, .5) !default;\n\n$custom-select-font-size-sm: 75% !default;\n$custom-select-height-sm: $input-height-sm !default;\n\n$custom-select-font-size-lg: 125% !default;\n$custom-select-height-lg: $input-height-lg !default;\n\n$custom-range-track-width: 100% !default;\n$custom-range-track-height: .5rem !default;\n$custom-range-track-cursor: pointer !default;\n$custom-range-track-bg: $gray-300 !default;\n$custom-range-track-border-radius: 1rem !default;\n$custom-range-track-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;\n\n$custom-range-thumb-width: 1rem !default;\n$custom-range-thumb-height: $custom-range-thumb-width !default;\n$custom-range-thumb-bg: $component-active-bg !default;\n$custom-range-thumb-border: 0 !default;\n$custom-range-thumb-border-radius: 1rem !default;\n$custom-range-thumb-box-shadow: 0 .1rem .25rem rgba($black, .1) !default;\n$custom-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-btn-focus-box-shadow !default;\n$custom-range-thumb-focus-box-shadow-width: $input-btn-focus-width !default; // For focus box shadow issue in IE/Edge\n$custom-range-thumb-active-bg: lighten($component-active-bg, 35%) !default;\n\n$custom-file-height: $input-height !default;\n$custom-file-height-inner: $input-height-inner !default;\n$custom-file-focus-border-color: $input-focus-border-color !default;\n$custom-file-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$custom-file-disabled-bg: $input-disabled-bg !default;\n\n$custom-file-padding-y: $input-btn-padding-y !default;\n$custom-file-padding-x: $input-btn-padding-x !default;\n$custom-file-line-height: $input-btn-line-height !default;\n$custom-file-color: $input-color !default;\n$custom-file-bg: $input-bg !default;\n$custom-file-border-width: $input-btn-border-width !default;\n$custom-file-border-color: $input-border-color !default;\n$custom-file-border-radius: $input-border-radius !default;\n$custom-file-box-shadow: $input-box-shadow !default;\n$custom-file-button-color: $custom-file-color !default;\n$custom-file-button-bg: $input-group-addon-bg !default;\n$custom-file-text: (\n en: \"Browse\"\n) !default;\n\n\n// Form validation\n$form-feedback-margin-top: $form-text-margin-top !default;\n$form-feedback-font-size: $small-font-size !default;\n$form-feedback-valid-color: theme-color(\"success\") !default;\n$form-feedback-invalid-color: theme-color(\"danger\") !default;\n\n\n// Dropdowns\n//\n// Dropdown menu container and contents.\n\n$dropdown-min-width: 10rem !default;\n$dropdown-padding-y: .5rem !default;\n$dropdown-spacer: .125rem !default;\n$dropdown-bg: $white !default;\n$dropdown-border-color: rgba($black, .15) !default;\n$dropdown-border-radius: $border-radius !default;\n$dropdown-border-width: $border-width !default;\n$dropdown-divider-bg: $gray-200 !default;\n$dropdown-box-shadow: 0 .5rem 1rem rgba($black, .175) !default;\n\n$dropdown-link-color: $gray-900 !default;\n$dropdown-link-hover-color: darken($gray-900, 5%) !default;\n$dropdown-link-hover-bg: $gray-100 !default;\n\n$dropdown-link-active-color: $component-active-color !default;\n$dropdown-link-active-bg: $component-active-bg !default;\n\n$dropdown-link-disabled-color: $gray-600 !default;\n\n$dropdown-item-padding-y: .25rem !default;\n$dropdown-item-padding-x: 1.5rem !default;\n\n$dropdown-header-color: $gray-600 !default;\n\n\n// Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n\n$zindex-dropdown: 1000 !default;\n$zindex-sticky: 1020 !default;\n$zindex-fixed: 1030 !default;\n$zindex-modal-backdrop: 1040 !default;\n$zindex-modal: 1050 !default;\n$zindex-popover: 1060 !default;\n$zindex-tooltip: 1070 !default;\n\n// Navs\n\n$nav-link-padding-y: .5rem !default;\n$nav-link-padding-x: 1rem !default;\n$nav-link-disabled-color: $gray-600 !default;\n\n$nav-tabs-border-color: $gray-300 !default;\n$nav-tabs-border-width: $border-width !default;\n$nav-tabs-border-radius: $border-radius !default;\n$nav-tabs-link-hover-border-color: $gray-200 $gray-200 $nav-tabs-border-color !default;\n$nav-tabs-link-active-color: $gray-700 !default;\n$nav-tabs-link-active-bg: $body-bg !default;\n$nav-tabs-link-active-border-color: $gray-300 $gray-300 $nav-tabs-link-active-bg !default;\n\n$nav-pills-border-radius: $border-radius !default;\n$nav-pills-link-active-color: $component-active-color !default;\n$nav-pills-link-active-bg: $component-active-bg !default;\n\n$nav-divider-color: $gray-200 !default;\n$nav-divider-margin-y: ($spacer / 2) !default;\n\n// Navbar\n\n$navbar-padding-y: ($spacer / 2) !default;\n$navbar-padding-x: $spacer !default;\n\n$navbar-nav-link-padding-x: .5rem !default;\n\n$navbar-brand-font-size: $font-size-lg !default;\n// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link\n$nav-link-height: ($font-size-base * $line-height-base + $nav-link-padding-y * 2) !default;\n$navbar-brand-height: $navbar-brand-font-size * $line-height-base !default;\n$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) / 2 !default;\n\n$navbar-toggler-padding-y: .25rem !default;\n$navbar-toggler-padding-x: .75rem !default;\n$navbar-toggler-font-size: $font-size-lg !default;\n$navbar-toggler-border-radius: $btn-border-radius !default;\n\n$navbar-dark-color: rgba($white, .5) !default;\n$navbar-dark-hover-color: rgba($white, .75) !default;\n$navbar-dark-active-color: $white !default;\n$navbar-dark-disabled-color: rgba($white, .25) !default;\n$navbar-dark-toggler-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$navbar-dark-toggler-border-color: rgba($white, .1) !default;\n\n$navbar-light-color: rgba($black, .5) !default;\n$navbar-light-hover-color: rgba($black, .7) !default;\n$navbar-light-active-color: rgba($black, .9) !default;\n$navbar-light-disabled-color: rgba($black, .3) !default;\n$navbar-light-toggler-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$navbar-light-toggler-border-color: rgba($black, .1) !default;\n\n// Pagination\n\n$pagination-padding-y: .5rem !default;\n$pagination-padding-x: .75rem !default;\n$pagination-padding-y-sm: .25rem !default;\n$pagination-padding-x-sm: .5rem !default;\n$pagination-padding-y-lg: .75rem !default;\n$pagination-padding-x-lg: 1.5rem !default;\n$pagination-line-height: 1.25 !default;\n\n$pagination-color: $link-color !default;\n$pagination-bg: $white !default;\n$pagination-border-width: $border-width !default;\n$pagination-border-color: $gray-300 !default;\n\n$pagination-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$pagination-focus-outline: 0 !default;\n\n$pagination-hover-color: $link-hover-color !default;\n$pagination-hover-bg: $gray-200 !default;\n$pagination-hover-border-color: $gray-300 !default;\n\n$pagination-active-color: $component-active-color !default;\n$pagination-active-bg: $component-active-bg !default;\n$pagination-active-border-color: $pagination-active-bg !default;\n\n$pagination-disabled-color: $gray-600 !default;\n$pagination-disabled-bg: $white !default;\n$pagination-disabled-border-color: $gray-300 !default;\n\n\n// Jumbotron\n\n$jumbotron-padding: 2rem !default;\n$jumbotron-bg: $gray-200 !default;\n\n\n// Cards\n\n$card-spacer-y: .75rem !default;\n$card-spacer-x: 1.25rem !default;\n$card-border-width: $border-width !default;\n$card-border-radius: $border-radius !default;\n$card-border-color: rgba($black, .125) !default;\n$card-inner-border-radius: calc(#{$card-border-radius} - #{$card-border-width}) !default;\n$card-cap-bg: rgba($black, .03) !default;\n$card-bg: $white !default;\n\n$card-img-overlay-padding: 1.25rem !default;\n\n$card-group-margin: ($grid-gutter-width / 2) !default;\n$card-deck-margin: $card-group-margin !default;\n\n$card-columns-count: 3 !default;\n$card-columns-gap: 1.25rem !default;\n$card-columns-margin: $card-spacer-y !default;\n\n\n// Tooltips\n\n$tooltip-font-size: $font-size-sm !default;\n$tooltip-max-width: 200px !default;\n$tooltip-color: $white !default;\n$tooltip-bg: $black !default;\n$tooltip-border-radius: $border-radius !default;\n$tooltip-opacity: .9 !default;\n$tooltip-padding-y: .25rem !default;\n$tooltip-padding-x: .5rem !default;\n$tooltip-margin: 0 !default;\n\n$tooltip-arrow-width: .8rem !default;\n$tooltip-arrow-height: .4rem !default;\n$tooltip-arrow-color: $tooltip-bg !default;\n\n\n// Popovers\n\n$popover-font-size: $font-size-sm !default;\n$popover-bg: $white !default;\n$popover-max-width: 276px !default;\n$popover-border-width: $border-width !default;\n$popover-border-color: rgba($black, .2) !default;\n$popover-border-radius: $border-radius-lg !default;\n$popover-box-shadow: 0 .25rem .5rem rgba($black, .2) !default;\n\n$popover-header-bg: darken($popover-bg, 3%) !default;\n$popover-header-color: $headings-color !default;\n$popover-header-padding-y: .5rem !default;\n$popover-header-padding-x: .75rem !default;\n\n$popover-body-color: $body-color !default;\n$popover-body-padding-y: $popover-header-padding-y !default;\n$popover-body-padding-x: $popover-header-padding-x !default;\n\n$popover-arrow-width: 1rem !default;\n$popover-arrow-height: .5rem !default;\n$popover-arrow-color: $popover-bg !default;\n\n$popover-arrow-outer-color: fade-in($popover-border-color, .05) !default;\n\n\n// Badges\n\n$badge-font-size: 75% !default;\n$badge-font-weight: $font-weight-bold !default;\n$badge-padding-y: .25em !default;\n$badge-padding-x: .4em !default;\n$badge-border-radius: $border-radius !default;\n\n$badge-pill-padding-x: .6em !default;\n// Use a higher than normal value to ensure completely rounded edges when\n// customizing padding or font-size on labels.\n$badge-pill-border-radius: 10rem !default;\n\n\n// Modals\n\n// Padding applied to the modal body\n$modal-inner-padding: 1rem !default;\n\n$modal-dialog-margin: .5rem !default;\n$modal-dialog-margin-y-sm-up: 1.75rem !default;\n\n$modal-title-line-height: $line-height-base !default;\n\n$modal-content-bg: $white !default;\n$modal-content-border-color: rgba($black, .2) !default;\n$modal-content-border-width: $border-width !default;\n$modal-content-border-radius: $border-radius-lg !default;\n$modal-content-box-shadow-xs: 0 .25rem .5rem rgba($black, .5) !default;\n$modal-content-box-shadow-sm-up: 0 .5rem 1rem rgba($black, .5) !default;\n\n$modal-backdrop-bg: $black !default;\n$modal-backdrop-opacity: .5 !default;\n$modal-header-border-color: $gray-200 !default;\n$modal-footer-border-color: $modal-header-border-color !default;\n$modal-header-border-width: $modal-content-border-width !default;\n$modal-footer-border-width: $modal-header-border-width !default;\n$modal-header-padding: 1rem !default;\n\n$modal-lg: 800px !default;\n$modal-md: 500px !default;\n$modal-sm: 300px !default;\n\n$modal-transition: transform .3s ease-out !default;\n\n\n// Alerts\n//\n// Define alert colors, border radius, and padding.\n\n$alert-padding-y: .75rem !default;\n$alert-padding-x: 1.25rem !default;\n$alert-margin-bottom: 1rem !default;\n$alert-border-radius: $border-radius !default;\n$alert-link-font-weight: $font-weight-bold !default;\n$alert-border-width: $border-width !default;\n\n$alert-bg-level: -10 !default;\n$alert-border-level: -9 !default;\n$alert-color-level: 6 !default;\n\n\n// Progress bars\n\n$progress-height: 1rem !default;\n$progress-font-size: ($font-size-base * .75) !default;\n$progress-bg: $gray-200 !default;\n$progress-border-radius: $border-radius !default;\n$progress-box-shadow: inset 0 .1rem .1rem rgba($black, .1) !default;\n$progress-bar-color: $white !default;\n$progress-bar-bg: theme-color(\"primary\") !default;\n$progress-bar-animation-timing: 1s linear infinite !default;\n$progress-bar-transition: width .6s ease !default;\n\n// List group\n\n$list-group-bg: $white !default;\n$list-group-border-color: rgba($black, .125) !default;\n$list-group-border-width: $border-width !default;\n$list-group-border-radius: $border-radius !default;\n\n$list-group-item-padding-y: .75rem !default;\n$list-group-item-padding-x: 1.25rem !default;\n\n$list-group-hover-bg: $gray-100 !default;\n$list-group-active-color: $component-active-color !default;\n$list-group-active-bg: $component-active-bg !default;\n$list-group-active-border-color: $list-group-active-bg !default;\n\n$list-group-disabled-color: $gray-600 !default;\n$list-group-disabled-bg: $list-group-bg !default;\n\n$list-group-action-color: $gray-700 !default;\n$list-group-action-hover-color: $list-group-action-color !default;\n\n$list-group-action-active-color: $body-color !default;\n$list-group-action-active-bg: $gray-200 !default;\n\n\n// Image thumbnails\n\n$thumbnail-padding: .25rem !default;\n$thumbnail-bg: $body-bg !default;\n$thumbnail-border-width: $border-width !default;\n$thumbnail-border-color: $gray-300 !default;\n$thumbnail-border-radius: $border-radius !default;\n$thumbnail-box-shadow: 0 1px 2px rgba($black, .075) !default;\n\n\n// Figures\n\n$figure-caption-font-size: 90% !default;\n$figure-caption-color: $gray-600 !default;\n\n\n// Breadcrumbs\n\n$breadcrumb-padding-y: .75rem !default;\n$breadcrumb-padding-x: 1rem !default;\n$breadcrumb-item-padding: .5rem !default;\n\n$breadcrumb-margin-bottom: 1rem !default;\n\n$breadcrumb-bg: $gray-200 !default;\n$breadcrumb-divider-color: $gray-600 !default;\n$breadcrumb-active-color: $gray-600 !default;\n$breadcrumb-divider: quote(\"/\") !default;\n\n$breadcrumb-border-radius: $border-radius !default;\n\n\n// Carousel\n\n$carousel-control-color: $white !default;\n$carousel-control-width: 15% !default;\n$carousel-control-opacity: .5 !default;\n\n$carousel-indicator-width: 30px !default;\n$carousel-indicator-height: 3px !default;\n$carousel-indicator-spacer: 3px !default;\n$carousel-indicator-active-bg: $white !default;\n\n$carousel-caption-width: 70% !default;\n$carousel-caption-color: $white !default;\n\n$carousel-control-icon-width: 20px !default;\n\n$carousel-control-prev-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$carousel-control-next-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n\n$carousel-transition: transform .6s ease !default; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)\n\n\n// Close\n\n$close-font-size: $font-size-base * 1.5 !default;\n$close-font-weight: $font-weight-bold !default;\n$close-color: $black !default;\n$close-text-shadow: 0 1px 0 $white !default;\n\n// Code\n\n$code-font-size: 87.5% !default;\n$code-color: $pink !default;\n\n$kbd-padding-y: .2rem !default;\n$kbd-padding-x: .4rem !default;\n$kbd-font-size: $code-font-size !default;\n$kbd-color: $white !default;\n$kbd-bg: $gray-900 !default;\n\n$pre-color: $gray-900 !default;\n$pre-scrollable-max-height: 340px !default;\n\n\n// Printing\n$print-page-size: a3 !default;\n$print-body-min-width: map-get($grid-breakpoints, \"lg\") !default;\n","/*!\n * Bootstrap Reboot v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nhtml {\n font-family: sans-serif;\n line-height: 1.15;\n -webkit-text-size-adjust: 100%;\n -ms-text-size-adjust: 100%;\n -ms-overflow-style: scrollbar;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\n@-ms-viewport {\n width: device-width;\n}\n\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\nbody {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n text-align: left;\n background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\nhr {\n box-sizing: content-box;\n height: 0;\n overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n text-decoration: underline;\n text-decoration: underline dotted;\n cursor: help;\n border-bottom: 0;\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: 700;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0;\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\ndfn {\n font-style: italic;\n}\n\nb,\nstrong {\n font-weight: bolder;\n}\n\nsmall {\n font-size: 80%;\n}\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -.25em;\n}\n\nsup {\n top: -.5em;\n}\n\na {\n color: #007bff;\n text-decoration: none;\n background-color: transparent;\n -webkit-text-decoration-skip: objects;\n}\n\na:hover {\n color: #0056b3;\n text-decoration: underline;\n}\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):focus {\n outline: 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 1em;\n}\n\npre {\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n -ms-overflow-style: scrollbar;\n}\n\nfigure {\n margin: 0 0 1rem;\n}\n\nimg {\n vertical-align: middle;\n border-style: none;\n}\n\nsvg {\n overflow: hidden;\n vertical-align: middle;\n}\n\ntable {\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n color: #6c757d;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n text-align: inherit;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 0.5rem;\n}\n\nbutton {\n border-radius: 0;\n}\n\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible;\n}\n\nbutton,\nselect {\n text-transform: none;\n}\n\nbutton,\nhtml [type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box;\n padding: 0;\n}\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto;\n resize: vertical;\n}\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n max-width: 100%;\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit;\n white-space: normal;\n}\n\nprogress {\n vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n outline-offset: -2px;\n -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-cancel-button,\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button;\n}\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n}\n\ntemplate {\n display: none;\n}\n\n[hidden] {\n display: none !important;\n}\n\n/*# sourceMappingURL=bootstrap-reboot.css.map */","// Hover mixin and `$enable-hover-media-query` are deprecated.\n//\n// Originally added during our alphas and maintained during betas, this mixin was\n// designed to prevent `:hover` stickiness on iOS-an issue where hover styles\n// would persist after initial touch.\n//\n// For backward compatibility, we've kept these mixins and updated them to\n// always return their regular pseudo-classes instead of a shimmed media query.\n//\n// Issue: https://github.com/twbs/bootstrap/issues/25195\n\n@mixin hover {\n &:hover { @content; }\n}\n\n@mixin hover-focus {\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin plain-hover-focus {\n &,\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin hover-focus-active {\n &:hover,\n &:focus,\n &:active {\n @content;\n }\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../../scss/bootstrap-reboot.scss","bootstrap-reboot.css","../../scss/_reboot.scss","../../scss/_variables.scss","../../scss/vendor/_rfs.scss","../../scss/mixins/_hover.scss"],"names":[],"mappings":"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","file":"bootstrap-reboot.css","sourcesContent":["/*!\n * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n\n@import \"functions\";\n@import \"variables\";\n@import \"mixins\";\n@import \"reboot\";\n","/*!\n * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nhtml {\n font-family: sans-serif;\n line-height: 1.15;\n -webkit-text-size-adjust: 100%;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\nbody {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n text-align: left;\n background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\nhr {\n box-sizing: content-box;\n height: 0;\n overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n text-decoration: underline;\n text-decoration: underline dotted;\n cursor: help;\n border-bottom: 0;\n text-decoration-skip-ink: none;\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: 700;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0;\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: bolder;\n}\n\nsmall {\n font-size: 80%;\n}\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -.25em;\n}\n\nsup {\n top: -.5em;\n}\n\na {\n color: #007bff;\n text-decoration: none;\n background-color: transparent;\n}\n\na:hover {\n color: #0056b3;\n text-decoration: underline;\n}\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):focus {\n outline: 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 1em;\n}\n\npre {\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n}\n\nfigure {\n margin: 0 0 1rem;\n}\n\nimg {\n vertical-align: middle;\n border-style: none;\n}\n\nsvg {\n overflow: hidden;\n vertical-align: middle;\n}\n\ntable {\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n color: #6c757d;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n text-align: inherit;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 0.5rem;\n}\n\nbutton {\n border-radius: 0;\n}\n\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible;\n}\n\nbutton,\nselect {\n text-transform: none;\n}\n\nselect {\n word-wrap: normal;\n}\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\nbutton:not(:disabled),\n[type=\"button\"]:not(:disabled),\n[type=\"reset\"]:not(:disabled),\n[type=\"submit\"]:not(:disabled) {\n cursor: pointer;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box;\n padding: 0;\n}\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto;\n resize: vertical;\n}\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n max-width: 100%;\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit;\n white-space: normal;\n}\n\nprogress {\n vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n outline-offset: -2px;\n -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button;\n}\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n}\n\ntemplate {\n display: none;\n}\n\n[hidden] {\n display: none !important;\n}\n\n/*# sourceMappingURL=bootstrap-reboot.css.map */","// stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix\n\n// Reboot\n//\n// Normalization of HTML elements, manually forked from Normalize.css to remove\n// styles targeting irrelevant browsers while applying new styles.\n//\n// Normalize is licensed MIT. https://github.com/necolas/normalize.css\n\n\n// Document\n//\n// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.\n// 2. Change the default font family in all browsers.\n// 3. Correct the line height in all browsers.\n// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.\n// 5. Change the default tap highlight to be completely transparent in iOS.\n\n*,\n*::before,\n*::after {\n box-sizing: border-box; // 1\n}\n\nhtml {\n font-family: sans-serif; // 2\n line-height: 1.15; // 3\n -webkit-text-size-adjust: 100%; // 4\n -webkit-tap-highlight-color: rgba($black, 0); // 5\n}\n\n// Shim for \"new\" HTML5 structural elements to display correctly (IE10, older browsers)\n// TODO: remove in v5\n// stylelint-disable-next-line selector-list-comma-newline-after\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\n// Body\n//\n// 1. Remove the margin in all browsers.\n// 2. As a best practice, apply a default `background-color`.\n// 3. Set an explicit initial text-align value so that we can later use\n// the `inherit` value on things like `` elements.\n\nbody {\n margin: 0; // 1\n font-family: $font-family-base;\n @include font-size($font-size-base);\n font-weight: $font-weight-base;\n line-height: $line-height-base;\n color: $body-color;\n text-align: left; // 3\n background-color: $body-bg; // 2\n}\n\n// Suppress the focus outline on elements that cannot be accessed via keyboard.\n// This prevents an unwanted focus outline from appearing around elements that\n// might still respond to pointer events.\n//\n// Credit: https://github.com/suitcss/base\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\n\n// Content grouping\n//\n// 1. Add the correct box sizing in Firefox.\n// 2. Show the overflow in Edge and IE.\n\nhr {\n box-sizing: content-box; // 1\n height: 0; // 1\n overflow: visible; // 2\n}\n\n\n//\n// Typography\n//\n\n// Remove top margins from headings\n//\n// By default, `

    `-`

    ` all receive top and bottom margins. We nuke the top\n// margin for easier control within type scales as it avoids margin collapsing.\n// stylelint-disable-next-line selector-list-comma-newline-after\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: $headings-margin-bottom;\n}\n\n// Reset margins on paragraphs\n//\n// Similarly, the top margin on `

    `s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n// Abbreviations\n//\n// 1. Duplicate behavior to the data-* attribute for our tooltip plugin\n// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Remove the bottom border in Firefox 39-.\n// 5. Prevent the text-decoration to be skipped.\n\nabbr[title],\nabbr[data-original-title] { // 1\n text-decoration: underline; // 2\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n border-bottom: 0; // 4\n text-decoration-skip-ink: none; // 5\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // Undo browser default\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: $font-weight-bolder; // Add the correct font weight in Chrome, Edge, and Safari\n}\n\nsmall {\n @include font-size(80%); // Add the correct font size in all browsers\n}\n\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n//\n\nsub,\nsup {\n position: relative;\n @include font-size(75%);\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n//\n// Links\n//\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n background-color: transparent; // Remove the gray background on active links in IE 10.\n\n @include hover {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href)\n// which have not been made explicitly keyboard-focusable (without tabindex).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n\n @include hover-focus {\n color: inherit;\n text-decoration: none;\n }\n\n &:focus {\n outline: 0;\n }\n}\n\n\n//\n// Code\n//\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-monospace;\n @include font-size(1em); // Correct the odd `em` font sizing in all browsers.\n}\n\npre {\n // Remove browser default top margin\n margin-top: 0;\n // Reset browser default of `1em` to use `rem`s\n margin-bottom: 1rem;\n // Don't allow content to break outside\n overflow: auto;\n}\n\n\n//\n// Figures\n//\n\nfigure {\n // Apply a consistent margin strategy (matches our type styles).\n margin: 0 0 1rem;\n}\n\n\n//\n// Images and content\n//\n\nimg {\n vertical-align: middle;\n border-style: none; // Remove the border on images inside links in IE 10-.\n}\n\nsvg {\n // Workaround for the SVG overflow bug in IE10/11 is still required.\n // See https://github.com/twbs/bootstrap/issues/26878\n overflow: hidden;\n vertical-align: middle;\n}\n\n\n//\n// Tables\n//\n\ntable {\n border-collapse: collapse; // Prevent double borders\n}\n\ncaption {\n padding-top: $table-cell-padding;\n padding-bottom: $table-cell-padding;\n color: $table-caption-color;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n // Matches default `` alignment by inheriting from the ``, or the\n // closest parent with a set `text-align`.\n text-align: inherit;\n}\n\n\n//\n// Forms\n//\n\nlabel {\n // Allow labels to use `margin` for spacing.\n display: inline-block;\n margin-bottom: $label-margin-bottom;\n}\n\n// Remove the default `border-radius` that macOS Chrome adds.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24093\nbutton {\n // stylelint-disable-next-line property-blacklist\n border-radius: 0;\n}\n\n// Work around a Firefox/IE bug where the transparent `button` background\n// results in a loss of the default `button` focus styles.\n//\n// Credit: https://github.com/suitcss/base/\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0; // Remove the margin in Firefox and Safari\n font-family: inherit;\n @include font-size(inherit);\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible; // Show the overflow in Edge\n}\n\nbutton,\nselect {\n text-transform: none; // Remove the inheritance of text transform in Firefox\n}\n\n// Remove the inheritance of word-wrap in Safari.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24990\nselect {\n word-wrap: normal;\n}\n\n\n// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`\n// controls in Android 4.\n// 2. Correct the inability to style clickable types in iOS and Safari.\nbutton,\n[type=\"button\"], // 1\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button; // 2\n}\n\n// Opinionated: add \"hand\" cursor to non-disabled button elements.\n@if $enable-pointer-cursor-for-buttons {\n button,\n [type=\"button\"],\n [type=\"reset\"],\n [type=\"submit\"] {\n &:not(:disabled) {\n cursor: pointer;\n }\n }\n}\n\n// Remove inner border and padding from Firefox, but don't restore the outline like Normalize.\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box; // 1. Add the correct box sizing in IE 10-\n padding: 0; // 2. Remove the padding in IE 10-\n}\n\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n // Remove the default appearance of temporal inputs to avoid a Mobile Safari\n // bug where setting a custom line-height prevents text from being vertically\n // centered within the input.\n // See https://bugs.webkit.org/show_bug.cgi?id=139848\n // and https://github.com/twbs/bootstrap/issues/11266\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto; // Remove the default vertical scrollbar in IE.\n // Textareas should really only resize vertically so they don't break their (horizontal) containers.\n resize: vertical;\n}\n\nfieldset {\n // Browsers set a default `min-width: min-content;` on fieldsets,\n // unlike e.g. `

    `s, which have `min-width: 0;` by default.\n // So we reset that to ensure fieldsets behave more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359\n // and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements\n min-width: 0;\n // Reset the default outline behavior of fieldsets so they don't affect page layout.\n padding: 0;\n margin: 0;\n border: 0;\n}\n\n// 1. Correct the text wrapping in Edge and IE.\n// 2. Correct the color inheritance from `fieldset` elements in IE.\nlegend {\n display: block;\n width: 100%;\n max-width: 100%; // 1\n padding: 0;\n margin-bottom: .5rem;\n @include font-size(1.5rem);\n line-height: inherit;\n color: inherit; // 2\n white-space: normal; // 1\n}\n\nprogress {\n vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera.\n}\n\n// Correct the cursor style of increment and decrement buttons in Chrome.\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n // This overrides the extra rounded corners on search inputs in iOS so that our\n // `.form-control` class can properly style them. Note that this cannot simply\n // be added to `.form-control` as it's not specific enough. For details, see\n // https://github.com/twbs/bootstrap/issues/11586.\n outline-offset: -2px; // 2. Correct the outline style in Safari.\n -webkit-appearance: none;\n}\n\n//\n// Remove the inner padding in Chrome and Safari on macOS.\n//\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// 1. Correct the inability to style clickable types in iOS and Safari.\n// 2. Change font properties to `inherit` in Safari.\n//\n\n::-webkit-file-upload-button {\n font: inherit; // 2\n -webkit-appearance: button; // 1\n}\n\n//\n// Correct element displays\n//\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item; // Add the correct display in all browsers\n cursor: pointer;\n}\n\ntemplate {\n display: none; // Add the correct display in IE\n}\n\n// Always hide an element with the `hidden` HTML attribute (from PureCSS).\n// Needed for proper display in IE 10-.\n[hidden] {\n display: none !important;\n}\n","// Variables\n//\n// Variables should follow the `$component-state-property-size` formula for\n// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs.\n\n// Color system\n\n$white: #fff !default;\n$gray-100: #f8f9fa !default;\n$gray-200: #e9ecef !default;\n$gray-300: #dee2e6 !default;\n$gray-400: #ced4da !default;\n$gray-500: #adb5bd !default;\n$gray-600: #6c757d !default;\n$gray-700: #495057 !default;\n$gray-800: #343a40 !default;\n$gray-900: #212529 !default;\n$black: #000 !default;\n\n$grays: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$grays: map-merge(\n (\n \"100\": $gray-100,\n \"200\": $gray-200,\n \"300\": $gray-300,\n \"400\": $gray-400,\n \"500\": $gray-500,\n \"600\": $gray-600,\n \"700\": $gray-700,\n \"800\": $gray-800,\n \"900\": $gray-900\n ),\n $grays\n);\n\n$blue: #007bff !default;\n$indigo: #6610f2 !default;\n$purple: #6f42c1 !default;\n$pink: #e83e8c !default;\n$red: #dc3545 !default;\n$orange: #fd7e14 !default;\n$yellow: #ffc107 !default;\n$green: #28a745 !default;\n$teal: #20c997 !default;\n$cyan: #17a2b8 !default;\n\n$colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$colors: map-merge(\n (\n \"blue\": $blue,\n \"indigo\": $indigo,\n \"purple\": $purple,\n \"pink\": $pink,\n \"red\": $red,\n \"orange\": $orange,\n \"yellow\": $yellow,\n \"green\": $green,\n \"teal\": $teal,\n \"cyan\": $cyan,\n \"white\": $white,\n \"gray\": $gray-600,\n \"gray-dark\": $gray-800\n ),\n $colors\n);\n\n$primary: $blue !default;\n$secondary: $gray-600 !default;\n$success: $green !default;\n$info: $cyan !default;\n$warning: $yellow !default;\n$danger: $red !default;\n$light: $gray-100 !default;\n$dark: $gray-800 !default;\n\n$theme-colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$theme-colors: map-merge(\n (\n \"primary\": $primary,\n \"secondary\": $secondary,\n \"success\": $success,\n \"info\": $info,\n \"warning\": $warning,\n \"danger\": $danger,\n \"light\": $light,\n \"dark\": $dark\n ),\n $theme-colors\n);\n\n// Set a specific jump point for requesting color jumps\n$theme-color-interval: 8% !default;\n\n// The yiq lightness value that determines when the lightness of color changes from \"dark\" to \"light\". Acceptable values are between 0 and 255.\n$yiq-contrasted-threshold: 150 !default;\n\n// Customize the light and dark text colors for use in our YIQ color contrast function.\n$yiq-text-dark: $gray-900 !default;\n$yiq-text-light: $white !default;\n\n\n// Options\n//\n// Quickly modify global styling by enabling or disabling optional features.\n\n$enable-caret: true !default;\n$enable-rounded: true !default;\n$enable-shadows: false !default;\n$enable-gradients: false !default;\n$enable-transitions: true !default;\n$enable-prefers-reduced-motion-media-query: true !default;\n$enable-hover-media-query: false !default; // Deprecated, no longer affects any compiled CSS\n$enable-grid-classes: true !default;\n$enable-pointer-cursor-for-buttons: true !default;\n$enable-print-styles: true !default;\n$enable-responsive-font-sizes: false !default;\n$enable-validation-icons: true !default;\n$enable-deprecation-messages: true !default;\n\n\n// Spacing\n//\n// Control the default styling of most Bootstrap elements by modifying these\n// variables. Mostly focused on spacing.\n// You can add more entries to the $spacers map, should you need more variation.\n\n$spacer: 1rem !default;\n$spacers: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$spacers: map-merge(\n (\n 0: 0,\n 1: ($spacer * .25),\n 2: ($spacer * .5),\n 3: $spacer,\n 4: ($spacer * 1.5),\n 5: ($spacer * 3)\n ),\n $spacers\n);\n\n// This variable affects the `.h-*` and `.w-*` classes.\n$sizes: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$sizes: map-merge(\n (\n 25: 25%,\n 50: 50%,\n 75: 75%,\n 100: 100%,\n auto: auto\n ),\n $sizes\n);\n\n\n// Body\n//\n// Settings for the `` element.\n\n$body-bg: $white !default;\n$body-color: $gray-900 !default;\n\n\n// Links\n//\n// Style anchor elements.\n\n$link-color: theme-color(\"primary\") !default;\n$link-decoration: none !default;\n$link-hover-color: darken($link-color, 15%) !default;\n$link-hover-decoration: underline !default;\n// Darken percentage for links with `.text-*` class (e.g. `.text-success`)\n$emphasized-link-hover-darken-percentage: 15% !default;\n\n// Paragraphs\n//\n// Style p element.\n\n$paragraph-margin-bottom: 1rem !default;\n\n\n// Grid breakpoints\n//\n// Define the minimum dimensions at which your layout will change,\n// adapting to different screen sizes, for use in media queries.\n\n$grid-breakpoints: (\n xs: 0,\n sm: 576px,\n md: 768px,\n lg: 992px,\n xl: 1200px\n) !default;\n\n@include _assert-ascending($grid-breakpoints, \"$grid-breakpoints\");\n@include _assert-starts-at-zero($grid-breakpoints, \"$grid-breakpoints\");\n\n\n// Grid containers\n//\n// Define the maximum width of `.container` for different screen sizes.\n\n$container-max-widths: (\n sm: 540px,\n md: 720px,\n lg: 960px,\n xl: 1140px\n) !default;\n\n@include _assert-ascending($container-max-widths, \"$container-max-widths\");\n\n\n// Grid columns\n//\n// Set the number of columns and specify the width of the gutters.\n\n$grid-columns: 12 !default;\n$grid-gutter-width: 30px !default;\n\n\n// Components\n//\n// Define common padding and border radius sizes and more.\n\n$line-height-lg: 1.5 !default;\n$line-height-sm: 1.5 !default;\n\n$border-width: 1px !default;\n$border-color: $gray-300 !default;\n\n$border-radius: .25rem !default;\n$border-radius-lg: .3rem !default;\n$border-radius-sm: .2rem !default;\n\n$rounded-pill: 50rem !default;\n\n$box-shadow-sm: 0 .125rem .25rem rgba($black, .075) !default;\n$box-shadow: 0 .5rem 1rem rgba($black, .15) !default;\n$box-shadow-lg: 0 1rem 3rem rgba($black, .175) !default;\n\n$component-active-color: $white !default;\n$component-active-bg: theme-color(\"primary\") !default;\n\n$caret-width: .3em !default;\n$caret-vertical-align: $caret-width * .85 !default;\n$caret-spacing: $caret-width * .85 !default;\n\n$transition-base: all .2s ease-in-out !default;\n$transition-fade: opacity .15s linear !default;\n$transition-collapse: height .35s ease !default;\n\n$embed-responsive-aspect-ratios: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$embed-responsive-aspect-ratios: join(\n (\n (21 9),\n (16 9),\n (4 3),\n (1 1),\n ),\n $embed-responsive-aspect-ratios\n);\n\n// Typography\n//\n// Font, line-height, and color for body text, headings, and more.\n\n// stylelint-disable value-keyword-case\n$font-family-sans-serif: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\" !default;\n$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace !default;\n$font-family-base: $font-family-sans-serif !default;\n// stylelint-enable value-keyword-case\n\n$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`\n$font-size-lg: $font-size-base * 1.25 !default;\n$font-size-sm: $font-size-base * .875 !default;\n\n$font-weight-lighter: lighter !default;\n$font-weight-light: 300 !default;\n$font-weight-normal: 400 !default;\n$font-weight-bold: 700 !default;\n$font-weight-bolder: bolder !default;\n\n$font-weight-base: $font-weight-normal !default;\n$line-height-base: 1.5 !default;\n\n$h1-font-size: $font-size-base * 2.5 !default;\n$h2-font-size: $font-size-base * 2 !default;\n$h3-font-size: $font-size-base * 1.75 !default;\n$h4-font-size: $font-size-base * 1.5 !default;\n$h5-font-size: $font-size-base * 1.25 !default;\n$h6-font-size: $font-size-base !default;\n\n$headings-margin-bottom: $spacer / 2 !default;\n$headings-font-family: null !default;\n$headings-font-weight: 500 !default;\n$headings-line-height: 1.2 !default;\n$headings-color: null !default;\n\n$display1-size: 6rem !default;\n$display2-size: 5.5rem !default;\n$display3-size: 4.5rem !default;\n$display4-size: 3.5rem !default;\n\n$display1-weight: 300 !default;\n$display2-weight: 300 !default;\n$display3-weight: 300 !default;\n$display4-weight: 300 !default;\n$display-line-height: $headings-line-height !default;\n\n$lead-font-size: $font-size-base * 1.25 !default;\n$lead-font-weight: 300 !default;\n\n$small-font-size: 80% !default;\n\n$text-muted: $gray-600 !default;\n\n$blockquote-small-color: $gray-600 !default;\n$blockquote-small-font-size: $small-font-size !default;\n$blockquote-font-size: $font-size-base * 1.25 !default;\n\n$hr-border-color: rgba($black, .1) !default;\n$hr-border-width: $border-width !default;\n\n$mark-padding: .2em !default;\n\n$dt-font-weight: $font-weight-bold !default;\n\n$kbd-box-shadow: inset 0 -.1rem 0 rgba($black, .25) !default;\n$nested-kbd-font-weight: $font-weight-bold !default;\n\n$list-inline-padding: .5rem !default;\n\n$mark-bg: #fcf8e3 !default;\n\n$hr-margin-y: $spacer !default;\n\n\n// Tables\n//\n// Customizes the `.table` component with basic values, each used across all table variations.\n\n$table-cell-padding: .75rem !default;\n$table-cell-padding-sm: .3rem !default;\n\n$table-color: $body-color !default;\n$table-bg: null !default;\n$table-accent-bg: rgba($black, .05) !default;\n$table-hover-color: $table-color !default;\n$table-hover-bg: rgba($black, .075) !default;\n$table-active-bg: $table-hover-bg !default;\n\n$table-border-width: $border-width !default;\n$table-border-color: $border-color !default;\n\n$table-head-bg: $gray-200 !default;\n$table-head-color: $gray-700 !default;\n\n$table-dark-color: $white !default;\n$table-dark-bg: $gray-800 !default;\n$table-dark-accent-bg: rgba($white, .05) !default;\n$table-dark-hover-color: $table-dark-color !default;\n$table-dark-hover-bg: rgba($white, .075) !default;\n$table-dark-border-color: lighten($table-dark-bg, 7.5%) !default;\n$table-dark-color: $white !default;\n\n$table-striped-order: odd !default;\n\n$table-caption-color: $text-muted !default;\n\n$table-bg-level: -9 !default;\n$table-border-level: -6 !default;\n\n\n// Buttons + Forms\n//\n// Shared variables that are reassigned to `$input-` and `$btn-` specific variables.\n\n$input-btn-padding-y: .375rem !default;\n$input-btn-padding-x: .75rem !default;\n$input-btn-font-family: null !default;\n$input-btn-font-size: $font-size-base !default;\n$input-btn-line-height: $line-height-base !default;\n\n$input-btn-focus-width: .2rem !default;\n$input-btn-focus-color: rgba($component-active-bg, .25) !default;\n$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default;\n\n$input-btn-padding-y-sm: .25rem !default;\n$input-btn-padding-x-sm: .5rem !default;\n$input-btn-font-size-sm: $font-size-sm !default;\n$input-btn-line-height-sm: $line-height-sm !default;\n\n$input-btn-padding-y-lg: .5rem !default;\n$input-btn-padding-x-lg: 1rem !default;\n$input-btn-font-size-lg: $font-size-lg !default;\n$input-btn-line-height-lg: $line-height-lg !default;\n\n$input-btn-border-width: $border-width !default;\n\n\n// Buttons\n//\n// For each of Bootstrap's buttons, define text, background, and border color.\n\n$btn-padding-y: $input-btn-padding-y !default;\n$btn-padding-x: $input-btn-padding-x !default;\n$btn-font-family: $input-btn-font-family !default;\n$btn-font-size: $input-btn-font-size !default;\n$btn-line-height: $input-btn-line-height !default;\n\n$btn-padding-y-sm: $input-btn-padding-y-sm !default;\n$btn-padding-x-sm: $input-btn-padding-x-sm !default;\n$btn-font-size-sm: $input-btn-font-size-sm !default;\n$btn-line-height-sm: $input-btn-line-height-sm !default;\n\n$btn-padding-y-lg: $input-btn-padding-y-lg !default;\n$btn-padding-x-lg: $input-btn-padding-x-lg !default;\n$btn-font-size-lg: $input-btn-font-size-lg !default;\n$btn-line-height-lg: $input-btn-line-height-lg !default;\n\n$btn-border-width: $input-btn-border-width !default;\n\n$btn-font-weight: $font-weight-normal !default;\n$btn-box-shadow: inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default;\n$btn-focus-width: $input-btn-focus-width !default;\n$btn-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$btn-disabled-opacity: .65 !default;\n$btn-active-box-shadow: inset 0 3px 5px rgba($black, .125) !default;\n\n$btn-link-disabled-color: $gray-600 !default;\n\n$btn-block-spacing-y: .5rem !default;\n\n// Allows for customizing button radius independently from global border radius\n$btn-border-radius: $border-radius !default;\n$btn-border-radius-lg: $border-radius-lg !default;\n$btn-border-radius-sm: $border-radius-sm !default;\n\n$btn-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n\n// Forms\n\n$label-margin-bottom: .5rem !default;\n\n$input-padding-y: $input-btn-padding-y !default;\n$input-padding-x: $input-btn-padding-x !default;\n$input-font-family: $input-btn-font-family !default;\n$input-font-size: $input-btn-font-size !default;\n$input-font-weight: $font-weight-base !default;\n$input-line-height: $input-btn-line-height !default;\n\n$input-padding-y-sm: $input-btn-padding-y-sm !default;\n$input-padding-x-sm: $input-btn-padding-x-sm !default;\n$input-font-size-sm: $input-btn-font-size-sm !default;\n$input-line-height-sm: $input-btn-line-height-sm !default;\n\n$input-padding-y-lg: $input-btn-padding-y-lg !default;\n$input-padding-x-lg: $input-btn-padding-x-lg !default;\n$input-font-size-lg: $input-btn-font-size-lg !default;\n$input-line-height-lg: $input-btn-line-height-lg !default;\n\n$input-bg: $white !default;\n$input-disabled-bg: $gray-200 !default;\n\n$input-color: $gray-700 !default;\n$input-border-color: $gray-400 !default;\n$input-border-width: $input-btn-border-width !default;\n$input-box-shadow: inset 0 1px 1px rgba($black, .075) !default;\n\n$input-border-radius: $border-radius !default;\n$input-border-radius-lg: $border-radius-lg !default;\n$input-border-radius-sm: $border-radius-sm !default;\n\n$input-focus-bg: $input-bg !default;\n$input-focus-border-color: lighten($component-active-bg, 25%) !default;\n$input-focus-color: $input-color !default;\n$input-focus-width: $input-btn-focus-width !default;\n$input-focus-box-shadow: $input-btn-focus-box-shadow !default;\n\n$input-placeholder-color: $gray-600 !default;\n$input-plaintext-color: $body-color !default;\n\n$input-height-border: $input-border-width * 2 !default;\n\n$input-height-inner: calc(#{$input-line-height * 1em} + #{$input-padding-y * 2}) !default;\n$input-height-inner-half: calc(#{$input-line-height * .5em} + #{$input-padding-y}) !default;\n$input-height-inner-quarter: calc(#{$input-line-height * .25em} + #{$input-padding-y / 2}) !default;\n\n$input-height: calc(#{$input-line-height * 1em} + #{$input-padding-y * 2} + #{$input-height-border}) !default;\n$input-height-sm: calc(#{$input-line-height-sm * 1em} + #{$input-btn-padding-y-sm * 2} + #{$input-height-border}) !default;\n$input-height-lg: calc(#{$input-line-height-lg * 1em} + #{$input-btn-padding-y-lg * 2} + #{$input-height-border}) !default;\n\n$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$form-text-margin-top: .25rem !default;\n\n$form-check-input-gutter: 1.25rem !default;\n$form-check-input-margin-y: .3rem !default;\n$form-check-input-margin-x: .25rem !default;\n\n$form-check-inline-margin-x: .75rem !default;\n$form-check-inline-input-margin-x: .3125rem !default;\n\n$form-grid-gutter-width: 10px !default;\n$form-group-margin-bottom: 1rem !default;\n\n$input-group-addon-color: $input-color !default;\n$input-group-addon-bg: $gray-200 !default;\n$input-group-addon-border-color: $input-border-color !default;\n\n$custom-forms-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$custom-control-gutter: .5rem !default;\n$custom-control-spacer-x: 1rem !default;\n\n$custom-control-indicator-size: 1rem !default;\n$custom-control-indicator-bg: $input-bg !default;\n\n$custom-control-indicator-bg-size: 50% 50% !default;\n$custom-control-indicator-box-shadow: $input-box-shadow !default;\n$custom-control-indicator-border-color: $gray-500 !default;\n$custom-control-indicator-border-width: $input-border-width !default;\n\n$custom-control-indicator-disabled-bg: $input-disabled-bg !default;\n$custom-control-label-disabled-color: $gray-600 !default;\n\n$custom-control-indicator-checked-color: $component-active-color !default;\n$custom-control-indicator-checked-bg: $component-active-bg !default;\n$custom-control-indicator-checked-disabled-bg: rgba(theme-color(\"primary\"), .5) !default;\n$custom-control-indicator-checked-box-shadow: none !default;\n$custom-control-indicator-checked-border-color: $custom-control-indicator-checked-bg !default;\n\n$custom-control-indicator-focus-box-shadow: $input-focus-box-shadow !default;\n$custom-control-indicator-focus-border-color: $input-focus-border-color !default;\n\n$custom-control-indicator-active-color: $component-active-color !default;\n$custom-control-indicator-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-control-indicator-active-box-shadow: none !default;\n$custom-control-indicator-active-border-color: $custom-control-indicator-active-bg !default;\n\n$custom-checkbox-indicator-border-radius: $border-radius !default;\n$custom-checkbox-indicator-icon-checked: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n\n$custom-checkbox-indicator-indeterminate-bg: $component-active-bg !default;\n$custom-checkbox-indicator-indeterminate-color: $custom-control-indicator-checked-color !default;\n$custom-checkbox-indicator-icon-indeterminate: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3e%3cpath stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$custom-checkbox-indicator-indeterminate-box-shadow: none !default;\n$custom-checkbox-indicator-indeterminate-border-color: $custom-checkbox-indicator-indeterminate-bg !default;\n\n$custom-radio-indicator-border-radius: 50% !default;\n$custom-radio-indicator-icon-checked: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='#{$custom-control-indicator-checked-color}'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n\n$custom-switch-width: $custom-control-indicator-size * 1.75 !default;\n$custom-switch-indicator-border-radius: $custom-control-indicator-size / 2 !default;\n$custom-switch-indicator-size: calc(#{$custom-control-indicator-size} - #{$custom-control-indicator-border-width * 4}) !default;\n\n$custom-select-padding-y: $input-padding-y !default;\n$custom-select-padding-x: $input-padding-x !default;\n$custom-select-font-family: $input-font-family !default;\n$custom-select-font-size: $input-font-size !default;\n$custom-select-height: $input-height !default;\n$custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator\n$custom-select-font-weight: $input-font-weight !default;\n$custom-select-line-height: $input-line-height !default;\n$custom-select-color: $input-color !default;\n$custom-select-disabled-color: $gray-600 !default;\n$custom-select-bg: $input-bg !default;\n$custom-select-disabled-bg: $gray-200 !default;\n$custom-select-bg-size: 8px 10px !default; // In pixels because image dimensions\n$custom-select-indicator-color: $gray-800 !default;\n$custom-select-indicator: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$custom-select-background: $custom-select-indicator no-repeat right $custom-select-padding-x center / $custom-select-bg-size !default; // Used so we can have multiple background elements (e.g., arrow and feedback icon)\n\n$custom-select-feedback-icon-padding-right: calc((1em + #{2 * $custom-select-padding-y}) * 3 / 4 + #{$custom-select-padding-x + $custom-select-indicator-padding}) !default;\n$custom-select-feedback-icon-position: center right ($custom-select-padding-x + $custom-select-indicator-padding) !default;\n$custom-select-feedback-icon-size: $input-height-inner-half $input-height-inner-half !default;\n\n$custom-select-border-width: $input-border-width !default;\n$custom-select-border-color: $input-border-color !default;\n$custom-select-border-radius: $border-radius !default;\n$custom-select-box-shadow: inset 0 1px 2px rgba($black, .075) !default;\n\n$custom-select-focus-border-color: $input-focus-border-color !default;\n$custom-select-focus-width: $input-focus-width !default;\n$custom-select-focus-box-shadow: 0 0 0 $custom-select-focus-width $input-btn-focus-color !default;\n\n$custom-select-padding-y-sm: $input-padding-y-sm !default;\n$custom-select-padding-x-sm: $input-padding-x-sm !default;\n$custom-select-font-size-sm: $input-font-size-sm !default;\n$custom-select-height-sm: $input-height-sm !default;\n\n$custom-select-padding-y-lg: $input-padding-y-lg !default;\n$custom-select-padding-x-lg: $input-padding-x-lg !default;\n$custom-select-font-size-lg: $input-font-size-lg !default;\n$custom-select-height-lg: $input-height-lg !default;\n\n$custom-range-track-width: 100% !default;\n$custom-range-track-height: .5rem !default;\n$custom-range-track-cursor: pointer !default;\n$custom-range-track-bg: $gray-300 !default;\n$custom-range-track-border-radius: 1rem !default;\n$custom-range-track-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;\n\n$custom-range-thumb-width: 1rem !default;\n$custom-range-thumb-height: $custom-range-thumb-width !default;\n$custom-range-thumb-bg: $component-active-bg !default;\n$custom-range-thumb-border: 0 !default;\n$custom-range-thumb-border-radius: 1rem !default;\n$custom-range-thumb-box-shadow: 0 .1rem .25rem rgba($black, .1) !default;\n$custom-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-focus-box-shadow !default;\n$custom-range-thumb-focus-box-shadow-width: $input-focus-width !default; // For focus box shadow issue in IE/Edge\n$custom-range-thumb-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-range-thumb-disabled-bg: $gray-500 !default;\n\n$custom-file-height: $input-height !default;\n$custom-file-height-inner: $input-height-inner !default;\n$custom-file-focus-border-color: $input-focus-border-color !default;\n$custom-file-focus-box-shadow: $input-focus-box-shadow !default;\n$custom-file-disabled-bg: $input-disabled-bg !default;\n\n$custom-file-padding-y: $input-padding-y !default;\n$custom-file-padding-x: $input-padding-x !default;\n$custom-file-line-height: $input-line-height !default;\n$custom-file-font-family: $input-font-family !default;\n$custom-file-font-weight: $input-font-weight !default;\n$custom-file-color: $input-color !default;\n$custom-file-bg: $input-bg !default;\n$custom-file-border-width: $input-border-width !default;\n$custom-file-border-color: $input-border-color !default;\n$custom-file-border-radius: $input-border-radius !default;\n$custom-file-box-shadow: $input-box-shadow !default;\n$custom-file-button-color: $custom-file-color !default;\n$custom-file-button-bg: $input-group-addon-bg !default;\n$custom-file-text: (\n en: \"Browse\"\n) !default;\n\n\n// Form validation\n\n$form-feedback-margin-top: $form-text-margin-top !default;\n$form-feedback-font-size: $small-font-size !default;\n$form-feedback-valid-color: theme-color(\"success\") !default;\n$form-feedback-invalid-color: theme-color(\"danger\") !default;\n\n$form-feedback-icon-valid-color: $form-feedback-valid-color !default;\n$form-feedback-icon-valid: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='#{$form-feedback-icon-valid-color}' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$form-feedback-icon-invalid-color: $form-feedback-invalid-color !default;\n$form-feedback-icon-invalid: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$form-feedback-icon-invalid-color}' viewBox='-2 -2 7 7'%3e%3cpath stroke='#{$form-feedback-icon-invalid-color}' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E\"), \"#\", \"%23\") !default;\n\n$form-validation-states: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$form-validation-states: map-merge(\n (\n \"valid\": (\n \"color\": $form-feedback-valid-color,\n \"icon\": $form-feedback-icon-valid\n ),\n \"invalid\": (\n \"color\": $form-feedback-invalid-color,\n \"icon\": $form-feedback-icon-invalid\n ),\n ),\n $form-validation-states\n);\n\n// Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n\n$zindex-dropdown: 1000 !default;\n$zindex-sticky: 1020 !default;\n$zindex-fixed: 1030 !default;\n$zindex-modal-backdrop: 1040 !default;\n$zindex-modal: 1050 !default;\n$zindex-popover: 1060 !default;\n$zindex-tooltip: 1070 !default;\n\n\n// Navs\n\n$nav-link-padding-y: .5rem !default;\n$nav-link-padding-x: 1rem !default;\n$nav-link-disabled-color: $gray-600 !default;\n\n$nav-tabs-border-color: $gray-300 !default;\n$nav-tabs-border-width: $border-width !default;\n$nav-tabs-border-radius: $border-radius !default;\n$nav-tabs-link-hover-border-color: $gray-200 $gray-200 $nav-tabs-border-color !default;\n$nav-tabs-link-active-color: $gray-700 !default;\n$nav-tabs-link-active-bg: $body-bg !default;\n$nav-tabs-link-active-border-color: $gray-300 $gray-300 $nav-tabs-link-active-bg !default;\n\n$nav-pills-border-radius: $border-radius !default;\n$nav-pills-link-active-color: $component-active-color !default;\n$nav-pills-link-active-bg: $component-active-bg !default;\n\n$nav-divider-color: $gray-200 !default;\n$nav-divider-margin-y: $spacer / 2 !default;\n\n\n// Navbar\n\n$navbar-padding-y: $spacer / 2 !default;\n$navbar-padding-x: $spacer !default;\n\n$navbar-nav-link-padding-x: .5rem !default;\n\n$navbar-brand-font-size: $font-size-lg !default;\n// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link\n$nav-link-height: $font-size-base * $line-height-base + $nav-link-padding-y * 2 !default;\n$navbar-brand-height: $navbar-brand-font-size * $line-height-base !default;\n$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) / 2 !default;\n\n$navbar-toggler-padding-y: .25rem !default;\n$navbar-toggler-padding-x: .75rem !default;\n$navbar-toggler-font-size: $font-size-lg !default;\n$navbar-toggler-border-radius: $btn-border-radius !default;\n\n$navbar-dark-color: rgba($white, .5) !default;\n$navbar-dark-hover-color: rgba($white, .75) !default;\n$navbar-dark-active-color: $white !default;\n$navbar-dark-disabled-color: rgba($white, .25) !default;\n$navbar-dark-toggler-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$navbar-dark-toggler-border-color: rgba($white, .1) !default;\n\n$navbar-light-color: rgba($black, .5) !default;\n$navbar-light-hover-color: rgba($black, .7) !default;\n$navbar-light-active-color: rgba($black, .9) !default;\n$navbar-light-disabled-color: rgba($black, .3) !default;\n$navbar-light-toggler-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$navbar-light-toggler-border-color: rgba($black, .1) !default;\n\n$navbar-light-brand-color: $navbar-light-active-color !default;\n$navbar-light-brand-hover-color: $navbar-light-active-color !default;\n$navbar-dark-brand-color: $navbar-dark-active-color !default;\n$navbar-dark-brand-hover-color: $navbar-dark-active-color !default;\n\n\n// Dropdowns\n//\n// Dropdown menu container and contents.\n\n$dropdown-min-width: 10rem !default;\n$dropdown-padding-y: .5rem !default;\n$dropdown-spacer: .125rem !default;\n$dropdown-font-size: $font-size-base !default;\n$dropdown-color: $body-color !default;\n$dropdown-bg: $white !default;\n$dropdown-border-color: rgba($black, .15) !default;\n$dropdown-border-radius: $border-radius !default;\n$dropdown-border-width: $border-width !default;\n$dropdown-inner-border-radius: calc(#{$dropdown-border-radius} - #{$dropdown-border-width}) !default;\n$dropdown-divider-bg: $gray-200 !default;\n$dropdown-divider-margin-y: $nav-divider-margin-y !default;\n$dropdown-box-shadow: 0 .5rem 1rem rgba($black, .175) !default;\n\n$dropdown-link-color: $gray-900 !default;\n$dropdown-link-hover-color: darken($gray-900, 5%) !default;\n$dropdown-link-hover-bg: $gray-100 !default;\n\n$dropdown-link-active-color: $component-active-color !default;\n$dropdown-link-active-bg: $component-active-bg !default;\n\n$dropdown-link-disabled-color: $gray-600 !default;\n\n$dropdown-item-padding-y: .25rem !default;\n$dropdown-item-padding-x: 1.5rem !default;\n\n$dropdown-header-color: $gray-600 !default;\n\n\n// Pagination\n\n$pagination-padding-y: .5rem !default;\n$pagination-padding-x: .75rem !default;\n$pagination-padding-y-sm: .25rem !default;\n$pagination-padding-x-sm: .5rem !default;\n$pagination-padding-y-lg: .75rem !default;\n$pagination-padding-x-lg: 1.5rem !default;\n$pagination-line-height: 1.25 !default;\n\n$pagination-color: $link-color !default;\n$pagination-bg: $white !default;\n$pagination-border-width: $border-width !default;\n$pagination-border-color: $gray-300 !default;\n\n$pagination-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$pagination-focus-outline: 0 !default;\n\n$pagination-hover-color: $link-hover-color !default;\n$pagination-hover-bg: $gray-200 !default;\n$pagination-hover-border-color: $gray-300 !default;\n\n$pagination-active-color: $component-active-color !default;\n$pagination-active-bg: $component-active-bg !default;\n$pagination-active-border-color: $pagination-active-bg !default;\n\n$pagination-disabled-color: $gray-600 !default;\n$pagination-disabled-bg: $white !default;\n$pagination-disabled-border-color: $gray-300 !default;\n\n\n// Jumbotron\n\n$jumbotron-padding: 2rem !default;\n$jumbotron-color: null !default;\n$jumbotron-bg: $gray-200 !default;\n\n\n// Cards\n\n$card-spacer-y: .75rem !default;\n$card-spacer-x: 1.25rem !default;\n$card-border-width: $border-width !default;\n$card-border-radius: $border-radius !default;\n$card-border-color: rgba($black, .125) !default;\n$card-inner-border-radius: calc(#{$card-border-radius} - #{$card-border-width}) !default;\n$card-cap-bg: rgba($black, .03) !default;\n$card-cap-color: null !default;\n$card-color: null !default;\n$card-bg: $white !default;\n\n$card-img-overlay-padding: 1.25rem !default;\n\n$card-group-margin: $grid-gutter-width / 2 !default;\n$card-deck-margin: $card-group-margin !default;\n\n$card-columns-count: 3 !default;\n$card-columns-gap: 1.25rem !default;\n$card-columns-margin: $card-spacer-y !default;\n\n\n// Tooltips\n\n$tooltip-font-size: $font-size-sm !default;\n$tooltip-max-width: 200px !default;\n$tooltip-color: $white !default;\n$tooltip-bg: $black !default;\n$tooltip-border-radius: $border-radius !default;\n$tooltip-opacity: .9 !default;\n$tooltip-padding-y: .25rem !default;\n$tooltip-padding-x: .5rem !default;\n$tooltip-margin: 0 !default;\n\n$tooltip-arrow-width: .8rem !default;\n$tooltip-arrow-height: .4rem !default;\n$tooltip-arrow-color: $tooltip-bg !default;\n\n// Form tooltips must come after regular tooltips\n$form-feedback-tooltip-padding-y: $tooltip-padding-y !default;\n$form-feedback-tooltip-padding-x: $tooltip-padding-x !default;\n$form-feedback-tooltip-font-size: $tooltip-font-size !default;\n$form-feedback-tooltip-line-height: $line-height-base !default;\n$form-feedback-tooltip-opacity: $tooltip-opacity !default;\n$form-feedback-tooltip-border-radius: $tooltip-border-radius !default;\n\n\n// Popovers\n\n$popover-font-size: $font-size-sm !default;\n$popover-bg: $white !default;\n$popover-max-width: 276px !default;\n$popover-border-width: $border-width !default;\n$popover-border-color: rgba($black, .2) !default;\n$popover-border-radius: $border-radius-lg !default;\n$popover-box-shadow: 0 .25rem .5rem rgba($black, .2) !default;\n\n$popover-header-bg: darken($popover-bg, 3%) !default;\n$popover-header-color: $headings-color !default;\n$popover-header-padding-y: .5rem !default;\n$popover-header-padding-x: .75rem !default;\n\n$popover-body-color: $body-color !default;\n$popover-body-padding-y: $popover-header-padding-y !default;\n$popover-body-padding-x: $popover-header-padding-x !default;\n\n$popover-arrow-width: 1rem !default;\n$popover-arrow-height: .5rem !default;\n$popover-arrow-color: $popover-bg !default;\n\n$popover-arrow-outer-color: fade-in($popover-border-color, .05) !default;\n\n\n// Toasts\n\n$toast-max-width: 350px !default;\n$toast-padding-x: .75rem !default;\n$toast-padding-y: .25rem !default;\n$toast-font-size: .875rem !default;\n$toast-color: null !default;\n$toast-background-color: rgba($white, .85) !default;\n$toast-border-width: 1px !default;\n$toast-border-color: rgba(0, 0, 0, .1) !default;\n$toast-border-radius: .25rem !default;\n$toast-box-shadow: 0 .25rem .75rem rgba($black, .1) !default;\n\n$toast-header-color: $gray-600 !default;\n$toast-header-background-color: rgba($white, .85) !default;\n$toast-header-border-color: rgba(0, 0, 0, .05) !default;\n\n\n// Badges\n\n$badge-font-size: 75% !default;\n$badge-font-weight: $font-weight-bold !default;\n$badge-padding-y: .25em !default;\n$badge-padding-x: .4em !default;\n$badge-border-radius: $border-radius !default;\n\n$badge-transition: $btn-transition !default;\n$badge-focus-width: $input-btn-focus-width !default;\n\n$badge-pill-padding-x: .6em !default;\n// Use a higher than normal value to ensure completely rounded edges when\n// customizing padding or font-size on labels.\n$badge-pill-border-radius: 10rem !default;\n\n\n// Modals\n\n// Padding applied to the modal body\n$modal-inner-padding: 1rem !default;\n\n$modal-dialog-margin: .5rem !default;\n$modal-dialog-margin-y-sm-up: 1.75rem !default;\n\n$modal-title-line-height: $line-height-base !default;\n\n$modal-content-color: null !default;\n$modal-content-bg: $white !default;\n$modal-content-border-color: rgba($black, .2) !default;\n$modal-content-border-width: $border-width !default;\n$modal-content-border-radius: $border-radius-lg !default;\n$modal-content-box-shadow-xs: 0 .25rem .5rem rgba($black, .5) !default;\n$modal-content-box-shadow-sm-up: 0 .5rem 1rem rgba($black, .5) !default;\n\n$modal-backdrop-bg: $black !default;\n$modal-backdrop-opacity: .5 !default;\n$modal-header-border-color: $border-color !default;\n$modal-footer-border-color: $modal-header-border-color !default;\n$modal-header-border-width: $modal-content-border-width !default;\n$modal-footer-border-width: $modal-header-border-width !default;\n$modal-header-padding-y: 1rem !default;\n$modal-header-padding-x: 1rem !default;\n$modal-header-padding: $modal-header-padding-y $modal-header-padding-x !default; // Keep this for backwards compatibility\n\n$modal-xl: 1140px !default;\n$modal-lg: 800px !default;\n$modal-md: 500px !default;\n$modal-sm: 300px !default;\n\n$modal-fade-transform: translate(0, -50px) !default;\n$modal-show-transform: none !default;\n$modal-transition: transform .3s ease-out !default;\n\n\n// Alerts\n//\n// Define alert colors, border radius, and padding.\n\n$alert-padding-y: .75rem !default;\n$alert-padding-x: 1.25rem !default;\n$alert-margin-bottom: 1rem !default;\n$alert-border-radius: $border-radius !default;\n$alert-link-font-weight: $font-weight-bold !default;\n$alert-border-width: $border-width !default;\n\n$alert-bg-level: -10 !default;\n$alert-border-level: -9 !default;\n$alert-color-level: 6 !default;\n\n\n// Progress bars\n\n$progress-height: 1rem !default;\n$progress-font-size: $font-size-base * .75 !default;\n$progress-bg: $gray-200 !default;\n$progress-border-radius: $border-radius !default;\n$progress-box-shadow: inset 0 .1rem .1rem rgba($black, .1) !default;\n$progress-bar-color: $white !default;\n$progress-bar-bg: theme-color(\"primary\") !default;\n$progress-bar-animation-timing: 1s linear infinite !default;\n$progress-bar-transition: width .6s ease !default;\n\n\n// List group\n\n$list-group-color: null !default;\n$list-group-bg: $white !default;\n$list-group-border-color: rgba($black, .125) !default;\n$list-group-border-width: $border-width !default;\n$list-group-border-radius: $border-radius !default;\n\n$list-group-item-padding-y: .75rem !default;\n$list-group-item-padding-x: 1.25rem !default;\n\n$list-group-hover-bg: $gray-100 !default;\n$list-group-active-color: $component-active-color !default;\n$list-group-active-bg: $component-active-bg !default;\n$list-group-active-border-color: $list-group-active-bg !default;\n\n$list-group-disabled-color: $gray-600 !default;\n$list-group-disabled-bg: $list-group-bg !default;\n\n$list-group-action-color: $gray-700 !default;\n$list-group-action-hover-color: $list-group-action-color !default;\n\n$list-group-action-active-color: $body-color !default;\n$list-group-action-active-bg: $gray-200 !default;\n\n\n// Image thumbnails\n\n$thumbnail-padding: .25rem !default;\n$thumbnail-bg: $body-bg !default;\n$thumbnail-border-width: $border-width !default;\n$thumbnail-border-color: $gray-300 !default;\n$thumbnail-border-radius: $border-radius !default;\n$thumbnail-box-shadow: 0 1px 2px rgba($black, .075) !default;\n\n\n// Figures\n\n$figure-caption-font-size: 90% !default;\n$figure-caption-color: $gray-600 !default;\n\n\n// Breadcrumbs\n\n$breadcrumb-padding-y: .75rem !default;\n$breadcrumb-padding-x: 1rem !default;\n$breadcrumb-item-padding: .5rem !default;\n\n$breadcrumb-margin-bottom: 1rem !default;\n\n$breadcrumb-bg: $gray-200 !default;\n$breadcrumb-divider-color: $gray-600 !default;\n$breadcrumb-active-color: $gray-600 !default;\n$breadcrumb-divider: quote(\"/\") !default;\n\n$breadcrumb-border-radius: $border-radius !default;\n\n\n// Carousel\n\n$carousel-control-color: $white !default;\n$carousel-control-width: 15% !default;\n$carousel-control-opacity: .5 !default;\n$carousel-control-hover-opacity: .9 !default;\n$carousel-control-transition: opacity .15s ease !default;\n\n$carousel-indicator-width: 30px !default;\n$carousel-indicator-height: 3px !default;\n$carousel-indicator-hit-area-height: 10px !default;\n$carousel-indicator-spacer: 3px !default;\n$carousel-indicator-active-bg: $white !default;\n$carousel-indicator-transition: opacity .6s ease !default;\n\n$carousel-caption-width: 70% !default;\n$carousel-caption-color: $white !default;\n\n$carousel-control-icon-width: 20px !default;\n\n$carousel-control-prev-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n$carousel-control-next-icon-bg: str-replace(url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3e%3c/svg%3e\"), \"#\", \"%23\") !default;\n\n$carousel-transition-duration: .6s !default;\n$carousel-transition: transform $carousel-transition-duration ease-in-out !default; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)\n\n\n// Spinners\n\n$spinner-width: 2rem !default;\n$spinner-height: $spinner-width !default;\n$spinner-border-width: .25em !default;\n\n$spinner-width-sm: 1rem !default;\n$spinner-height-sm: $spinner-width-sm !default;\n$spinner-border-width-sm: .2em !default;\n\n\n// Close\n\n$close-font-size: $font-size-base * 1.5 !default;\n$close-font-weight: $font-weight-bold !default;\n$close-color: $black !default;\n$close-text-shadow: 0 1px 0 $white !default;\n\n\n// Code\n\n$code-font-size: 87.5% !default;\n$code-color: $pink !default;\n\n$kbd-padding-y: .2rem !default;\n$kbd-padding-x: .4rem !default;\n$kbd-font-size: $code-font-size !default;\n$kbd-color: $white !default;\n$kbd-bg: $gray-900 !default;\n\n$pre-color: $gray-900 !default;\n$pre-scrollable-max-height: 340px !default;\n\n\n// Utilities\n\n$displays: none, inline, inline-block, block, table, table-row, table-cell, flex, inline-flex !default;\n$overflows: auto, hidden !default;\n$positions: static, relative, absolute, fixed, sticky !default;\n\n\n// Printing\n\n$print-page-size: a3 !default;\n$print-body-min-width: map-get($grid-breakpoints, \"lg\") !default;\n","// stylelint-disable property-blacklist, scss/dollar-variable-default\n\n// SCSS RFS mixin\n//\n// Automated font-resizing\n//\n// See https://github.com/twbs/rfs\n\n// Configuration\n\n// Base font size\n$rfs-base-font-size: 1.25rem !default;\n$rfs-font-size-unit: rem !default;\n\n// Breakpoint at where font-size starts decreasing if screen width is smaller\n$rfs-breakpoint: 1200px !default;\n$rfs-breakpoint-unit: px !default;\n\n// Resize font-size based on screen height and width\n$rfs-two-dimensional: false !default;\n\n// Factor of decrease\n$rfs-factor: 10 !default;\n\n@if type-of($rfs-factor) != \"number\" or $rfs-factor <= 1 {\n @error \"`#{$rfs-factor}` is not a valid $rfs-factor, it must be greater than 1.\";\n}\n\n// Generate enable or disable classes. Possibilities: false, \"enable\" or \"disable\"\n$rfs-class: false !default;\n\n// 1 rem = $rfs-rem-value px\n$rfs-rem-value: 16 !default;\n\n// Safari iframe resize bug: https://github.com/twbs/rfs/issues/14\n$rfs-safari-iframe-resize-bug-fix: false !default;\n\n// Disable RFS by setting $enable-responsive-font-sizes to false\n$enable-responsive-font-sizes: true !default;\n\n// Cache $rfs-base-font-size unit\n$rfs-base-font-size-unit: unit($rfs-base-font-size);\n\n// Remove px-unit from $rfs-base-font-size for calculations\n@if $rfs-base-font-size-unit == \"px\" {\n $rfs-base-font-size: $rfs-base-font-size / ($rfs-base-font-size * 0 + 1);\n}\n@else if $rfs-base-font-size-unit == \"rem\" {\n $rfs-base-font-size: $rfs-base-font-size / ($rfs-base-font-size * 0 + 1 / $rfs-rem-value);\n}\n\n// Cache $rfs-breakpoint unit to prevent multiple calls\n$rfs-breakpoint-unit-cache: unit($rfs-breakpoint);\n\n// Remove unit from $rfs-breakpoint for calculations\n@if $rfs-breakpoint-unit-cache == \"px\" {\n $rfs-breakpoint: $rfs-breakpoint / ($rfs-breakpoint * 0 + 1);\n}\n@else if $rfs-breakpoint-unit-cache == \"rem\" or $rfs-breakpoint-unit-cache == \"em\" {\n $rfs-breakpoint: $rfs-breakpoint / ($rfs-breakpoint * 0 + 1 / $rfs-rem-value);\n}\n\n// Responsive font-size mixin\n@mixin rfs($fs, $important: false) {\n // Cache $fs unit\n $fs-unit: if(type-of($fs) == \"number\", unit($fs), false);\n\n // Add !important suffix if needed\n $rfs-suffix: if($important, \" !important\", \"\");\n\n // If $fs isn't a number (like inherit) or $fs has a unit (not px or rem, like 1.5em) or $ is 0, just print the value\n @if not $fs-unit or $fs-unit != \"\" and $fs-unit != \"px\" and $fs-unit != \"rem\" or $fs == 0 {\n font-size: #{$fs}#{$rfs-suffix};\n }\n @else {\n // Variables for storing static and fluid rescaling\n $rfs-static: null;\n $rfs-fluid: null;\n\n // Remove px-unit from $fs for calculations\n @if $fs-unit == \"px\" {\n $fs: $fs / ($fs * 0 + 1);\n }\n @else if $fs-unit == \"rem\" {\n $fs: $fs / ($fs * 0 + 1 / $rfs-rem-value);\n }\n\n // Set default font-size\n @if $rfs-font-size-unit == rem {\n $rfs-static: #{$fs / $rfs-rem-value}rem#{$rfs-suffix};\n }\n @else if $rfs-font-size-unit == px {\n $rfs-static: #{$fs}px#{$rfs-suffix};\n }\n @else {\n @error \"`#{$rfs-font-size-unit}` is not a valid unit for $rfs-font-size-unit. Use `px` or `rem`.\";\n }\n\n // Only add media query if font-size is bigger as the minimum font-size\n // If $rfs-factor == 1, no rescaling will take place\n @if $fs > $rfs-base-font-size and $enable-responsive-font-sizes {\n $min-width: null;\n $variable-unit: null;\n\n // Calculate minimum font-size for given font-size\n $fs-min: $rfs-base-font-size + ($fs - $rfs-base-font-size) / $rfs-factor;\n\n // Calculate difference between given font-size and minimum font-size for given font-size\n $fs-diff: $fs - $fs-min;\n\n // Base font-size formatting\n // No need to check if the unit is valid, because we did that before\n $min-width: if($rfs-font-size-unit == rem, #{$fs-min / $rfs-rem-value}rem, #{$fs-min}px);\n\n // If two-dimensional, use smallest of screen width and height\n $variable-unit: if($rfs-two-dimensional, vmin, vw);\n\n // Calculate the variable width between 0 and $rfs-breakpoint\n $variable-width: #{$fs-diff * 100 / $rfs-breakpoint}#{$variable-unit};\n\n // Set the calculated font-size.\n $rfs-fluid: calc(#{$min-width} + #{$variable-width}) #{$rfs-suffix};\n }\n\n // Rendering\n @if $rfs-fluid == null {\n // Only render static font-size if no fluid font-size is available\n font-size: $rfs-static;\n }\n @else {\n $mq-value: null;\n\n // RFS breakpoint formatting\n @if $rfs-breakpoint-unit == em or $rfs-breakpoint-unit == rem {\n $mq-value: #{$rfs-breakpoint / $rfs-rem-value}#{$rfs-breakpoint-unit};\n }\n @else if $rfs-breakpoint-unit == px {\n $mq-value: #{$rfs-breakpoint}px;\n }\n @else {\n @error \"`#{$rfs-breakpoint-unit}` is not a valid unit for $rfs-breakpoint-unit. Use `px`, `em` or `rem`.\";\n }\n\n @if $rfs-class == \"disable\" {\n // Adding an extra class increases specificity,\n // which prevents the media query to override the font size\n &,\n .disable-responsive-font-size &,\n &.disable-responsive-font-size {\n font-size: $rfs-static;\n }\n }\n @else {\n font-size: $rfs-static;\n }\n\n @if $rfs-two-dimensional {\n @media (max-width: #{$mq-value}), (max-height: #{$mq-value}) {\n @if $rfs-class == \"enable\" {\n .enable-responsive-font-size &,\n &.enable-responsive-font-size {\n font-size: $rfs-fluid;\n }\n }\n @else {\n font-size: $rfs-fluid;\n }\n\n @if $rfs-safari-iframe-resize-bug-fix {\n // stylelint-disable-next-line length-zero-no-unit\n min-width: 0vw;\n }\n }\n }\n @else {\n @media (max-width: #{$mq-value}) {\n @if $rfs-class == \"enable\" {\n .enable-responsive-font-size &,\n &.enable-responsive-font-size {\n font-size: $rfs-fluid;\n }\n }\n @else {\n font-size: $rfs-fluid;\n }\n\n @if $rfs-safari-iframe-resize-bug-fix {\n // stylelint-disable-next-line length-zero-no-unit\n min-width: 0vw;\n }\n }\n }\n }\n }\n}\n\n// The font-size & responsive-font-size mixin uses RFS to rescale font sizes\n@mixin font-size($fs, $important: false) {\n @include rfs($fs, $important);\n}\n\n@mixin responsive-font-size($fs, $important: false) {\n @include rfs($fs, $important);\n}\n","// Hover mixin and `$enable-hover-media-query` are deprecated.\n//\n// Originally added during our alphas and maintained during betas, this mixin was\n// designed to prevent `:hover` stickiness on iOS-an issue where hover styles\n// would persist after initial touch.\n//\n// For backward compatibility, we've kept these mixins and updated them to\n// always return their regular pseudo-classes instead of a shimmed media query.\n//\n// Issue: https://github.com/twbs/bootstrap/issues/25195\n\n@mixin hover {\n &:hover { @content; }\n}\n\n@mixin hover-focus {\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin plain-hover-focus {\n &,\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin hover-focus-active {\n &:hover,\n &:focus,\n &:active {\n @content;\n }\n}\n"]} \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css index 402715d5..c804b3b1 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css @@ -1,8 +1,8 @@ /*! - * Bootstrap Reboot v4.1.3 (https://getbootstrap.com/) - * Copyright 2011-2018 The Bootstrap Authors - * Copyright 2011-2018 Twitter, Inc. + * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/) + * Copyright 2011-2019 The Bootstrap Authors + * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) - */*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}@-ms-viewport{width:device-width}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important} + */*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important} /*# sourceMappingURL=bootstrap-reboot.min.css.map */ \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map index 2d7932cd..73f4a192 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map @@ -1 +1 @@ -{"version":3,"sources":["../../scss/bootstrap-reboot.scss","../../scss/_reboot.scss","dist/css/bootstrap-reboot.css","bootstrap-reboot.css","../../scss/mixins/_hover.scss"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Bootstrap Reboot v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n\n@import \"functions\";\n@import \"variables\";\n@import \"mixins\";\n@import \"reboot\";\n","// stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix\n\n// Reboot\n//\n// Normalization of HTML elements, manually forked from Normalize.css to remove\n// styles targeting irrelevant browsers while applying new styles.\n//\n// Normalize is licensed MIT. https://github.com/necolas/normalize.css\n\n\n// Document\n//\n// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.\n// 2. Change the default font family in all browsers.\n// 3. Correct the line height in all browsers.\n// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.\n// 5. Setting @viewport causes scrollbars to overlap content in IE11 and Edge, so\n// we force a non-overlapping, non-auto-hiding scrollbar to counteract.\n// 6. Change the default tap highlight to be completely transparent in iOS.\n\n*,\n*::before,\n*::after {\n box-sizing: border-box; // 1\n}\n\nhtml {\n font-family: sans-serif; // 2\n line-height: 1.15; // 3\n -webkit-text-size-adjust: 100%; // 4\n -ms-text-size-adjust: 100%; // 4\n -ms-overflow-style: scrollbar; // 5\n -webkit-tap-highlight-color: rgba($black, 0); // 6\n}\n\n// IE10+ doesn't honor `` in some cases.\n@at-root {\n @-ms-viewport {\n width: device-width;\n }\n}\n\n// stylelint-disable selector-list-comma-newline-after\n// Shim for \"new\" HTML5 structural elements to display correctly (IE10, older browsers)\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n// stylelint-enable selector-list-comma-newline-after\n\n// Body\n//\n// 1. Remove the margin in all browsers.\n// 2. As a best practice, apply a default `background-color`.\n// 3. Set an explicit initial text-align value so that we can later use the\n// the `inherit` value on things like `` elements.\n\nbody {\n margin: 0; // 1\n font-family: $font-family-base;\n font-size: $font-size-base;\n font-weight: $font-weight-base;\n line-height: $line-height-base;\n color: $body-color;\n text-align: left; // 3\n background-color: $body-bg; // 2\n}\n\n// Suppress the focus outline on elements that cannot be accessed via keyboard.\n// This prevents an unwanted focus outline from appearing around elements that\n// might still respond to pointer events.\n//\n// Credit: https://github.com/suitcss/base\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\n\n// Content grouping\n//\n// 1. Add the correct box sizing in Firefox.\n// 2. Show the overflow in Edge and IE.\n\nhr {\n box-sizing: content-box; // 1\n height: 0; // 1\n overflow: visible; // 2\n}\n\n\n//\n// Typography\n//\n\n// Remove top margins from headings\n//\n// By default, `

    `-`

    ` all receive top and bottom margins. We nuke the top\n// margin for easier control within type scales as it avoids margin collapsing.\n// stylelint-disable selector-list-comma-newline-after\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: $headings-margin-bottom;\n}\n// stylelint-enable selector-list-comma-newline-after\n\n// Reset margins on paragraphs\n//\n// Similarly, the top margin on `

    `s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n// Abbreviations\n//\n// 1. Remove the bottom border in Firefox 39-.\n// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Duplicate behavior to the data-* attribute for our tooltip plugin\n\nabbr[title],\nabbr[data-original-title] { // 4\n text-decoration: underline; // 2\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n border-bottom: 0; // 1\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // Undo browser default\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\ndfn {\n font-style: italic; // Add the correct font style in Android 4.3-\n}\n\n// stylelint-disable font-weight-notation\nb,\nstrong {\n font-weight: bolder; // Add the correct font weight in Chrome, Edge, and Safari\n}\n// stylelint-enable font-weight-notation\n\nsmall {\n font-size: 80%; // Add the correct font size in all browsers\n}\n\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n//\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n//\n// Links\n//\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n background-color: transparent; // Remove the gray background on active links in IE 10.\n -webkit-text-decoration-skip: objects; // Remove gaps in links underline in iOS 8+ and Safari 8+.\n\n @include hover {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href)\n// which have not been made explicitly keyboard-focusable (without tabindex).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n\n @include hover-focus {\n color: inherit;\n text-decoration: none;\n }\n\n &:focus {\n outline: 0;\n }\n}\n\n\n//\n// Code\n//\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-monospace;\n font-size: 1em; // Correct the odd `em` font sizing in all browsers.\n}\n\npre {\n // Remove browser default top margin\n margin-top: 0;\n // Reset browser default of `1em` to use `rem`s\n margin-bottom: 1rem;\n // Don't allow content to break outside\n overflow: auto;\n // We have @viewport set which causes scrollbars to overlap content in IE11 and Edge, so\n // we force a non-overlapping, non-auto-hiding scrollbar to counteract.\n -ms-overflow-style: scrollbar;\n}\n\n\n//\n// Figures\n//\n\nfigure {\n // Apply a consistent margin strategy (matches our type styles).\n margin: 0 0 1rem;\n}\n\n\n//\n// Images and content\n//\n\nimg {\n vertical-align: middle;\n border-style: none; // Remove the border on images inside links in IE 10-.\n}\n\nsvg {\n // Workaround for the SVG overflow bug in IE10/11 is still required.\n // See https://github.com/twbs/bootstrap/issues/26878\n overflow: hidden;\n vertical-align: middle;\n}\n\n\n//\n// Tables\n//\n\ntable {\n border-collapse: collapse; // Prevent double borders\n}\n\ncaption {\n padding-top: $table-cell-padding;\n padding-bottom: $table-cell-padding;\n color: $table-caption-color;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n // Matches default `` alignment by inheriting from the ``, or the\n // closest parent with a set `text-align`.\n text-align: inherit;\n}\n\n\n//\n// Forms\n//\n\nlabel {\n // Allow labels to use `margin` for spacing.\n display: inline-block;\n margin-bottom: $label-margin-bottom;\n}\n\n// Remove the default `border-radius` that macOS Chrome adds.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24093\nbutton {\n border-radius: 0;\n}\n\n// Work around a Firefox/IE bug where the transparent `button` background\n// results in a loss of the default `button` focus styles.\n//\n// Credit: https://github.com/suitcss/base/\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0; // Remove the margin in Firefox and Safari\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible; // Show the overflow in Edge\n}\n\nbutton,\nselect {\n text-transform: none; // Remove the inheritance of text transform in Firefox\n}\n\n// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`\n// controls in Android 4.\n// 2. Correct the inability to style clickable types in iOS and Safari.\nbutton,\nhtml [type=\"button\"], // 1\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button; // 2\n}\n\n// Remove inner border and padding from Firefox, but don't restore the outline like Normalize.\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box; // 1. Add the correct box sizing in IE 10-\n padding: 0; // 2. Remove the padding in IE 10-\n}\n\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n // Remove the default appearance of temporal inputs to avoid a Mobile Safari\n // bug where setting a custom line-height prevents text from being vertically\n // centered within the input.\n // See https://bugs.webkit.org/show_bug.cgi?id=139848\n // and https://github.com/twbs/bootstrap/issues/11266\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto; // Remove the default vertical scrollbar in IE.\n // Textareas should really only resize vertically so they don't break their (horizontal) containers.\n resize: vertical;\n}\n\nfieldset {\n // Browsers set a default `min-width: min-content;` on fieldsets,\n // unlike e.g. `

    `s, which have `min-width: 0;` by default.\n // So we reset that to ensure fieldsets behave more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359\n // and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements\n min-width: 0;\n // Reset the default outline behavior of fieldsets so they don't affect page layout.\n padding: 0;\n margin: 0;\n border: 0;\n}\n\n// 1. Correct the text wrapping in Edge and IE.\n// 2. Correct the color inheritance from `fieldset` elements in IE.\nlegend {\n display: block;\n width: 100%;\n max-width: 100%; // 1\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit; // 2\n white-space: normal; // 1\n}\n\nprogress {\n vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera.\n}\n\n// Correct the cursor style of increment and decrement buttons in Chrome.\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n // This overrides the extra rounded corners on search inputs in iOS so that our\n // `.form-control` class can properly style them. Note that this cannot simply\n // be added to `.form-control` as it's not specific enough. For details, see\n // https://github.com/twbs/bootstrap/issues/11586.\n outline-offset: -2px; // 2. Correct the outline style in Safari.\n -webkit-appearance: none;\n}\n\n//\n// Remove the inner padding and cancel buttons in Chrome and Safari on macOS.\n//\n\n[type=\"search\"]::-webkit-search-cancel-button,\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// 1. Correct the inability to style clickable types in iOS and Safari.\n// 2. Change font properties to `inherit` in Safari.\n//\n\n::-webkit-file-upload-button {\n font: inherit; // 2\n -webkit-appearance: button; // 1\n}\n\n//\n// Correct element displays\n//\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item; // Add the correct display in all browsers\n cursor: pointer;\n}\n\ntemplate {\n display: none; // Add the correct display in IE\n}\n\n// Always hide an element with the `hidden` HTML attribute (from PureCSS).\n// Needed for proper display in IE 10-.\n[hidden] {\n display: none !important;\n}\n","/*!\n * Bootstrap Reboot v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nhtml {\n font-family: sans-serif;\n line-height: 1.15;\n -webkit-text-size-adjust: 100%;\n -ms-text-size-adjust: 100%;\n -ms-overflow-style: scrollbar;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\n@-ms-viewport {\n width: device-width;\n}\n\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\nbody {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n text-align: left;\n background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\nhr {\n box-sizing: content-box;\n height: 0;\n overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n text-decoration: underline;\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n cursor: help;\n border-bottom: 0;\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: 700;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0;\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\ndfn {\n font-style: italic;\n}\n\nb,\nstrong {\n font-weight: bolder;\n}\n\nsmall {\n font-size: 80%;\n}\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -.25em;\n}\n\nsup {\n top: -.5em;\n}\n\na {\n color: #007bff;\n text-decoration: none;\n background-color: transparent;\n -webkit-text-decoration-skip: objects;\n}\n\na:hover {\n color: #0056b3;\n text-decoration: underline;\n}\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):focus {\n outline: 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 1em;\n}\n\npre {\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n -ms-overflow-style: scrollbar;\n}\n\nfigure {\n margin: 0 0 1rem;\n}\n\nimg {\n vertical-align: middle;\n border-style: none;\n}\n\nsvg {\n overflow: hidden;\n vertical-align: middle;\n}\n\ntable {\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n color: #6c757d;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n text-align: inherit;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 0.5rem;\n}\n\nbutton {\n border-radius: 0;\n}\n\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible;\n}\n\nbutton,\nselect {\n text-transform: none;\n}\n\nbutton,\nhtml [type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box;\n padding: 0;\n}\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto;\n resize: vertical;\n}\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n max-width: 100%;\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit;\n white-space: normal;\n}\n\nprogress {\n vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n outline-offset: -2px;\n -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-cancel-button,\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button;\n}\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n}\n\ntemplate {\n display: none;\n}\n\n[hidden] {\n display: none !important;\n}\n/*# sourceMappingURL=bootstrap-reboot.css.map */","/*!\n * Bootstrap Reboot v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nhtml {\n font-family: sans-serif;\n line-height: 1.15;\n -webkit-text-size-adjust: 100%;\n -ms-text-size-adjust: 100%;\n -ms-overflow-style: scrollbar;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\n@-ms-viewport {\n width: device-width;\n}\n\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\nbody {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n text-align: left;\n background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\nhr {\n box-sizing: content-box;\n height: 0;\n overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n text-decoration: underline;\n text-decoration: underline dotted;\n cursor: help;\n border-bottom: 0;\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: 700;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0;\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\ndfn {\n font-style: italic;\n}\n\nb,\nstrong {\n font-weight: bolder;\n}\n\nsmall {\n font-size: 80%;\n}\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -.25em;\n}\n\nsup {\n top: -.5em;\n}\n\na {\n color: #007bff;\n text-decoration: none;\n background-color: transparent;\n -webkit-text-decoration-skip: objects;\n}\n\na:hover {\n color: #0056b3;\n text-decoration: underline;\n}\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):focus {\n outline: 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 1em;\n}\n\npre {\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n -ms-overflow-style: scrollbar;\n}\n\nfigure {\n margin: 0 0 1rem;\n}\n\nimg {\n vertical-align: middle;\n border-style: none;\n}\n\nsvg {\n overflow: hidden;\n vertical-align: middle;\n}\n\ntable {\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n color: #6c757d;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n text-align: inherit;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 0.5rem;\n}\n\nbutton {\n border-radius: 0;\n}\n\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible;\n}\n\nbutton,\nselect {\n text-transform: none;\n}\n\nbutton,\nhtml [type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box;\n padding: 0;\n}\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto;\n resize: vertical;\n}\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n max-width: 100%;\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit;\n white-space: normal;\n}\n\nprogress {\n vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n outline-offset: -2px;\n -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-cancel-button,\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button;\n}\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n}\n\ntemplate {\n display: none;\n}\n\n[hidden] {\n display: none !important;\n}\n\n/*# sourceMappingURL=bootstrap-reboot.css.map */","// Hover mixin and `$enable-hover-media-query` are deprecated.\n//\n// Originally added during our alphas and maintained during betas, this mixin was\n// designed to prevent `:hover` stickiness on iOS-an issue where hover styles\n// would persist after initial touch.\n//\n// For backward compatibility, we've kept these mixins and updated them to\n// always return their regular pseudo-classes instead of a shimmed media query.\n//\n// Issue: https://github.com/twbs/bootstrap/issues/25195\n\n@mixin hover {\n &:hover { @content; }\n}\n\n@mixin hover-focus {\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin plain-hover-focus {\n &,\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin hover-focus-active {\n &:hover,\n &:focus,\n &:active {\n @content;\n }\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../../scss/bootstrap-reboot.scss","../../scss/_reboot.scss","dist/css/bootstrap-reboot.css","../../scss/vendor/_rfs.scss","bootstrap-reboot.css","../../scss/mixins/_hover.scss"],"names":[],"mappings":"AAAA;;;;;;ACkBA,ECTA,QADA,SDaE,WAAA,WAGF,KACE,YAAA,WACA,YAAA,KACA,yBAAA,KACA,4BAAA,YAMF,QAAA,MAAA,WAAA,OAAA,OAAA,OAAA,OAAA,KAAA,IAAA,QACE,QAAA,MAUF,KACE,OAAA,EACA,YAAA,aAAA,CAAA,kBAAA,CAAA,UAAA,CAAA,MAAA,CAAA,gBAAA,CAAA,KAAA,CAAA,WAAA,CAAA,UAAA,CAAA,mBAAA,CAAA,gBAAA,CAAA,iBAAA,CAAA,mBEgFI,UAAA,KF9EJ,YAAA,IACA,YAAA,IACA,MAAA,QACA,WAAA,KACA,iBAAA,KGlBF,sBH2BE,QAAA,YASF,GACE,WAAA,YACA,OAAA,EACA,SAAA,QAaF,GAAA,GAAA,GAAA,GAAA,GAAA,GACE,WAAA,EACA,cAAA,MAOF,EACE,WAAA,EACA,cAAA,KC1CF,0BDqDA,YAEE,gBAAA,UACA,wBAAA,UAAA,OAAA,gBAAA,UAAA,OACA,OAAA,KACA,cAAA,EACA,iCAAA,KAAA,yBAAA,KAGF,QACE,cAAA,KACA,WAAA,OACA,YAAA,QC/CF,GDkDA,GCnDA,GDsDE,WAAA,EACA,cAAA,KAGF,MClDA,MACA,MAFA,MDuDE,cAAA,EAGF,GACE,YAAA,IAGF,GACE,cAAA,MACA,YAAA,EAGF,WACE,OAAA,EAAA,EAAA,KAGF,ECnDA,ODqDE,YAAA,OAGF,MEpFI,UAAA,IF6FJ,ICxDA,ID0DE,SAAA,SE/FE,UAAA,IFiGF,YAAA,EACA,eAAA,SAGF,IAAM,OAAA,OACN,IAAM,IAAA,MAON,EACE,MAAA,QACA,gBAAA,KACA,iBAAA,YI5KA,QJ+KE,MAAA,QACA,gBAAA,UAUJ,8BACE,MAAA,QACA,gBAAA,KIxLA,oCAAA,oCJ2LE,MAAA,QACA,gBAAA,KANJ,oCAUI,QAAA,EC1DJ,KACA,IDkEA,ICjEA,KDqEE,YAAA,cAAA,CAAA,KAAA,CAAA,MAAA,CAAA,QAAA,CAAA,iBAAA,CAAA,aAAA,CAAA,UErJE,UAAA,IFyJJ,IAEE,WAAA,EAEA,cAAA,KAEA,SAAA,KAQF,OAEE,OAAA,EAAA,EAAA,KAQF,IACE,eAAA,OACA,aAAA,KAGF,IAGE,SAAA,OACA,eAAA,OAQF,MACE,gBAAA,SAGF,QACE,YAAA,OACA,eAAA,OACA,MAAA,QACA,WAAA,KACA,aAAA,OAGF,GAGE,WAAA,QAQF,MAEE,QAAA,aACA,cAAA,MAMF,OAEE,cAAA,EAOF,aACE,QAAA,IAAA,OACA,QAAA,IAAA,KAAA,yBCrGF,ODwGA,MCtGA,SADA,OAEA,SD0GE,OAAA,EACA,YAAA,QEtPE,UAAA,QFwPF,YAAA,QAGF,OCxGA,MD0GE,SAAA,QAGF,OCxGA,OD0GE,eAAA,KAMF,OACE,UAAA,OCxGF,cACA,aACA,cD6GA,OAIE,mBAAA,OC5GF,6BACA,4BACA,6BD+GE,sBAKI,OAAA,QC/GN,gCACA,+BACA,gCDmHA,yBAIE,QAAA,EACA,aAAA,KClHF,qBDqHA,kBAEE,WAAA,WACA,QAAA,EAIF,iBCrHA,2BACA,kBAFA,iBD+HE,mBAAA,QAGF,SACE,SAAA,KAEA,OAAA,SAGF,SAME,UAAA,EAEA,QAAA,EACA,OAAA,EACA,OAAA,EAKF,OACE,QAAA,MACA,MAAA,KACA,UAAA,KACA,QAAA,EACA,cAAA,MElSI,UAAA,OFoSJ,YAAA,QACA,MAAA,QACA,YAAA,OAGF,SACE,eAAA,SGpIF,yCFGA,yCDuIE,OAAA,KGrIF,cH6IE,eAAA,KACA,mBAAA,KGzIF,yCHiJE,mBAAA,KAQF,6BACE,KAAA,QACA,mBAAA,OAOF,OACE,QAAA,aAGF,QACE,QAAA,UACA,OAAA,QAGF,SACE,QAAA,KGtJF,SH4JE,QAAA","sourcesContent":["/*!\n * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n\n@import \"functions\";\n@import \"variables\";\n@import \"mixins\";\n@import \"reboot\";\n","// stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix\n\n// Reboot\n//\n// Normalization of HTML elements, manually forked from Normalize.css to remove\n// styles targeting irrelevant browsers while applying new styles.\n//\n// Normalize is licensed MIT. https://github.com/necolas/normalize.css\n\n\n// Document\n//\n// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.\n// 2. Change the default font family in all browsers.\n// 3. Correct the line height in all browsers.\n// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.\n// 5. Change the default tap highlight to be completely transparent in iOS.\n\n*,\n*::before,\n*::after {\n box-sizing: border-box; // 1\n}\n\nhtml {\n font-family: sans-serif; // 2\n line-height: 1.15; // 3\n -webkit-text-size-adjust: 100%; // 4\n -webkit-tap-highlight-color: rgba($black, 0); // 5\n}\n\n// Shim for \"new\" HTML5 structural elements to display correctly (IE10, older browsers)\n// TODO: remove in v5\n// stylelint-disable-next-line selector-list-comma-newline-after\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\n// Body\n//\n// 1. Remove the margin in all browsers.\n// 2. As a best practice, apply a default `background-color`.\n// 3. Set an explicit initial text-align value so that we can later use\n// the `inherit` value on things like `` elements.\n\nbody {\n margin: 0; // 1\n font-family: $font-family-base;\n @include font-size($font-size-base);\n font-weight: $font-weight-base;\n line-height: $line-height-base;\n color: $body-color;\n text-align: left; // 3\n background-color: $body-bg; // 2\n}\n\n// Suppress the focus outline on elements that cannot be accessed via keyboard.\n// This prevents an unwanted focus outline from appearing around elements that\n// might still respond to pointer events.\n//\n// Credit: https://github.com/suitcss/base\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\n\n// Content grouping\n//\n// 1. Add the correct box sizing in Firefox.\n// 2. Show the overflow in Edge and IE.\n\nhr {\n box-sizing: content-box; // 1\n height: 0; // 1\n overflow: visible; // 2\n}\n\n\n//\n// Typography\n//\n\n// Remove top margins from headings\n//\n// By default, `

    `-`

    ` all receive top and bottom margins. We nuke the top\n// margin for easier control within type scales as it avoids margin collapsing.\n// stylelint-disable-next-line selector-list-comma-newline-after\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: $headings-margin-bottom;\n}\n\n// Reset margins on paragraphs\n//\n// Similarly, the top margin on `

    `s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n// Abbreviations\n//\n// 1. Duplicate behavior to the data-* attribute for our tooltip plugin\n// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Remove the bottom border in Firefox 39-.\n// 5. Prevent the text-decoration to be skipped.\n\nabbr[title],\nabbr[data-original-title] { // 1\n text-decoration: underline; // 2\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n border-bottom: 0; // 4\n text-decoration-skip-ink: none; // 5\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // Undo browser default\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: $font-weight-bolder; // Add the correct font weight in Chrome, Edge, and Safari\n}\n\nsmall {\n @include font-size(80%); // Add the correct font size in all browsers\n}\n\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n//\n\nsub,\nsup {\n position: relative;\n @include font-size(75%);\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n//\n// Links\n//\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n background-color: transparent; // Remove the gray background on active links in IE 10.\n\n @include hover {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href)\n// which have not been made explicitly keyboard-focusable (without tabindex).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n\n @include hover-focus {\n color: inherit;\n text-decoration: none;\n }\n\n &:focus {\n outline: 0;\n }\n}\n\n\n//\n// Code\n//\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-monospace;\n @include font-size(1em); // Correct the odd `em` font sizing in all browsers.\n}\n\npre {\n // Remove browser default top margin\n margin-top: 0;\n // Reset browser default of `1em` to use `rem`s\n margin-bottom: 1rem;\n // Don't allow content to break outside\n overflow: auto;\n}\n\n\n//\n// Figures\n//\n\nfigure {\n // Apply a consistent margin strategy (matches our type styles).\n margin: 0 0 1rem;\n}\n\n\n//\n// Images and content\n//\n\nimg {\n vertical-align: middle;\n border-style: none; // Remove the border on images inside links in IE 10-.\n}\n\nsvg {\n // Workaround for the SVG overflow bug in IE10/11 is still required.\n // See https://github.com/twbs/bootstrap/issues/26878\n overflow: hidden;\n vertical-align: middle;\n}\n\n\n//\n// Tables\n//\n\ntable {\n border-collapse: collapse; // Prevent double borders\n}\n\ncaption {\n padding-top: $table-cell-padding;\n padding-bottom: $table-cell-padding;\n color: $table-caption-color;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n // Matches default `` alignment by inheriting from the ``, or the\n // closest parent with a set `text-align`.\n text-align: inherit;\n}\n\n\n//\n// Forms\n//\n\nlabel {\n // Allow labels to use `margin` for spacing.\n display: inline-block;\n margin-bottom: $label-margin-bottom;\n}\n\n// Remove the default `border-radius` that macOS Chrome adds.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24093\nbutton {\n // stylelint-disable-next-line property-blacklist\n border-radius: 0;\n}\n\n// Work around a Firefox/IE bug where the transparent `button` background\n// results in a loss of the default `button` focus styles.\n//\n// Credit: https://github.com/suitcss/base/\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0; // Remove the margin in Firefox and Safari\n font-family: inherit;\n @include font-size(inherit);\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible; // Show the overflow in Edge\n}\n\nbutton,\nselect {\n text-transform: none; // Remove the inheritance of text transform in Firefox\n}\n\n// Remove the inheritance of word-wrap in Safari.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24990\nselect {\n word-wrap: normal;\n}\n\n\n// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`\n// controls in Android 4.\n// 2. Correct the inability to style clickable types in iOS and Safari.\nbutton,\n[type=\"button\"], // 1\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button; // 2\n}\n\n// Opinionated: add \"hand\" cursor to non-disabled button elements.\n@if $enable-pointer-cursor-for-buttons {\n button,\n [type=\"button\"],\n [type=\"reset\"],\n [type=\"submit\"] {\n &:not(:disabled) {\n cursor: pointer;\n }\n }\n}\n\n// Remove inner border and padding from Firefox, but don't restore the outline like Normalize.\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box; // 1. Add the correct box sizing in IE 10-\n padding: 0; // 2. Remove the padding in IE 10-\n}\n\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n // Remove the default appearance of temporal inputs to avoid a Mobile Safari\n // bug where setting a custom line-height prevents text from being vertically\n // centered within the input.\n // See https://bugs.webkit.org/show_bug.cgi?id=139848\n // and https://github.com/twbs/bootstrap/issues/11266\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto; // Remove the default vertical scrollbar in IE.\n // Textareas should really only resize vertically so they don't break their (horizontal) containers.\n resize: vertical;\n}\n\nfieldset {\n // Browsers set a default `min-width: min-content;` on fieldsets,\n // unlike e.g. `

    `s, which have `min-width: 0;` by default.\n // So we reset that to ensure fieldsets behave more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359\n // and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements\n min-width: 0;\n // Reset the default outline behavior of fieldsets so they don't affect page layout.\n padding: 0;\n margin: 0;\n border: 0;\n}\n\n// 1. Correct the text wrapping in Edge and IE.\n// 2. Correct the color inheritance from `fieldset` elements in IE.\nlegend {\n display: block;\n width: 100%;\n max-width: 100%; // 1\n padding: 0;\n margin-bottom: .5rem;\n @include font-size(1.5rem);\n line-height: inherit;\n color: inherit; // 2\n white-space: normal; // 1\n}\n\nprogress {\n vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera.\n}\n\n// Correct the cursor style of increment and decrement buttons in Chrome.\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n // This overrides the extra rounded corners on search inputs in iOS so that our\n // `.form-control` class can properly style them. Note that this cannot simply\n // be added to `.form-control` as it's not specific enough. For details, see\n // https://github.com/twbs/bootstrap/issues/11586.\n outline-offset: -2px; // 2. Correct the outline style in Safari.\n -webkit-appearance: none;\n}\n\n//\n// Remove the inner padding in Chrome and Safari on macOS.\n//\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// 1. Correct the inability to style clickable types in iOS and Safari.\n// 2. Change font properties to `inherit` in Safari.\n//\n\n::-webkit-file-upload-button {\n font: inherit; // 2\n -webkit-appearance: button; // 1\n}\n\n//\n// Correct element displays\n//\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item; // Add the correct display in all browsers\n cursor: pointer;\n}\n\ntemplate {\n display: none; // Add the correct display in IE\n}\n\n// Always hide an element with the `hidden` HTML attribute (from PureCSS).\n// Needed for proper display in IE 10-.\n[hidden] {\n display: none !important;\n}\n","/*!\n * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nhtml {\n font-family: sans-serif;\n line-height: 1.15;\n -webkit-text-size-adjust: 100%;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\nbody {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n text-align: left;\n background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\nhr {\n box-sizing: content-box;\n height: 0;\n overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n text-decoration: underline;\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n cursor: help;\n border-bottom: 0;\n -webkit-text-decoration-skip-ink: none;\n text-decoration-skip-ink: none;\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: 700;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0;\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: bolder;\n}\n\nsmall {\n font-size: 80%;\n}\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -.25em;\n}\n\nsup {\n top: -.5em;\n}\n\na {\n color: #007bff;\n text-decoration: none;\n background-color: transparent;\n}\n\na:hover {\n color: #0056b3;\n text-decoration: underline;\n}\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):focus {\n outline: 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 1em;\n}\n\npre {\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n}\n\nfigure {\n margin: 0 0 1rem;\n}\n\nimg {\n vertical-align: middle;\n border-style: none;\n}\n\nsvg {\n overflow: hidden;\n vertical-align: middle;\n}\n\ntable {\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n color: #6c757d;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n text-align: inherit;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 0.5rem;\n}\n\nbutton {\n border-radius: 0;\n}\n\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible;\n}\n\nbutton,\nselect {\n text-transform: none;\n}\n\nselect {\n word-wrap: normal;\n}\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\nbutton:not(:disabled),\n[type=\"button\"]:not(:disabled),\n[type=\"reset\"]:not(:disabled),\n[type=\"submit\"]:not(:disabled) {\n cursor: pointer;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box;\n padding: 0;\n}\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto;\n resize: vertical;\n}\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n max-width: 100%;\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit;\n white-space: normal;\n}\n\nprogress {\n vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n outline-offset: -2px;\n -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button;\n}\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n}\n\ntemplate {\n display: none;\n}\n\n[hidden] {\n display: none !important;\n}\n/*# sourceMappingURL=bootstrap-reboot.css.map */","// stylelint-disable property-blacklist, scss/dollar-variable-default\n\n// SCSS RFS mixin\n//\n// Automated font-resizing\n//\n// See https://github.com/twbs/rfs\n\n// Configuration\n\n// Base font size\n$rfs-base-font-size: 1.25rem !default;\n$rfs-font-size-unit: rem !default;\n\n// Breakpoint at where font-size starts decreasing if screen width is smaller\n$rfs-breakpoint: 1200px !default;\n$rfs-breakpoint-unit: px !default;\n\n// Resize font-size based on screen height and width\n$rfs-two-dimensional: false !default;\n\n// Factor of decrease\n$rfs-factor: 10 !default;\n\n@if type-of($rfs-factor) != \"number\" or $rfs-factor <= 1 {\n @error \"`#{$rfs-factor}` is not a valid $rfs-factor, it must be greater than 1.\";\n}\n\n// Generate enable or disable classes. Possibilities: false, \"enable\" or \"disable\"\n$rfs-class: false !default;\n\n// 1 rem = $rfs-rem-value px\n$rfs-rem-value: 16 !default;\n\n// Safari iframe resize bug: https://github.com/twbs/rfs/issues/14\n$rfs-safari-iframe-resize-bug-fix: false !default;\n\n// Disable RFS by setting $enable-responsive-font-sizes to false\n$enable-responsive-font-sizes: true !default;\n\n// Cache $rfs-base-font-size unit\n$rfs-base-font-size-unit: unit($rfs-base-font-size);\n\n// Remove px-unit from $rfs-base-font-size for calculations\n@if $rfs-base-font-size-unit == \"px\" {\n $rfs-base-font-size: $rfs-base-font-size / ($rfs-base-font-size * 0 + 1);\n}\n@else if $rfs-base-font-size-unit == \"rem\" {\n $rfs-base-font-size: $rfs-base-font-size / ($rfs-base-font-size * 0 + 1 / $rfs-rem-value);\n}\n\n// Cache $rfs-breakpoint unit to prevent multiple calls\n$rfs-breakpoint-unit-cache: unit($rfs-breakpoint);\n\n// Remove unit from $rfs-breakpoint for calculations\n@if $rfs-breakpoint-unit-cache == \"px\" {\n $rfs-breakpoint: $rfs-breakpoint / ($rfs-breakpoint * 0 + 1);\n}\n@else if $rfs-breakpoint-unit-cache == \"rem\" or $rfs-breakpoint-unit-cache == \"em\" {\n $rfs-breakpoint: $rfs-breakpoint / ($rfs-breakpoint * 0 + 1 / $rfs-rem-value);\n}\n\n// Responsive font-size mixin\n@mixin rfs($fs, $important: false) {\n // Cache $fs unit\n $fs-unit: if(type-of($fs) == \"number\", unit($fs), false);\n\n // Add !important suffix if needed\n $rfs-suffix: if($important, \" !important\", \"\");\n\n // If $fs isn't a number (like inherit) or $fs has a unit (not px or rem, like 1.5em) or $ is 0, just print the value\n @if not $fs-unit or $fs-unit != \"\" and $fs-unit != \"px\" and $fs-unit != \"rem\" or $fs == 0 {\n font-size: #{$fs}#{$rfs-suffix};\n }\n @else {\n // Variables for storing static and fluid rescaling\n $rfs-static: null;\n $rfs-fluid: null;\n\n // Remove px-unit from $fs for calculations\n @if $fs-unit == \"px\" {\n $fs: $fs / ($fs * 0 + 1);\n }\n @else if $fs-unit == \"rem\" {\n $fs: $fs / ($fs * 0 + 1 / $rfs-rem-value);\n }\n\n // Set default font-size\n @if $rfs-font-size-unit == rem {\n $rfs-static: #{$fs / $rfs-rem-value}rem#{$rfs-suffix};\n }\n @else if $rfs-font-size-unit == px {\n $rfs-static: #{$fs}px#{$rfs-suffix};\n }\n @else {\n @error \"`#{$rfs-font-size-unit}` is not a valid unit for $rfs-font-size-unit. Use `px` or `rem`.\";\n }\n\n // Only add media query if font-size is bigger as the minimum font-size\n // If $rfs-factor == 1, no rescaling will take place\n @if $fs > $rfs-base-font-size and $enable-responsive-font-sizes {\n $min-width: null;\n $variable-unit: null;\n\n // Calculate minimum font-size for given font-size\n $fs-min: $rfs-base-font-size + ($fs - $rfs-base-font-size) / $rfs-factor;\n\n // Calculate difference between given font-size and minimum font-size for given font-size\n $fs-diff: $fs - $fs-min;\n\n // Base font-size formatting\n // No need to check if the unit is valid, because we did that before\n $min-width: if($rfs-font-size-unit == rem, #{$fs-min / $rfs-rem-value}rem, #{$fs-min}px);\n\n // If two-dimensional, use smallest of screen width and height\n $variable-unit: if($rfs-two-dimensional, vmin, vw);\n\n // Calculate the variable width between 0 and $rfs-breakpoint\n $variable-width: #{$fs-diff * 100 / $rfs-breakpoint}#{$variable-unit};\n\n // Set the calculated font-size.\n $rfs-fluid: calc(#{$min-width} + #{$variable-width}) #{$rfs-suffix};\n }\n\n // Rendering\n @if $rfs-fluid == null {\n // Only render static font-size if no fluid font-size is available\n font-size: $rfs-static;\n }\n @else {\n $mq-value: null;\n\n // RFS breakpoint formatting\n @if $rfs-breakpoint-unit == em or $rfs-breakpoint-unit == rem {\n $mq-value: #{$rfs-breakpoint / $rfs-rem-value}#{$rfs-breakpoint-unit};\n }\n @else if $rfs-breakpoint-unit == px {\n $mq-value: #{$rfs-breakpoint}px;\n }\n @else {\n @error \"`#{$rfs-breakpoint-unit}` is not a valid unit for $rfs-breakpoint-unit. Use `px`, `em` or `rem`.\";\n }\n\n @if $rfs-class == \"disable\" {\n // Adding an extra class increases specificity,\n // which prevents the media query to override the font size\n &,\n .disable-responsive-font-size &,\n &.disable-responsive-font-size {\n font-size: $rfs-static;\n }\n }\n @else {\n font-size: $rfs-static;\n }\n\n @if $rfs-two-dimensional {\n @media (max-width: #{$mq-value}), (max-height: #{$mq-value}) {\n @if $rfs-class == \"enable\" {\n .enable-responsive-font-size &,\n &.enable-responsive-font-size {\n font-size: $rfs-fluid;\n }\n }\n @else {\n font-size: $rfs-fluid;\n }\n\n @if $rfs-safari-iframe-resize-bug-fix {\n // stylelint-disable-next-line length-zero-no-unit\n min-width: 0vw;\n }\n }\n }\n @else {\n @media (max-width: #{$mq-value}) {\n @if $rfs-class == \"enable\" {\n .enable-responsive-font-size &,\n &.enable-responsive-font-size {\n font-size: $rfs-fluid;\n }\n }\n @else {\n font-size: $rfs-fluid;\n }\n\n @if $rfs-safari-iframe-resize-bug-fix {\n // stylelint-disable-next-line length-zero-no-unit\n min-width: 0vw;\n }\n }\n }\n }\n }\n}\n\n// The font-size & responsive-font-size mixin uses RFS to rescale font sizes\n@mixin font-size($fs, $important: false) {\n @include rfs($fs, $important);\n}\n\n@mixin responsive-font-size($fs, $important: false) {\n @include rfs($fs, $important);\n}\n","/*!\n * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 The Bootstrap Authors\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nhtml {\n font-family: sans-serif;\n line-height: 1.15;\n -webkit-text-size-adjust: 100%;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\nbody {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n text-align: left;\n background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\nhr {\n box-sizing: content-box;\n height: 0;\n overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n text-decoration: underline;\n text-decoration: underline dotted;\n cursor: help;\n border-bottom: 0;\n text-decoration-skip-ink: none;\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: 700;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0;\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: bolder;\n}\n\nsmall {\n font-size: 80%;\n}\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -.25em;\n}\n\nsup {\n top: -.5em;\n}\n\na {\n color: #007bff;\n text-decoration: none;\n background-color: transparent;\n}\n\na:hover {\n color: #0056b3;\n text-decoration: underline;\n}\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):focus {\n outline: 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 1em;\n}\n\npre {\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n}\n\nfigure {\n margin: 0 0 1rem;\n}\n\nimg {\n vertical-align: middle;\n border-style: none;\n}\n\nsvg {\n overflow: hidden;\n vertical-align: middle;\n}\n\ntable {\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n color: #6c757d;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n text-align: inherit;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 0.5rem;\n}\n\nbutton {\n border-radius: 0;\n}\n\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible;\n}\n\nbutton,\nselect {\n text-transform: none;\n}\n\nselect {\n word-wrap: normal;\n}\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\nbutton:not(:disabled),\n[type=\"button\"]:not(:disabled),\n[type=\"reset\"]:not(:disabled),\n[type=\"submit\"]:not(:disabled) {\n cursor: pointer;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box;\n padding: 0;\n}\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto;\n resize: vertical;\n}\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n max-width: 100%;\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit;\n white-space: normal;\n}\n\nprogress {\n vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n outline-offset: -2px;\n -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button;\n}\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n}\n\ntemplate {\n display: none;\n}\n\n[hidden] {\n display: none !important;\n}\n\n/*# sourceMappingURL=bootstrap-reboot.css.map */","// Hover mixin and `$enable-hover-media-query` are deprecated.\n//\n// Originally added during our alphas and maintained during betas, this mixin was\n// designed to prevent `:hover` stickiness on iOS-an issue where hover styles\n// would persist after initial touch.\n//\n// For backward compatibility, we've kept these mixins and updated them to\n// always return their regular pseudo-classes instead of a shimmed media query.\n//\n// Issue: https://github.com/twbs/bootstrap/issues/25195\n\n@mixin hover {\n &:hover { @content; }\n}\n\n@mixin hover-focus {\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin plain-hover-focus {\n &,\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin hover-focus-active {\n &:hover,\n &:focus,\n &:active {\n @content;\n }\n}\n"]} \ No newline at end of file diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap.css b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap.css index 943532db..8f475892 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap.css +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap.css @@ -1,7 +1,7 @@ /*! - * Bootstrap v4.1.3 (https://getbootstrap.com/) - * Copyright 2011-2018 The Bootstrap Authors - * Copyright 2011-2018 Twitter, Inc. + * Bootstrap v4.3.1 (https://getbootstrap.com/) + * Copyright 2011-2019 The Bootstrap Authors + * Copyright 2011-2019 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ :root { @@ -31,7 +31,7 @@ --breakpoint-md: 768px; --breakpoint-lg: 992px; --breakpoint-xl: 1200px; - --font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + --font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; } @@ -45,22 +45,16 @@ html { font-family: sans-serif; line-height: 1.15; -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; - -ms-overflow-style: scrollbar; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } -@-ms-viewport { - width: device-width; -} - article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { display: block; } body { margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 1rem; font-weight: 400; line-height: 1.5; @@ -96,6 +90,8 @@ abbr[data-original-title] { text-decoration: underline dotted; cursor: help; border-bottom: 0; + -webkit-text-decoration-skip-ink: none; + text-decoration-skip-ink: none; } address { @@ -131,10 +127,6 @@ blockquote { margin: 0 0 1rem; } -dfn { - font-style: italic; -} - b, strong { font-weight: bolder; @@ -164,7 +156,6 @@ a { color: #007bff; text-decoration: none; background-color: transparent; - -webkit-text-decoration-skip: objects; } a:hover { @@ -198,7 +189,6 @@ pre { margin-top: 0; margin-bottom: 1rem; overflow: auto; - -ms-overflow-style: scrollbar; } figure { @@ -266,13 +256,24 @@ select { text-transform: none; } +select { + word-wrap: normal; +} + button, -html [type="button"], +[type="button"], [type="reset"], [type="submit"] { -webkit-appearance: button; } +button:not(:disabled), +[type="button"]:not(:disabled), +[type="reset"]:not(:disabled), +[type="submit"]:not(:disabled) { + cursor: pointer; +} + button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, @@ -332,7 +333,6 @@ progress { -webkit-appearance: none; } -[type="search"]::-webkit-search-cancel-button, [type="search"]::-webkit-search-decoration { -webkit-appearance: none; } @@ -362,10 +362,8 @@ template { h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 { margin-bottom: 0.5rem; - font-family: inherit; font-weight: 500; line-height: 1.2; - color: inherit; } h1, .h1 { @@ -475,7 +473,7 @@ mark, } .blockquote-footer::before { - content: "\2014 \00A0"; + content: "\2014\00A0"; } .img-fluid { @@ -615,7 +613,6 @@ pre code { .col-xl-auto { position: relative; width: 100%; - min-height: 1px; padding-right: 15px; padding-left: 15px; } @@ -632,7 +629,7 @@ pre code { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; - max-width: none; + max-width: 100%; } .col-1 { @@ -838,7 +835,7 @@ pre code { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; - max-width: none; + max-width: 100%; } .col-sm-1 { -ms-flex: 0 0 8.333333%; @@ -1010,7 +1007,7 @@ pre code { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; - max-width: none; + max-width: 100%; } .col-md-1 { -ms-flex: 0 0 8.333333%; @@ -1182,7 +1179,7 @@ pre code { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; - max-width: none; + max-width: 100%; } .col-lg-1 { -ms-flex: 0 0 8.333333%; @@ -1354,7 +1351,7 @@ pre code { -ms-flex: 0 0 auto; flex: 0 0 auto; width: auto; - max-width: none; + max-width: 100%; } .col-xl-1 { -ms-flex: 0 0 8.333333%; @@ -1517,7 +1514,7 @@ pre code { .table { width: 100%; margin-bottom: 1rem; - background-color: transparent; + color: #212529; } .table th, @@ -1536,10 +1533,6 @@ pre code { border-top: 2px solid #dee2e6; } -.table .table { - background-color: #fff; -} - .table-sm th, .table-sm td { padding: 0.3rem; @@ -1571,6 +1564,7 @@ pre code { } .table-hover tbody tr:hover { + color: #212529; background-color: rgba(0, 0, 0, 0.075); } @@ -1580,6 +1574,13 @@ pre code { background-color: #b8daff; } +.table-primary th, +.table-primary td, +.table-primary thead th, +.table-primary tbody + tbody { + border-color: #7abaff; +} + .table-hover .table-primary:hover { background-color: #9fcdff; } @@ -1595,6 +1596,13 @@ pre code { background-color: #d6d8db; } +.table-secondary th, +.table-secondary td, +.table-secondary thead th, +.table-secondary tbody + tbody { + border-color: #b3b7bb; +} + .table-hover .table-secondary:hover { background-color: #c8cbcf; } @@ -1610,6 +1618,13 @@ pre code { background-color: #c3e6cb; } +.table-success th, +.table-success td, +.table-success thead th, +.table-success tbody + tbody { + border-color: #8fd19e; +} + .table-hover .table-success:hover { background-color: #b1dfbb; } @@ -1625,6 +1640,13 @@ pre code { background-color: #bee5eb; } +.table-info th, +.table-info td, +.table-info thead th, +.table-info tbody + tbody { + border-color: #86cfda; +} + .table-hover .table-info:hover { background-color: #abdde5; } @@ -1640,6 +1662,13 @@ pre code { background-color: #ffeeba; } +.table-warning th, +.table-warning td, +.table-warning thead th, +.table-warning tbody + tbody { + border-color: #ffdf7e; +} + .table-hover .table-warning:hover { background-color: #ffe8a1; } @@ -1655,6 +1684,13 @@ pre code { background-color: #f5c6cb; } +.table-danger th, +.table-danger td, +.table-danger thead th, +.table-danger tbody + tbody { + border-color: #ed969e; +} + .table-hover .table-danger:hover { background-color: #f1b0b7; } @@ -1670,6 +1706,13 @@ pre code { background-color: #fdfdfe; } +.table-light th, +.table-light td, +.table-light thead th, +.table-light tbody + tbody { + border-color: #fbfcfc; +} + .table-hover .table-light:hover { background-color: #ececf6; } @@ -1685,6 +1728,13 @@ pre code { background-color: #c6c8ca; } +.table-dark th, +.table-dark td, +.table-dark thead th, +.table-dark tbody + tbody { + border-color: #95999c; +} + .table-hover .table-dark:hover { background-color: #b9bbbe; } @@ -1711,8 +1761,8 @@ pre code { .table .thead-dark th { color: #fff; - background-color: #212529; - border-color: #32383e; + background-color: #343a40; + border-color: #454d55; } .table .thead-light th { @@ -1723,13 +1773,13 @@ pre code { .table-dark { color: #fff; - background-color: #212529; + background-color: #343a40; } .table-dark th, .table-dark td, .table-dark thead th { - border-color: #32383e; + border-color: #454d55; } .table-dark.table-bordered { @@ -1741,6 +1791,7 @@ pre code { } .table-dark.table-hover tbody tr:hover { + color: #fff; background-color: rgba(255, 255, 255, 0.075); } @@ -1750,7 +1801,6 @@ pre code { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; - -ms-overflow-style: -ms-autohiding-scrollbar; } .table-responsive-sm > .table-bordered { border: 0; @@ -1763,7 +1813,6 @@ pre code { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; - -ms-overflow-style: -ms-autohiding-scrollbar; } .table-responsive-md > .table-bordered { border: 0; @@ -1776,7 +1825,6 @@ pre code { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; - -ms-overflow-style: -ms-autohiding-scrollbar; } .table-responsive-lg > .table-bordered { border: 0; @@ -1789,7 +1837,6 @@ pre code { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; - -ms-overflow-style: -ms-autohiding-scrollbar; } .table-responsive-xl > .table-bordered { border: 0; @@ -1801,7 +1848,6 @@ pre code { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; - -ms-overflow-style: -ms-autohiding-scrollbar; } .table-responsive > .table-bordered { @@ -1811,9 +1857,10 @@ pre code { .form-control { display: block; width: 100%; - height: calc(2.25rem + 2px); + height: calc(1.5em + 0.75rem + 2px); padding: 0.375rem 0.75rem; font-size: 1rem; + font-weight: 400; line-height: 1.5; color: #495057; background-color: #fff; @@ -1823,7 +1870,7 @@ pre code { transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } -@media screen and (prefers-reduced-motion: reduce) { +@media (prefers-reduced-motion: reduce) { .form-control { transition: none; } @@ -1924,7 +1971,7 @@ select.form-control:focus::-ms-value { } .form-control-sm { - height: calc(1.8125rem + 2px); + height: calc(1.5em + 0.5rem + 2px); padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; @@ -1932,7 +1979,7 @@ select.form-control:focus::-ms-value { } .form-control-lg { - height: calc(2.875rem + 2px); + height: calc(1.5em + 1rem + 2px); padding: 0.5rem 1rem; font-size: 1.25rem; line-height: 1.5; @@ -2030,26 +2077,44 @@ textarea.form-control { border-radius: 0.25rem; } -.was-validated .form-control:valid, .form-control.is-valid, .was-validated -.custom-select:valid, -.custom-select.is-valid { +.was-validated .form-control:valid, .form-control.is-valid { border-color: #28a745; + padding-right: calc(1.5em + 0.75rem); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: center right calc(0.375em + 0.1875rem); + background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } -.was-validated .form-control:valid:focus, .form-control.is-valid:focus, .was-validated -.custom-select:valid:focus, -.custom-select.is-valid:focus { +.was-validated .form-control:valid:focus, .form-control.is-valid:focus { border-color: #28a745; box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); } .was-validated .form-control:valid ~ .valid-feedback, .was-validated .form-control:valid ~ .valid-tooltip, .form-control.is-valid ~ .valid-feedback, -.form-control.is-valid ~ .valid-tooltip, .was-validated -.custom-select:valid ~ .valid-feedback, -.was-validated -.custom-select:valid ~ .valid-tooltip, -.custom-select.is-valid ~ .valid-feedback, +.form-control.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated textarea.form-control:valid, textarea.form-control.is-valid { + padding-right: calc(1.5em + 0.75rem); + background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); +} + +.was-validated .custom-select:valid, .custom-select.is-valid { + border-color: #28a745; + padding-right: calc((1em + 0.75rem) * 3 / 4 + 1.75rem); + background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px, url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} + +.was-validated .custom-select:valid:focus, .custom-select.is-valid:focus { + border-color: #28a745; + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); +} + +.was-validated .custom-select:valid ~ .valid-feedback, +.was-validated .custom-select:valid ~ .valid-tooltip, .custom-select.is-valid ~ .valid-feedback, .custom-select.is-valid ~ .valid-tooltip { display: block; } @@ -2075,7 +2140,7 @@ textarea.form-control { } .was-validated .custom-control-input:valid ~ .custom-control-label::before, .custom-control-input.is-valid ~ .custom-control-label::before { - background-color: #71dd8a; + border-color: #28a745; } .was-validated .custom-control-input:valid ~ .valid-feedback, @@ -2085,19 +2150,20 @@ textarea.form-control { } .was-validated .custom-control-input:valid:checked ~ .custom-control-label::before, .custom-control-input.is-valid:checked ~ .custom-control-label::before { + border-color: #34ce57; background-color: #34ce57; } .was-validated .custom-control-input:valid:focus ~ .custom-control-label::before, .custom-control-input.is-valid:focus ~ .custom-control-label::before { - box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(40, 167, 69, 0.25); + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); } -.was-validated .custom-file-input:valid ~ .custom-file-label, .custom-file-input.is-valid ~ .custom-file-label { +.was-validated .custom-control-input:valid:focus:not(:checked) ~ .custom-control-label::before, .custom-control-input.is-valid:focus:not(:checked) ~ .custom-control-label::before { border-color: #28a745; } -.was-validated .custom-file-input:valid ~ .custom-file-label::after, .custom-file-input.is-valid ~ .custom-file-label::after { - border-color: inherit; +.was-validated .custom-file-input:valid ~ .custom-file-label, .custom-file-input.is-valid ~ .custom-file-label { + border-color: #28a745; } .was-validated .custom-file-input:valid ~ .valid-feedback, @@ -2107,6 +2173,7 @@ textarea.form-control { } .was-validated .custom-file-input:valid:focus ~ .custom-file-label, .custom-file-input.is-valid:focus ~ .custom-file-label { + border-color: #28a745; box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); } @@ -2133,26 +2200,44 @@ textarea.form-control { border-radius: 0.25rem; } -.was-validated .form-control:invalid, .form-control.is-invalid, .was-validated -.custom-select:invalid, -.custom-select.is-invalid { +.was-validated .form-control:invalid, .form-control.is-invalid { border-color: #dc3545; + padding-right: calc(1.5em + 0.75rem); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23dc3545' viewBox='-2 -2 7 7'%3e%3cpath stroke='%23dc3545' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E"); + background-repeat: no-repeat; + background-position: center right calc(0.375em + 0.1875rem); + background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); } -.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus, .was-validated -.custom-select:invalid:focus, -.custom-select.is-invalid:focus { +.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus { border-color: #dc3545; box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); } .was-validated .form-control:invalid ~ .invalid-feedback, .was-validated .form-control:invalid ~ .invalid-tooltip, .form-control.is-invalid ~ .invalid-feedback, -.form-control.is-invalid ~ .invalid-tooltip, .was-validated -.custom-select:invalid ~ .invalid-feedback, -.was-validated -.custom-select:invalid ~ .invalid-tooltip, -.custom-select.is-invalid ~ .invalid-feedback, +.form-control.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated textarea.form-control:invalid, textarea.form-control.is-invalid { + padding-right: calc(1.5em + 0.75rem); + background-position: top calc(0.375em + 0.1875rem) right calc(0.375em + 0.1875rem); +} + +.was-validated .custom-select:invalid, .custom-select.is-invalid { + border-color: #dc3545; + padding-right: calc((1em + 0.75rem) * 3 / 4 + 1.75rem); + background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px, url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23dc3545' viewBox='-2 -2 7 7'%3e%3cpath stroke='%23dc3545' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem); +} + +.was-validated .custom-select:invalid:focus, .custom-select.is-invalid:focus { + border-color: #dc3545; + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); +} + +.was-validated .custom-select:invalid ~ .invalid-feedback, +.was-validated .custom-select:invalid ~ .invalid-tooltip, .custom-select.is-invalid ~ .invalid-feedback, .custom-select.is-invalid ~ .invalid-tooltip { display: block; } @@ -2178,7 +2263,7 @@ textarea.form-control { } .was-validated .custom-control-input:invalid ~ .custom-control-label::before, .custom-control-input.is-invalid ~ .custom-control-label::before { - background-color: #efa2a9; + border-color: #dc3545; } .was-validated .custom-control-input:invalid ~ .invalid-feedback, @@ -2188,19 +2273,20 @@ textarea.form-control { } .was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before, .custom-control-input.is-invalid:checked ~ .custom-control-label::before { + border-color: #e4606d; background-color: #e4606d; } .was-validated .custom-control-input:invalid:focus ~ .custom-control-label::before, .custom-control-input.is-invalid:focus ~ .custom-control-label::before { - box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(220, 53, 69, 0.25); + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); } -.was-validated .custom-file-input:invalid ~ .custom-file-label, .custom-file-input.is-invalid ~ .custom-file-label { +.was-validated .custom-control-input:invalid:focus:not(:checked) ~ .custom-control-label::before, .custom-control-input.is-invalid:focus:not(:checked) ~ .custom-control-label::before { border-color: #dc3545; } -.was-validated .custom-file-input:invalid ~ .custom-file-label::after, .custom-file-input.is-invalid ~ .custom-file-label::after { - border-color: inherit; +.was-validated .custom-file-input:invalid ~ .custom-file-label, .custom-file-input.is-invalid ~ .custom-file-label { + border-color: #dc3545; } .was-validated .custom-file-input:invalid ~ .invalid-feedback, @@ -2210,6 +2296,7 @@ textarea.form-control { } .was-validated .custom-file-input:invalid:focus ~ .custom-file-label, .custom-file-input.is-invalid:focus ~ .custom-file-label { + border-color: #dc3545; box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); } @@ -2271,6 +2358,8 @@ textarea.form-control { } .form-inline .form-check-input { position: relative; + -ms-flex-negative: 0; + flex-shrink: 0; margin-top: 0; margin-right: 0.25rem; margin-left: 0; @@ -2289,13 +2378,14 @@ textarea.form-control { .btn { display: inline-block; font-weight: 400; + color: #212529; text-align: center; - white-space: nowrap; vertical-align: middle; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; + background-color: transparent; border: 1px solid transparent; padding: 0.375rem 0.75rem; font-size: 1rem; @@ -2304,13 +2394,14 @@ textarea.form-control { transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } -@media screen and (prefers-reduced-motion: reduce) { +@media (prefers-reduced-motion: reduce) { .btn { transition: none; } } -.btn:hover, .btn:focus { +.btn:hover { + color: #212529; text-decoration: none; } @@ -2323,10 +2414,6 @@ textarea.form-control { opacity: 0.65; } -.btn:not(:disabled):not(.disabled) { - cursor: pointer; -} - a.btn.disabled, fieldset:disabled a.btn { pointer-events: none; @@ -2345,7 +2432,7 @@ fieldset:disabled a.btn { } .btn-primary:focus, .btn-primary.focus { - box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); + box-shadow: 0 0 0 0.2rem rgba(38, 143, 255, 0.5); } .btn-primary.disabled, .btn-primary:disabled { @@ -2363,7 +2450,7 @@ fieldset:disabled a.btn { .btn-primary:not(:disabled):not(.disabled):active:focus, .btn-primary:not(:disabled):not(.disabled).active:focus, .show > .btn-primary.dropdown-toggle:focus { - box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); + box-shadow: 0 0 0 0.2rem rgba(38, 143, 255, 0.5); } .btn-secondary { @@ -2379,7 +2466,7 @@ fieldset:disabled a.btn { } .btn-secondary:focus, .btn-secondary.focus { - box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5); + box-shadow: 0 0 0 0.2rem rgba(130, 138, 145, 0.5); } .btn-secondary.disabled, .btn-secondary:disabled { @@ -2397,7 +2484,7 @@ fieldset:disabled a.btn { .btn-secondary:not(:disabled):not(.disabled):active:focus, .btn-secondary:not(:disabled):not(.disabled).active:focus, .show > .btn-secondary.dropdown-toggle:focus { - box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5); + box-shadow: 0 0 0 0.2rem rgba(130, 138, 145, 0.5); } .btn-success { @@ -2413,7 +2500,7 @@ fieldset:disabled a.btn { } .btn-success:focus, .btn-success.focus { - box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(72, 180, 97, 0.5); } .btn-success.disabled, .btn-success:disabled { @@ -2431,7 +2518,7 @@ fieldset:disabled a.btn { .btn-success:not(:disabled):not(.disabled):active:focus, .btn-success:not(:disabled):not(.disabled).active:focus, .show > .btn-success.dropdown-toggle:focus { - box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(72, 180, 97, 0.5); } .btn-info { @@ -2447,7 +2534,7 @@ fieldset:disabled a.btn { } .btn-info:focus, .btn-info.focus { - box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); + box-shadow: 0 0 0 0.2rem rgba(58, 176, 195, 0.5); } .btn-info.disabled, .btn-info:disabled { @@ -2465,7 +2552,7 @@ fieldset:disabled a.btn { .btn-info:not(:disabled):not(.disabled):active:focus, .btn-info:not(:disabled):not(.disabled).active:focus, .show > .btn-info.dropdown-toggle:focus { - box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); + box-shadow: 0 0 0 0.2rem rgba(58, 176, 195, 0.5); } .btn-warning { @@ -2481,7 +2568,7 @@ fieldset:disabled a.btn { } .btn-warning:focus, .btn-warning.focus { - box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); + box-shadow: 0 0 0 0.2rem rgba(222, 170, 12, 0.5); } .btn-warning.disabled, .btn-warning:disabled { @@ -2499,7 +2586,7 @@ fieldset:disabled a.btn { .btn-warning:not(:disabled):not(.disabled):active:focus, .btn-warning:not(:disabled):not(.disabled).active:focus, .show > .btn-warning.dropdown-toggle:focus { - box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); + box-shadow: 0 0 0 0.2rem rgba(222, 170, 12, 0.5); } .btn-danger { @@ -2515,7 +2602,7 @@ fieldset:disabled a.btn { } .btn-danger:focus, .btn-danger.focus { - box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(225, 83, 97, 0.5); } .btn-danger.disabled, .btn-danger:disabled { @@ -2533,7 +2620,7 @@ fieldset:disabled a.btn { .btn-danger:not(:disabled):not(.disabled):active:focus, .btn-danger:not(:disabled):not(.disabled).active:focus, .show > .btn-danger.dropdown-toggle:focus { - box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); + box-shadow: 0 0 0 0.2rem rgba(225, 83, 97, 0.5); } .btn-light { @@ -2549,7 +2636,7 @@ fieldset:disabled a.btn { } .btn-light:focus, .btn-light.focus { - box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); + box-shadow: 0 0 0 0.2rem rgba(216, 217, 219, 0.5); } .btn-light.disabled, .btn-light:disabled { @@ -2567,7 +2654,7 @@ fieldset:disabled a.btn { .btn-light:not(:disabled):not(.disabled):active:focus, .btn-light:not(:disabled):not(.disabled).active:focus, .show > .btn-light.dropdown-toggle:focus { - box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); + box-shadow: 0 0 0 0.2rem rgba(216, 217, 219, 0.5); } .btn-dark { @@ -2583,7 +2670,7 @@ fieldset:disabled a.btn { } .btn-dark:focus, .btn-dark.focus { - box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); + box-shadow: 0 0 0 0.2rem rgba(82, 88, 93, 0.5); } .btn-dark.disabled, .btn-dark:disabled { @@ -2601,13 +2688,11 @@ fieldset:disabled a.btn { .btn-dark:not(:disabled):not(.disabled):active:focus, .btn-dark:not(:disabled):not(.disabled).active:focus, .show > .btn-dark.dropdown-toggle:focus { - box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); + box-shadow: 0 0 0 0.2rem rgba(82, 88, 93, 0.5); } .btn-outline-primary { color: #007bff; - background-color: transparent; - background-image: none; border-color: #007bff; } @@ -2640,8 +2725,6 @@ fieldset:disabled a.btn { .btn-outline-secondary { color: #6c757d; - background-color: transparent; - background-image: none; border-color: #6c757d; } @@ -2674,8 +2757,6 @@ fieldset:disabled a.btn { .btn-outline-success { color: #28a745; - background-color: transparent; - background-image: none; border-color: #28a745; } @@ -2708,8 +2789,6 @@ fieldset:disabled a.btn { .btn-outline-info { color: #17a2b8; - background-color: transparent; - background-image: none; border-color: #17a2b8; } @@ -2742,8 +2821,6 @@ fieldset:disabled a.btn { .btn-outline-warning { color: #ffc107; - background-color: transparent; - background-image: none; border-color: #ffc107; } @@ -2776,8 +2853,6 @@ fieldset:disabled a.btn { .btn-outline-danger { color: #dc3545; - background-color: transparent; - background-image: none; border-color: #dc3545; } @@ -2810,8 +2885,6 @@ fieldset:disabled a.btn { .btn-outline-light { color: #f8f9fa; - background-color: transparent; - background-image: none; border-color: #f8f9fa; } @@ -2844,8 +2917,6 @@ fieldset:disabled a.btn { .btn-outline-dark { color: #343a40; - background-color: transparent; - background-image: none; border-color: #343a40; } @@ -2879,19 +2950,16 @@ fieldset:disabled a.btn { .btn-link { font-weight: 400; color: #007bff; - background-color: transparent; + text-decoration: none; } .btn-link:hover { color: #0056b3; text-decoration: underline; - background-color: transparent; - border-color: transparent; } .btn-link:focus, .btn-link.focus { text-decoration: underline; - border-color: transparent; box-shadow: none; } @@ -2933,7 +3001,7 @@ input[type="button"].btn-block { transition: opacity 0.15s linear; } -@media screen and (prefers-reduced-motion: reduce) { +@media (prefers-reduced-motion: reduce) { .fade { transition: none; } @@ -2954,7 +3022,7 @@ input[type="button"].btn-block { transition: height 0.35s ease; } -@media screen and (prefers-reduced-motion: reduce) { +@media (prefers-reduced-motion: reduce) { .collapsing { transition: none; } @@ -2967,10 +3035,12 @@ input[type="button"].btn-block { position: relative; } +.dropdown-toggle { + white-space: nowrap; +} + .dropdown-toggle::after { display: inline-block; - width: 0; - height: 0; margin-left: 0.255em; vertical-align: 0.255em; content: ""; @@ -3004,11 +3074,60 @@ input[type="button"].btn-block { border-radius: 0.25rem; } +.dropdown-menu-left { + right: auto; + left: 0; +} + .dropdown-menu-right { right: 0; left: auto; } +@media (min-width: 576px) { + .dropdown-menu-sm-left { + right: auto; + left: 0; + } + .dropdown-menu-sm-right { + right: 0; + left: auto; + } +} + +@media (min-width: 768px) { + .dropdown-menu-md-left { + right: auto; + left: 0; + } + .dropdown-menu-md-right { + right: 0; + left: auto; + } +} + +@media (min-width: 992px) { + .dropdown-menu-lg-left { + right: auto; + left: 0; + } + .dropdown-menu-lg-right { + right: 0; + left: auto; + } +} + +@media (min-width: 1200px) { + .dropdown-menu-xl-left { + right: auto; + left: 0; + } + .dropdown-menu-xl-right { + right: 0; + left: auto; + } +} + .dropup .dropdown-menu { top: auto; bottom: 100%; @@ -3018,8 +3137,6 @@ input[type="button"].btn-block { .dropup .dropdown-toggle::after { display: inline-block; - width: 0; - height: 0; margin-left: 0.255em; vertical-align: 0.255em; content: ""; @@ -3043,8 +3160,6 @@ input[type="button"].btn-block { .dropright .dropdown-toggle::after { display: inline-block; - width: 0; - height: 0; margin-left: 0.255em; vertical-align: 0.255em; content: ""; @@ -3072,8 +3187,6 @@ input[type="button"].btn-block { .dropleft .dropdown-toggle::after { display: inline-block; - width: 0; - height: 0; margin-left: 0.255em; vertical-align: 0.255em; content: ""; @@ -3085,8 +3198,6 @@ input[type="button"].btn-block { .dropleft .dropdown-toggle::before { display: inline-block; - width: 0; - height: 0; margin-right: 0.255em; vertical-align: 0.255em; content: ""; @@ -3142,6 +3253,7 @@ input[type="button"].btn-block { .dropdown-item.disabled, .dropdown-item:disabled { color: #6c757d; + pointer-events: none; background-color: transparent; } @@ -3175,8 +3287,8 @@ input[type="button"].btn-block { .btn-group > .btn, .btn-group-vertical > .btn { position: relative; - -ms-flex: 0 1 auto; - flex: 0 1 auto; + -ms-flex: 1 1 auto; + flex: 1 1 auto; } .btn-group > .btn:hover, @@ -3191,17 +3303,6 @@ input[type="button"].btn-block { z-index: 1; } -.btn-group .btn + .btn, -.btn-group .btn + .btn-group, -.btn-group .btn-group + .btn, -.btn-group .btn-group + .btn-group, -.btn-group-vertical .btn + .btn, -.btn-group-vertical .btn + .btn-group, -.btn-group-vertical .btn-group + .btn, -.btn-group-vertical .btn-group + .btn-group { - margin-left: -1px; -} - .btn-toolbar { display: -ms-flexbox; display: flex; @@ -3215,8 +3316,9 @@ input[type="button"].btn-block { width: auto; } -.btn-group > .btn:first-child { - margin-left: 0; +.btn-group > .btn:not(:first-child), +.btn-group > .btn-group:not(:first-child) { + margin-left: -1px; } .btn-group > .btn:not(:last-child):not(.dropdown-toggle), @@ -3265,17 +3367,14 @@ input[type="button"].btn-block { justify-content: center; } -.btn-group-vertical .btn, -.btn-group-vertical .btn-group { +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group { width: 100%; } -.btn-group-vertical > .btn + .btn, -.btn-group-vertical > .btn + .btn-group, -.btn-group-vertical > .btn-group + .btn, -.btn-group-vertical > .btn-group + .btn-group { +.btn-group-vertical > .btn:not(:first-child), +.btn-group-vertical > .btn-group:not(:first-child) { margin-top: -1px; - margin-left: 0; } .btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle), @@ -3316,6 +3415,7 @@ input[type="button"].btn-block { } .input-group > .form-control, +.input-group > .form-control-plaintext, .input-group > .custom-select, .input-group > .custom-file { position: relative; @@ -3328,6 +3428,9 @@ input[type="button"].btn-block { .input-group > .form-control + .form-control, .input-group > .form-control + .custom-select, .input-group > .form-control + .custom-file, +.input-group > .form-control-plaintext + .form-control, +.input-group > .form-control-plaintext + .custom-select, +.input-group > .form-control-plaintext + .custom-file, .input-group > .custom-select + .form-control, .input-group > .custom-select + .custom-select, .input-group > .custom-select + .custom-file, @@ -3389,6 +3492,11 @@ input[type="button"].btn-block { z-index: 2; } +.input-group-prepend .btn:focus, +.input-group-append .btn:focus { + z-index: 3; +} + .input-group-prepend .btn + .btn, .input-group-prepend .btn + .input-group-text, .input-group-prepend .input-group-text + .input-group-text, @@ -3431,30 +3539,45 @@ input[type="button"].btn-block { margin-top: 0; } +.input-group-lg > .form-control:not(textarea), +.input-group-lg > .custom-select { + height: calc(1.5em + 1rem + 2px); +} + .input-group-lg > .form-control, +.input-group-lg > .custom-select, .input-group-lg > .input-group-prepend > .input-group-text, .input-group-lg > .input-group-append > .input-group-text, .input-group-lg > .input-group-prepend > .btn, .input-group-lg > .input-group-append > .btn { - height: calc(2.875rem + 2px); padding: 0.5rem 1rem; font-size: 1.25rem; line-height: 1.5; border-radius: 0.3rem; } +.input-group-sm > .form-control:not(textarea), +.input-group-sm > .custom-select { + height: calc(1.5em + 0.5rem + 2px); +} + .input-group-sm > .form-control, +.input-group-sm > .custom-select, .input-group-sm > .input-group-prepend > .input-group-text, .input-group-sm > .input-group-append > .input-group-text, .input-group-sm > .input-group-prepend > .btn, .input-group-sm > .input-group-append > .btn { - height: calc(1.8125rem + 2px); padding: 0.25rem 0.5rem; font-size: 0.875rem; line-height: 1.5; border-radius: 0.2rem; } +.input-group-lg > .custom-select, +.input-group-sm > .custom-select { + padding-right: 1.75rem; +} + .input-group > .input-group-prepend > .btn, .input-group > .input-group-prepend > .input-group-text, .input-group > .input-group-append:not(:last-child) > .btn, @@ -3496,16 +3619,22 @@ input[type="button"].btn-block { .custom-control-input:checked ~ .custom-control-label::before { color: #fff; + border-color: #007bff; background-color: #007bff; } .custom-control-input:focus ~ .custom-control-label::before { - box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +.custom-control-input:focus:not(:checked) ~ .custom-control-label::before { + border-color: #80bdff; } -.custom-control-input:active ~ .custom-control-label::before { +.custom-control-input:not(:disabled):active ~ .custom-control-label::before { color: #fff; background-color: #b3d7ff; + border-color: #b3d7ff; } .custom-control-input:disabled ~ .custom-control-label { @@ -3519,6 +3648,7 @@ input[type="button"].btn-block { .custom-control-label { position: relative; margin-bottom: 0; + vertical-align: top; } .custom-control-label::before { @@ -3530,11 +3660,8 @@ input[type="button"].btn-block { height: 1rem; pointer-events: none; content: ""; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - background-color: #dee2e6; + background-color: #fff; + border: #adb5bd solid 1px; } .custom-control-label::after { @@ -3545,29 +3672,24 @@ input[type="button"].btn-block { width: 1rem; height: 1rem; content: ""; - background-repeat: no-repeat; - background-position: center center; - background-size: 50% 50%; + background: no-repeat 50% / 50% 50%; } .custom-checkbox .custom-control-label::before { border-radius: 0.25rem; } -.custom-checkbox .custom-control-input:checked ~ .custom-control-label::before { - background-color: #007bff; -} - .custom-checkbox .custom-control-input:checked ~ .custom-control-label::after { - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e"); } .custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before { + border-color: #007bff; background-color: #007bff; } .custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after { - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E"); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3e%3cpath stroke='%23fff' d='M0 2h4'/%3e%3c/svg%3e"); } .custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label::before { @@ -3582,28 +3704,65 @@ input[type="button"].btn-block { border-radius: 50%; } -.custom-radio .custom-control-input:checked ~ .custom-control-label::before { - background-color: #007bff; -} - .custom-radio .custom-control-input:checked ~ .custom-control-label::after { - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E"); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e"); } .custom-radio .custom-control-input:disabled:checked ~ .custom-control-label::before { background-color: rgba(0, 123, 255, 0.5); } +.custom-switch { + padding-left: 2.25rem; +} + +.custom-switch .custom-control-label::before { + left: -2.25rem; + width: 1.75rem; + pointer-events: all; + border-radius: 0.5rem; +} + +.custom-switch .custom-control-label::after { + top: calc(0.25rem + 2px); + left: calc(-2.25rem + 2px); + width: calc(1rem - 4px); + height: calc(1rem - 4px); + background-color: #adb5bd; + border-radius: 0.5rem; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-transform 0.15s ease-in-out; + transition: transform 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + transition: transform 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out, -webkit-transform 0.15s ease-in-out; +} + +@media (prefers-reduced-motion: reduce) { + .custom-switch .custom-control-label::after { + transition: none; + } +} + +.custom-switch .custom-control-input:checked ~ .custom-control-label::after { + background-color: #fff; + -webkit-transform: translateX(0.75rem); + transform: translateX(0.75rem); +} + +.custom-switch .custom-control-input:disabled:checked ~ .custom-control-label::before { + background-color: rgba(0, 123, 255, 0.5); +} + .custom-select { display: inline-block; width: 100%; - height: calc(2.25rem + 2px); + height: calc(1.5em + 0.75rem + 2px); padding: 0.375rem 1.75rem 0.375rem 0.75rem; + font-size: 1rem; + font-weight: 400; line-height: 1.5; color: #495057; vertical-align: middle; - background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center; - background-size: 8px 10px; + background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px; + background-color: #fff; border: 1px solid #ced4da; border-radius: 0.25rem; -webkit-appearance: none; @@ -3614,7 +3773,7 @@ input[type="button"].btn-block { .custom-select:focus { border-color: #80bdff; outline: 0; - box-shadow: 0 0 0 0.2rem rgba(128, 189, 255, 0.5); + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } .custom-select:focus::-ms-value { @@ -3634,28 +3793,30 @@ input[type="button"].btn-block { } .custom-select::-ms-expand { - opacity: 0; + display: none; } .custom-select-sm { - height: calc(1.8125rem + 2px); - padding-top: 0.375rem; - padding-bottom: 0.375rem; - font-size: 75%; + height: calc(1.5em + 0.5rem + 2px); + padding-top: 0.25rem; + padding-bottom: 0.25rem; + padding-left: 0.5rem; + font-size: 0.875rem; } .custom-select-lg { - height: calc(2.875rem + 2px); - padding-top: 0.375rem; - padding-bottom: 0.375rem; - font-size: 125%; + height: calc(1.5em + 1rem + 2px); + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 1rem; + font-size: 1.25rem; } .custom-file { position: relative; display: inline-block; width: 100%; - height: calc(2.25rem + 2px); + height: calc(1.5em + 0.75rem + 2px); margin-bottom: 0; } @@ -3663,7 +3824,7 @@ input[type="button"].btn-block { position: relative; z-index: 2; width: 100%; - height: calc(2.25rem + 2px); + height: calc(1.5em + 0.75rem + 2px); margin: 0; opacity: 0; } @@ -3673,10 +3834,6 @@ input[type="button"].btn-block { box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } -.custom-file-input:focus ~ .custom-file-label::after { - border-color: #80bdff; -} - .custom-file-input:disabled ~ .custom-file-label { background-color: #e9ecef; } @@ -3685,14 +3842,19 @@ input[type="button"].btn-block { content: "Browse"; } +.custom-file-input ~ .custom-file-label[data-browse]::after { + content: attr(data-browse); +} + .custom-file-label { position: absolute; top: 0; right: 0; left: 0; z-index: 1; - height: calc(2.25rem + 2px); + height: calc(1.5em + 0.75rem + 2px); padding: 0.375rem 0.75rem; + font-weight: 400; line-height: 1.5; color: #495057; background-color: #fff; @@ -3707,19 +3869,20 @@ input[type="button"].btn-block { bottom: 0; z-index: 3; display: block; - height: 2.25rem; + height: calc(1.5em + 0.75rem); padding: 0.375rem 0.75rem; line-height: 1.5; color: #495057; content: "Browse"; background-color: #e9ecef; - border-left: 1px solid #ced4da; + border-left: inherit; border-radius: 0 0.25rem 0.25rem 0; } .custom-range { width: 100%; - padding-left: 0; + height: calc(1rem + 0.4rem); + padding: 0; background-color: transparent; -webkit-appearance: none; -moz-appearance: none; @@ -3758,7 +3921,7 @@ input[type="button"].btn-block { appearance: none; } -@media screen and (prefers-reduced-motion: reduce) { +@media (prefers-reduced-motion: reduce) { .custom-range::-webkit-slider-thumb { transition: none; } @@ -3789,7 +3952,7 @@ input[type="button"].btn-block { appearance: none; } -@media screen and (prefers-reduced-motion: reduce) { +@media (prefers-reduced-motion: reduce) { .custom-range::-moz-range-thumb { transition: none; } @@ -3822,7 +3985,7 @@ input[type="button"].btn-block { appearance: none; } -@media screen and (prefers-reduced-motion: reduce) { +@media (prefers-reduced-motion: reduce) { .custom-range::-ms-thumb { transition: none; } @@ -3853,13 +4016,33 @@ input[type="button"].btn-block { border-radius: 1rem; } +.custom-range:disabled::-webkit-slider-thumb { + background-color: #adb5bd; +} + +.custom-range:disabled::-webkit-slider-runnable-track { + cursor: default; +} + +.custom-range:disabled::-moz-range-thumb { + background-color: #adb5bd; +} + +.custom-range:disabled::-moz-range-track { + cursor: default; +} + +.custom-range:disabled::-ms-thumb { + background-color: #adb5bd; +} + .custom-control-label::before, .custom-file-label, .custom-select { transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; } -@media screen and (prefers-reduced-motion: reduce) { +@media (prefers-reduced-motion: reduce) { .custom-control-label::before, .custom-file-label, .custom-select { @@ -3888,6 +4071,8 @@ input[type="button"].btn-block { .nav-link.disabled { color: #6c757d; + pointer-events: none; + cursor: default; } .nav-tabs { @@ -4046,10 +4231,6 @@ input[type="button"].btn-block { text-decoration: none; } -.navbar-toggler:not(:disabled):not(.disabled) { - cursor: pointer; -} - .navbar-toggler-icon { display: inline-block; width: 1.5em; @@ -4305,7 +4486,7 @@ input[type="button"].btn-block { } .navbar-light .navbar-toggler-icon { - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); + background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); } .navbar-light .navbar-text { @@ -4353,7 +4534,7 @@ input[type="button"].btn-block { } .navbar-dark .navbar-toggler-icon { - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); + background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); } .navbar-dark .navbar-text { @@ -4543,52 +4724,30 @@ input[type="button"].btn-block { margin-left: 0; border-left: 0; } - .card-group > .card:first-child { + .card-group > .card:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; } - .card-group > .card:first-child .card-img-top, - .card-group > .card:first-child .card-header { + .card-group > .card:not(:last-child) .card-img-top, + .card-group > .card:not(:last-child) .card-header { border-top-right-radius: 0; } - .card-group > .card:first-child .card-img-bottom, - .card-group > .card:first-child .card-footer { + .card-group > .card:not(:last-child) .card-img-bottom, + .card-group > .card:not(:last-child) .card-footer { border-bottom-right-radius: 0; } - .card-group > .card:last-child { + .card-group > .card:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; } - .card-group > .card:last-child .card-img-top, - .card-group > .card:last-child .card-header { + .card-group > .card:not(:first-child) .card-img-top, + .card-group > .card:not(:first-child) .card-header { border-top-left-radius: 0; } - .card-group > .card:last-child .card-img-bottom, - .card-group > .card:last-child .card-footer { + .card-group > .card:not(:first-child) .card-img-bottom, + .card-group > .card:not(:first-child) .card-footer { border-bottom-left-radius: 0; } - .card-group > .card:only-child { - border-radius: 0.25rem; - } - .card-group > .card:only-child .card-img-top, - .card-group > .card:only-child .card-header { - border-top-left-radius: 0.25rem; - border-top-right-radius: 0.25rem; - } - .card-group > .card:only-child .card-img-bottom, - .card-group > .card:only-child .card-footer { - border-bottom-right-radius: 0.25rem; - border-bottom-left-radius: 0.25rem; - } - .card-group > .card:not(:first-child):not(:last-child):not(:only-child) { - border-radius: 0; - } - .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-img-top, - .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom, - .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-header, - .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-footer { - border-radius: 0; - } } .card-columns .card { @@ -4612,26 +4771,34 @@ input[type="button"].btn-block { } } -.accordion .card:not(:first-of-type):not(:last-of-type) { - border-bottom: 0; +.accordion > .card { + overflow: hidden; +} + +.accordion > .card:not(:first-of-type) .card-header:first-child { border-radius: 0; } -.accordion .card:not(:first-of-type) .card-header:first-child { +.accordion > .card:not(:first-of-type):not(:last-of-type) { + border-bottom: 0; border-radius: 0; } -.accordion .card:first-of-type { +.accordion > .card:first-of-type { border-bottom: 0; border-bottom-right-radius: 0; border-bottom-left-radius: 0; } -.accordion .card:last-of-type { +.accordion > .card:last-of-type { border-top-left-radius: 0; border-top-right-radius: 0; } +.accordion > .card .card-header { + margin-bottom: -1px; +} + .breadcrumb { display: -ms-flexbox; display: flex; @@ -4700,10 +4867,6 @@ input[type="button"].btn-block { box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); } -.page-link:not(:disabled):not(.disabled) { - cursor: pointer; -} - .page-item:first-child .page-link { margin-left: 0; border-top-left-radius: 0.25rem; @@ -4772,6 +4935,17 @@ input[type="button"].btn-block { white-space: nowrap; vertical-align: baseline; border-radius: 0.25rem; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +@media (prefers-reduced-motion: reduce) { + .badge { + transition: none; + } +} + +a.badge:hover, a.badge:focus { + text-decoration: none; } .badge:empty { @@ -4794,89 +4968,121 @@ input[type="button"].btn-block { background-color: #007bff; } -.badge-primary[href]:hover, .badge-primary[href]:focus { +a.badge-primary:hover, a.badge-primary:focus { color: #fff; - text-decoration: none; background-color: #0062cc; } +a.badge-primary:focus, a.badge-primary.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); +} + .badge-secondary { color: #fff; background-color: #6c757d; } -.badge-secondary[href]:hover, .badge-secondary[href]:focus { +a.badge-secondary:hover, a.badge-secondary:focus { color: #fff; - text-decoration: none; background-color: #545b62; } +a.badge-secondary:focus, a.badge-secondary.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5); +} + .badge-success { color: #fff; background-color: #28a745; } -.badge-success[href]:hover, .badge-success[href]:focus { +a.badge-success:hover, a.badge-success:focus { color: #fff; - text-decoration: none; background-color: #1e7e34; } +a.badge-success:focus, a.badge-success.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + .badge-info { color: #fff; background-color: #17a2b8; } -.badge-info[href]:hover, .badge-info[href]:focus { +a.badge-info:hover, a.badge-info:focus { color: #fff; - text-decoration: none; background-color: #117a8b; } +a.badge-info:focus, a.badge-info.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + .badge-warning { color: #212529; background-color: #ffc107; } -.badge-warning[href]:hover, .badge-warning[href]:focus { +a.badge-warning:hover, a.badge-warning:focus { color: #212529; - text-decoration: none; background-color: #d39e00; } +a.badge-warning:focus, a.badge-warning.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + .badge-danger { color: #fff; background-color: #dc3545; } -.badge-danger[href]:hover, .badge-danger[href]:focus { +a.badge-danger:hover, a.badge-danger:focus { color: #fff; - text-decoration: none; background-color: #bd2130; } +a.badge-danger:focus, a.badge-danger.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + .badge-light { color: #212529; background-color: #f8f9fa; } -.badge-light[href]:hover, .badge-light[href]:focus { +a.badge-light:hover, a.badge-light:focus { color: #212529; - text-decoration: none; background-color: #dae0e5; } +a.badge-light:focus, a.badge-light.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + .badge-dark { color: #fff; background-color: #343a40; } -.badge-dark[href]:hover, .badge-dark[href]:focus { +a.badge-dark:hover, a.badge-dark:focus { color: #fff; - text-decoration: none; background-color: #1d2124; } +a.badge-dark:focus, a.badge-dark.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + .jumbotron { padding: 2rem 1rem; margin-bottom: 2rem; @@ -5078,7 +5284,7 @@ input[type="button"].btn-block { transition: width 0.6s ease; } -@media screen and (prefers-reduced-motion: reduce) { +@media (prefers-reduced-motion: reduce) { .progress-bar { transition: none; } @@ -5094,6 +5300,13 @@ input[type="button"].btn-block { animation: progress-bar-stripes 1s linear infinite; } +@media (prefers-reduced-motion: reduce) { + .progress-bar-animated { + -webkit-animation: none; + animation: none; + } +} + .media { display: -ms-flexbox; display: flex; @@ -5122,6 +5335,7 @@ input[type="button"].btn-block { } .list-group-item-action:hover, .list-group-item-action:focus { + z-index: 1; color: #495057; text-decoration: none; background-color: #f8f9fa; @@ -5152,13 +5366,9 @@ input[type="button"].btn-block { border-bottom-left-radius: 0.25rem; } -.list-group-item:hover, .list-group-item:focus { - z-index: 1; - text-decoration: none; -} - .list-group-item.disabled, .list-group-item:disabled { color: #6c757d; + pointer-events: none; background-color: #fff; } @@ -5169,17 +5379,133 @@ input[type="button"].btn-block { border-color: #007bff; } +.list-group-horizontal { + -ms-flex-direction: row; + flex-direction: row; +} + +.list-group-horizontal .list-group-item { + margin-right: -1px; + margin-bottom: 0; +} + +.list-group-horizontal .list-group-item:first-child { + border-top-left-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; +} + +.list-group-horizontal .list-group-item:last-child { + margin-right: 0; + border-top-right-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0; +} + +@media (min-width: 576px) { + .list-group-horizontal-sm { + -ms-flex-direction: row; + flex-direction: row; + } + .list-group-horizontal-sm .list-group-item { + margin-right: -1px; + margin-bottom: 0; + } + .list-group-horizontal-sm .list-group-item:first-child { + border-top-left-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + .list-group-horizontal-sm .list-group-item:last-child { + margin-right: 0; + border-top-right-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } +} + +@media (min-width: 768px) { + .list-group-horizontal-md { + -ms-flex-direction: row; + flex-direction: row; + } + .list-group-horizontal-md .list-group-item { + margin-right: -1px; + margin-bottom: 0; + } + .list-group-horizontal-md .list-group-item:first-child { + border-top-left-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + .list-group-horizontal-md .list-group-item:last-child { + margin-right: 0; + border-top-right-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } +} + +@media (min-width: 992px) { + .list-group-horizontal-lg { + -ms-flex-direction: row; + flex-direction: row; + } + .list-group-horizontal-lg .list-group-item { + margin-right: -1px; + margin-bottom: 0; + } + .list-group-horizontal-lg .list-group-item:first-child { + border-top-left-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + .list-group-horizontal-lg .list-group-item:last-child { + margin-right: 0; + border-top-right-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } +} + +@media (min-width: 1200px) { + .list-group-horizontal-xl { + -ms-flex-direction: row; + flex-direction: row; + } + .list-group-horizontal-xl .list-group-item { + margin-right: -1px; + margin-bottom: 0; + } + .list-group-horizontal-xl .list-group-item:first-child { + border-top-left-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; + border-top-right-radius: 0; + } + .list-group-horizontal-xl .list-group-item:last-child { + margin-right: 0; + border-top-right-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0; + } +} + .list-group-flush .list-group-item { border-right: 0; border-left: 0; border-radius: 0; } +.list-group-flush .list-group-item:last-child { + margin-bottom: -1px; +} + .list-group-flush:first-child .list-group-item:first-child { border-top: 0; } .list-group-flush:last-child .list-group-item:last-child { + margin-bottom: 0; border-bottom: 0; } @@ -5321,13 +5647,12 @@ input[type="button"].btn-block { opacity: .5; } -.close:not(:disabled):not(.disabled) { - cursor: pointer; +.close:hover { + color: #000; + text-decoration: none; } .close:not(:disabled):not(.disabled):hover, .close:not(:disabled):not(.disabled):focus { - color: #000; - text-decoration: none; opacity: .75; } @@ -5336,6 +5661,59 @@ button.close { background-color: transparent; border: 0; -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +a.close.disabled { + pointer-events: none; +} + +.toast { + max-width: 350px; + overflow: hidden; + font-size: 0.875rem; + background-color: rgba(255, 255, 255, 0.85); + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.1); + box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.1); + -webkit-backdrop-filter: blur(10px); + backdrop-filter: blur(10px); + opacity: 0; + border-radius: 0.25rem; +} + +.toast:not(:last-child) { + margin-bottom: 0.75rem; +} + +.toast.showing { + opacity: 1; +} + +.toast.show { + display: block; + opacity: 1; +} + +.toast.hide { + display: none; +} + +.toast-header { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + padding: 0.25rem 0.75rem; + color: #6c757d; + background-color: rgba(255, 255, 255, 0.85); + background-clip: padding-box; + border-bottom: 1px solid rgba(0, 0, 0, 0.05); +} + +.toast-body { + padding: 0.75rem; } .modal-open { @@ -5350,11 +5728,11 @@ button.close { .modal { position: fixed; top: 0; - right: 0; - bottom: 0; left: 0; z-index: 1050; display: none; + width: 100%; + height: 100%; overflow: hidden; outline: 0; } @@ -5370,19 +5748,40 @@ button.close { transition: -webkit-transform 0.3s ease-out; transition: transform 0.3s ease-out; transition: transform 0.3s ease-out, -webkit-transform 0.3s ease-out; - -webkit-transform: translate(0, -25%); - transform: translate(0, -25%); + -webkit-transform: translate(0, -50px); + transform: translate(0, -50px); } -@media screen and (prefers-reduced-motion: reduce) { +@media (prefers-reduced-motion: reduce) { .modal.fade .modal-dialog { transition: none; } } .modal.show .modal-dialog { - -webkit-transform: translate(0, 0); - transform: translate(0, 0); + -webkit-transform: none; + transform: none; +} + +.modal-dialog-scrollable { + display: -ms-flexbox; + display: flex; + max-height: calc(100% - 1rem); +} + +.modal-dialog-scrollable .modal-content { + max-height: calc(100vh - 1rem); + overflow: hidden; +} + +.modal-dialog-scrollable .modal-header, +.modal-dialog-scrollable .modal-footer { + -ms-flex-negative: 0; + flex-shrink: 0; +} + +.modal-dialog-scrollable .modal-body { + overflow-y: auto; } .modal-dialog-centered { @@ -5390,15 +5789,31 @@ button.close { display: flex; -ms-flex-align: center; align-items: center; - min-height: calc(100% - (0.5rem * 2)); + min-height: calc(100% - 1rem); } .modal-dialog-centered::before { display: block; - height: calc(100vh - (0.5rem * 2)); + height: calc(100vh - 1rem); content: ""; } +.modal-dialog-centered.modal-dialog-scrollable { + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-pack: center; + justify-content: center; + height: 100%; +} + +.modal-dialog-centered.modal-dialog-scrollable .modal-content { + max-height: none; +} + +.modal-dialog-centered.modal-dialog-scrollable::before { + content: none; +} + .modal-content { position: relative; display: -ms-flexbox; @@ -5417,10 +5832,10 @@ button.close { .modal-backdrop { position: fixed; top: 0; - right: 0; - bottom: 0; left: 0; z-index: 1040; + width: 100vw; + height: 100vh; background-color: #000; } @@ -5439,14 +5854,14 @@ button.close { align-items: flex-start; -ms-flex-pack: justify; justify-content: space-between; - padding: 1rem; - border-bottom: 1px solid #e9ecef; + padding: 1rem 1rem; + border-bottom: 1px solid #dee2e6; border-top-left-radius: 0.3rem; border-top-right-radius: 0.3rem; } .modal-header .close { - padding: 1rem; + padding: 1rem 1rem; margin: -1rem -1rem -1rem auto; } @@ -5470,7 +5885,9 @@ button.close { -ms-flex-pack: end; justify-content: flex-end; padding: 1rem; - border-top: 1px solid #e9ecef; + border-top: 1px solid #dee2e6; + border-bottom-right-radius: 0.3rem; + border-bottom-left-radius: 0.3rem; } .modal-footer > :not(:first-child) { @@ -5494,11 +5911,17 @@ button.close { max-width: 500px; margin: 1.75rem auto; } + .modal-dialog-scrollable { + max-height: calc(100% - 3.5rem); + } + .modal-dialog-scrollable .modal-content { + max-height: calc(100vh - 3.5rem); + } .modal-dialog-centered { - min-height: calc(100% - (1.75rem * 2)); + min-height: calc(100% - 3.5rem); } .modal-dialog-centered::before { - height: calc(100vh - (1.75rem * 2)); + height: calc(100vh - 3.5rem); } .modal-sm { max-width: 300px; @@ -5506,17 +5929,24 @@ button.close { } @media (min-width: 992px) { - .modal-lg { + .modal-lg, + .modal-xl { max-width: 800px; } } +@media (min-width: 1200px) { + .modal-xl { + max-width: 1140px; + } +} + .tooltip { position: absolute; z-index: 1070; display: block; margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-style: normal; font-weight: 400; line-height: 1.5; @@ -5629,7 +6059,7 @@ button.close { z-index: 1060; display: block; max-width: 276px; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-style: normal; font-weight: 400; line-height: 1.5; @@ -5671,25 +6101,19 @@ button.close { margin-bottom: 0.5rem; } -.bs-popover-top .arrow, .bs-popover-auto[x-placement^="top"] .arrow { +.bs-popover-top > .arrow, .bs-popover-auto[x-placement^="top"] > .arrow { bottom: calc((0.5rem + 1px) * -1); } -.bs-popover-top .arrow::before, .bs-popover-auto[x-placement^="top"] .arrow::before, -.bs-popover-top .arrow::after, -.bs-popover-auto[x-placement^="top"] .arrow::after { - border-width: 0.5rem 0.5rem 0; -} - -.bs-popover-top .arrow::before, .bs-popover-auto[x-placement^="top"] .arrow::before { +.bs-popover-top > .arrow::before, .bs-popover-auto[x-placement^="top"] > .arrow::before { bottom: 0; + border-width: 0.5rem 0.5rem 0; border-top-color: rgba(0, 0, 0, 0.25); } - -.bs-popover-top .arrow::after, -.bs-popover-auto[x-placement^="top"] .arrow::after { +.bs-popover-top > .arrow::after, .bs-popover-auto[x-placement^="top"] > .arrow::after { bottom: 1px; + border-width: 0.5rem 0.5rem 0; border-top-color: #fff; } @@ -5697,28 +6121,22 @@ button.close { margin-left: 0.5rem; } -.bs-popover-right .arrow, .bs-popover-auto[x-placement^="right"] .arrow { +.bs-popover-right > .arrow, .bs-popover-auto[x-placement^="right"] > .arrow { left: calc((0.5rem + 1px) * -1); width: 0.5rem; height: 1rem; margin: 0.3rem 0; } -.bs-popover-right .arrow::before, .bs-popover-auto[x-placement^="right"] .arrow::before, -.bs-popover-right .arrow::after, -.bs-popover-auto[x-placement^="right"] .arrow::after { - border-width: 0.5rem 0.5rem 0.5rem 0; -} - -.bs-popover-right .arrow::before, .bs-popover-auto[x-placement^="right"] .arrow::before { +.bs-popover-right > .arrow::before, .bs-popover-auto[x-placement^="right"] > .arrow::before { left: 0; + border-width: 0.5rem 0.5rem 0.5rem 0; border-right-color: rgba(0, 0, 0, 0.25); } - -.bs-popover-right .arrow::after, -.bs-popover-auto[x-placement^="right"] .arrow::after { +.bs-popover-right > .arrow::after, .bs-popover-auto[x-placement^="right"] > .arrow::after { left: 1px; + border-width: 0.5rem 0.5rem 0.5rem 0; border-right-color: #fff; } @@ -5726,25 +6144,19 @@ button.close { margin-top: 0.5rem; } -.bs-popover-bottom .arrow, .bs-popover-auto[x-placement^="bottom"] .arrow { +.bs-popover-bottom > .arrow, .bs-popover-auto[x-placement^="bottom"] > .arrow { top: calc((0.5rem + 1px) * -1); } -.bs-popover-bottom .arrow::before, .bs-popover-auto[x-placement^="bottom"] .arrow::before, -.bs-popover-bottom .arrow::after, -.bs-popover-auto[x-placement^="bottom"] .arrow::after { - border-width: 0 0.5rem 0.5rem 0.5rem; -} - -.bs-popover-bottom .arrow::before, .bs-popover-auto[x-placement^="bottom"] .arrow::before { +.bs-popover-bottom > .arrow::before, .bs-popover-auto[x-placement^="bottom"] > .arrow::before { top: 0; + border-width: 0 0.5rem 0.5rem 0.5rem; border-bottom-color: rgba(0, 0, 0, 0.25); } - -.bs-popover-bottom .arrow::after, -.bs-popover-auto[x-placement^="bottom"] .arrow::after { +.bs-popover-bottom > .arrow::after, .bs-popover-auto[x-placement^="bottom"] > .arrow::after { top: 1px; + border-width: 0 0.5rem 0.5rem 0.5rem; border-bottom-color: #fff; } @@ -5763,28 +6175,22 @@ button.close { margin-right: 0.5rem; } -.bs-popover-left .arrow, .bs-popover-auto[x-placement^="left"] .arrow { +.bs-popover-left > .arrow, .bs-popover-auto[x-placement^="left"] > .arrow { right: calc((0.5rem + 1px) * -1); width: 0.5rem; height: 1rem; margin: 0.3rem 0; } -.bs-popover-left .arrow::before, .bs-popover-auto[x-placement^="left"] .arrow::before, -.bs-popover-left .arrow::after, -.bs-popover-auto[x-placement^="left"] .arrow::after { - border-width: 0.5rem 0 0.5rem 0.5rem; -} - -.bs-popover-left .arrow::before, .bs-popover-auto[x-placement^="left"] .arrow::before { +.bs-popover-left > .arrow::before, .bs-popover-auto[x-placement^="left"] > .arrow::before { right: 0; + border-width: 0.5rem 0 0.5rem 0.5rem; border-left-color: rgba(0, 0, 0, 0.25); } - -.bs-popover-left .arrow::after, -.bs-popover-auto[x-placement^="left"] .arrow::after { +.bs-popover-left > .arrow::after, .bs-popover-auto[x-placement^="left"] > .arrow::after { right: 1px; + border-width: 0.5rem 0 0.5rem 0.5rem; border-left-color: #fff; } @@ -5792,7 +6198,6 @@ button.close { padding: 0.5rem 0.75rem; margin-bottom: 0; font-size: 1rem; - color: inherit; background-color: #f7f7f7; border-bottom: 1px solid #ebebeb; border-top-left-radius: calc(0.3rem - 1px); @@ -5812,123 +6217,85 @@ button.close { position: relative; } +.carousel.pointer-event { + -ms-touch-action: pan-y; + touch-action: pan-y; +} + .carousel-inner { position: relative; width: 100%; overflow: hidden; } +.carousel-inner::after { + display: block; + clear: both; + content: ""; +} + .carousel-item { position: relative; display: none; - -ms-flex-align: center; - align-items: center; + float: left; width: 100%; + margin-right: -100%; -webkit-backface-visibility: hidden; backface-visibility: hidden; - -webkit-perspective: 1000px; - perspective: 1000px; + transition: -webkit-transform 0.6s ease-in-out; + transition: transform 0.6s ease-in-out; + transition: transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out; } -.carousel-item.active, -.carousel-item-next, -.carousel-item-prev { - display: block; - transition: -webkit-transform 0.6s ease; - transition: transform 0.6s ease; - transition: transform 0.6s ease, -webkit-transform 0.6s ease; -} - -@media screen and (prefers-reduced-motion: reduce) { - .carousel-item.active, - .carousel-item-next, - .carousel-item-prev { +@media (prefers-reduced-motion: reduce) { + .carousel-item { transition: none; } } +.carousel-item.active, .carousel-item-next, .carousel-item-prev { - position: absolute; - top: 0; -} - -.carousel-item-next.carousel-item-left, -.carousel-item-prev.carousel-item-right { - -webkit-transform: translateX(0); - transform: translateX(0); -} - -@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) { - .carousel-item-next.carousel-item-left, - .carousel-item-prev.carousel-item-right { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } + display: block; } -.carousel-item-next, +.carousel-item-next:not(.carousel-item-left), .active.carousel-item-right { -webkit-transform: translateX(100%); transform: translateX(100%); } -@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) { - .carousel-item-next, - .active.carousel-item-right { - -webkit-transform: translate3d(100%, 0, 0); - transform: translate3d(100%, 0, 0); - } -} - -.carousel-item-prev, +.carousel-item-prev:not(.carousel-item-right), .active.carousel-item-left { -webkit-transform: translateX(-100%); transform: translateX(-100%); } -@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) { - .carousel-item-prev, - .active.carousel-item-left { - -webkit-transform: translate3d(-100%, 0, 0); - transform: translate3d(-100%, 0, 0); - } -} - .carousel-fade .carousel-item { opacity: 0; - transition-duration: .6s; transition-property: opacity; + -webkit-transform: none; + transform: none; } .carousel-fade .carousel-item.active, .carousel-fade .carousel-item-next.carousel-item-left, .carousel-fade .carousel-item-prev.carousel-item-right { + z-index: 1; opacity: 1; } .carousel-fade .active.carousel-item-left, -.carousel-fade .active.carousel-item-right { - opacity: 0; -} - -.carousel-fade .carousel-item-next, -.carousel-fade .carousel-item-prev, -.carousel-fade .carousel-item.active, -.carousel-fade .active.carousel-item-left, -.carousel-fade .active.carousel-item-prev { - -webkit-transform: translateX(0); - transform: translateX(0); +.carousel-fade .active.carousel-item-right { + z-index: 0; + opacity: 0; + transition: 0s 0.6s opacity; } -@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) { - .carousel-fade .carousel-item-next, - .carousel-fade .carousel-item-prev, - .carousel-fade .carousel-item.active, +@media (prefers-reduced-motion: reduce) { .carousel-fade .active.carousel-item-left, - .carousel-fade .active.carousel-item-prev { - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); + .carousel-fade .active.carousel-item-right { + transition: none; } } @@ -5937,6 +6304,7 @@ button.close { position: absolute; top: 0; bottom: 0; + z-index: 1; display: -ms-flexbox; display: flex; -ms-flex-align: center; @@ -5947,6 +6315,14 @@ button.close { color: #fff; text-align: center; opacity: 0.5; + transition: opacity 0.15s ease; +} + +@media (prefers-reduced-motion: reduce) { + .carousel-control-prev, + .carousel-control-next { + transition: none; + } } .carousel-control-prev:hover, .carousel-control-prev:focus, @@ -5955,7 +6331,7 @@ button.close { color: #fff; text-decoration: none; outline: 0; - opacity: .9; + opacity: 0.9; } .carousel-control-prev { @@ -5971,22 +6347,21 @@ button.close { display: inline-block; width: 20px; height: 20px; - background: transparent no-repeat center center; - background-size: 100% 100%; + background: no-repeat 50% / 100% 100%; } .carousel-control-prev-icon { - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E"); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3e%3c/svg%3e"); } .carousel-control-next-icon { - background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E"); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3e%3c/svg%3e"); } .carousel-indicators { position: absolute; right: 0; - bottom: 10px; + bottom: 0; left: 0; z-index: 15; display: -ms-flexbox; @@ -6000,7 +6375,7 @@ button.close { } .carousel-indicators li { - position: relative; + box-sizing: content-box; -ms-flex: 0 1 auto; flex: 0 1 auto; width: 30px; @@ -6009,31 +6384,22 @@ button.close { margin-left: 3px; text-indent: -999px; cursor: pointer; - background-color: rgba(255, 255, 255, 0.5); -} - -.carousel-indicators li::before { - position: absolute; - top: -10px; - left: 0; - display: inline-block; - width: 100%; - height: 10px; - content: ""; + background-color: #fff; + background-clip: padding-box; + border-top: 10px solid transparent; + border-bottom: 10px solid transparent; + opacity: .5; + transition: opacity 0.6s ease; } -.carousel-indicators li::after { - position: absolute; - bottom: -10px; - left: 0; - display: inline-block; - width: 100%; - height: 10px; - content: ""; +@media (prefers-reduced-motion: reduce) { + .carousel-indicators li { + transition: none; + } } .carousel-indicators .active { - background-color: #fff; + opacity: 1; } .carousel-caption { @@ -6048,6 +6414,75 @@ button.close { text-align: center; } +@-webkit-keyframes spinner-border { + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes spinner-border { + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +.spinner-border { + display: inline-block; + width: 2rem; + height: 2rem; + vertical-align: text-bottom; + border: 0.25em solid currentColor; + border-right-color: transparent; + border-radius: 50%; + -webkit-animation: spinner-border .75s linear infinite; + animation: spinner-border .75s linear infinite; +} + +.spinner-border-sm { + width: 1rem; + height: 1rem; + border-width: 0.2em; +} + +@-webkit-keyframes spinner-grow { + 0% { + -webkit-transform: scale(0); + transform: scale(0); + } + 50% { + opacity: 1; + } +} + +@keyframes spinner-grow { + 0% { + -webkit-transform: scale(0); + transform: scale(0); + } + 50% { + opacity: 1; + } +} + +.spinner-grow { + display: inline-block; + width: 2rem; + height: 2rem; + vertical-align: text-bottom; + background-color: currentColor; + border-radius: 50%; + opacity: 0; + -webkit-animation: spinner-grow .75s linear infinite; + animation: spinner-grow .75s linear infinite; +} + +.spinner-grow-sm { + width: 1rem; + height: 1rem; +} + .align-baseline { vertical-align: baseline !important; } @@ -6236,6 +6671,10 @@ button.bg-dark:focus { border-color: #fff !important; } +.rounded-sm { + border-radius: 0.2rem !important; +} + .rounded { border-radius: 0.25rem !important; } @@ -6260,10 +6699,18 @@ button.bg-dark:focus { border-bottom-left-radius: 0.25rem !important; } +.rounded-lg { + border-radius: 0.3rem !important; +} + .rounded-circle { border-radius: 50% !important; } +.rounded-pill { + border-radius: 50rem !important; +} + .rounded-0 { border-radius: 0 !important; } @@ -7301,6 +7748,14 @@ button.bg-dark:focus { } } +.overflow-auto { + overflow: auto !important; +} + +.overflow-hidden { + overflow: hidden !important; +} + .position-static { position: static !important; } @@ -7431,6 +7886,34 @@ button.bg-dark:focus { max-height: 100% !important; } +.min-vw-100 { + min-width: 100vw !important; +} + +.min-vh-100 { + min-height: 100vh !important; +} + +.vw-100 { + width: 100vw !important; +} + +.vh-100 { + height: 100vh !important; +} + +.stretched-link::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1; + pointer-events: auto; + content: ""; + background-color: rgba(0, 0, 0, 0); +} + .m-0 { margin: 0 !important; } @@ -7719,6 +8202,126 @@ button.bg-dark:focus { padding-left: 3rem !important; } +.m-n1 { + margin: -0.25rem !important; +} + +.mt-n1, +.my-n1 { + margin-top: -0.25rem !important; +} + +.mr-n1, +.mx-n1 { + margin-right: -0.25rem !important; +} + +.mb-n1, +.my-n1 { + margin-bottom: -0.25rem !important; +} + +.ml-n1, +.mx-n1 { + margin-left: -0.25rem !important; +} + +.m-n2 { + margin: -0.5rem !important; +} + +.mt-n2, +.my-n2 { + margin-top: -0.5rem !important; +} + +.mr-n2, +.mx-n2 { + margin-right: -0.5rem !important; +} + +.mb-n2, +.my-n2 { + margin-bottom: -0.5rem !important; +} + +.ml-n2, +.mx-n2 { + margin-left: -0.5rem !important; +} + +.m-n3 { + margin: -1rem !important; +} + +.mt-n3, +.my-n3 { + margin-top: -1rem !important; +} + +.mr-n3, +.mx-n3 { + margin-right: -1rem !important; +} + +.mb-n3, +.my-n3 { + margin-bottom: -1rem !important; +} + +.ml-n3, +.mx-n3 { + margin-left: -1rem !important; +} + +.m-n4 { + margin: -1.5rem !important; +} + +.mt-n4, +.my-n4 { + margin-top: -1.5rem !important; +} + +.mr-n4, +.mx-n4 { + margin-right: -1.5rem !important; +} + +.mb-n4, +.my-n4 { + margin-bottom: -1.5rem !important; +} + +.ml-n4, +.mx-n4 { + margin-left: -1.5rem !important; +} + +.m-n5 { + margin: -3rem !important; +} + +.mt-n5, +.my-n5 { + margin-top: -3rem !important; +} + +.mr-n5, +.mx-n5 { + margin-right: -3rem !important; +} + +.mb-n5, +.my-n5 { + margin-bottom: -3rem !important; +} + +.ml-n5, +.mx-n5 { + margin-left: -3rem !important; +} + .m-auto { margin: auto !important; } @@ -7972,6 +8575,101 @@ button.bg-dark:focus { .px-sm-5 { padding-left: 3rem !important; } + .m-sm-n1 { + margin: -0.25rem !important; + } + .mt-sm-n1, + .my-sm-n1 { + margin-top: -0.25rem !important; + } + .mr-sm-n1, + .mx-sm-n1 { + margin-right: -0.25rem !important; + } + .mb-sm-n1, + .my-sm-n1 { + margin-bottom: -0.25rem !important; + } + .ml-sm-n1, + .mx-sm-n1 { + margin-left: -0.25rem !important; + } + .m-sm-n2 { + margin: -0.5rem !important; + } + .mt-sm-n2, + .my-sm-n2 { + margin-top: -0.5rem !important; + } + .mr-sm-n2, + .mx-sm-n2 { + margin-right: -0.5rem !important; + } + .mb-sm-n2, + .my-sm-n2 { + margin-bottom: -0.5rem !important; + } + .ml-sm-n2, + .mx-sm-n2 { + margin-left: -0.5rem !important; + } + .m-sm-n3 { + margin: -1rem !important; + } + .mt-sm-n3, + .my-sm-n3 { + margin-top: -1rem !important; + } + .mr-sm-n3, + .mx-sm-n3 { + margin-right: -1rem !important; + } + .mb-sm-n3, + .my-sm-n3 { + margin-bottom: -1rem !important; + } + .ml-sm-n3, + .mx-sm-n3 { + margin-left: -1rem !important; + } + .m-sm-n4 { + margin: -1.5rem !important; + } + .mt-sm-n4, + .my-sm-n4 { + margin-top: -1.5rem !important; + } + .mr-sm-n4, + .mx-sm-n4 { + margin-right: -1.5rem !important; + } + .mb-sm-n4, + .my-sm-n4 { + margin-bottom: -1.5rem !important; + } + .ml-sm-n4, + .mx-sm-n4 { + margin-left: -1.5rem !important; + } + .m-sm-n5 { + margin: -3rem !important; + } + .mt-sm-n5, + .my-sm-n5 { + margin-top: -3rem !important; + } + .mr-sm-n5, + .mx-sm-n5 { + margin-right: -3rem !important; + } + .mb-sm-n5, + .my-sm-n5 { + margin-bottom: -3rem !important; + } + .ml-sm-n5, + .mx-sm-n5 { + margin-left: -3rem !important; + } .m-sm-auto { margin: auto !important; } @@ -8222,6 +8920,101 @@ button.bg-dark:focus { .px-md-5 { padding-left: 3rem !important; } + .m-md-n1 { + margin: -0.25rem !important; + } + .mt-md-n1, + .my-md-n1 { + margin-top: -0.25rem !important; + } + .mr-md-n1, + .mx-md-n1 { + margin-right: -0.25rem !important; + } + .mb-md-n1, + .my-md-n1 { + margin-bottom: -0.25rem !important; + } + .ml-md-n1, + .mx-md-n1 { + margin-left: -0.25rem !important; + } + .m-md-n2 { + margin: -0.5rem !important; + } + .mt-md-n2, + .my-md-n2 { + margin-top: -0.5rem !important; + } + .mr-md-n2, + .mx-md-n2 { + margin-right: -0.5rem !important; + } + .mb-md-n2, + .my-md-n2 { + margin-bottom: -0.5rem !important; + } + .ml-md-n2, + .mx-md-n2 { + margin-left: -0.5rem !important; + } + .m-md-n3 { + margin: -1rem !important; + } + .mt-md-n3, + .my-md-n3 { + margin-top: -1rem !important; + } + .mr-md-n3, + .mx-md-n3 { + margin-right: -1rem !important; + } + .mb-md-n3, + .my-md-n3 { + margin-bottom: -1rem !important; + } + .ml-md-n3, + .mx-md-n3 { + margin-left: -1rem !important; + } + .m-md-n4 { + margin: -1.5rem !important; + } + .mt-md-n4, + .my-md-n4 { + margin-top: -1.5rem !important; + } + .mr-md-n4, + .mx-md-n4 { + margin-right: -1.5rem !important; + } + .mb-md-n4, + .my-md-n4 { + margin-bottom: -1.5rem !important; + } + .ml-md-n4, + .mx-md-n4 { + margin-left: -1.5rem !important; + } + .m-md-n5 { + margin: -3rem !important; + } + .mt-md-n5, + .my-md-n5 { + margin-top: -3rem !important; + } + .mr-md-n5, + .mx-md-n5 { + margin-right: -3rem !important; + } + .mb-md-n5, + .my-md-n5 { + margin-bottom: -3rem !important; + } + .ml-md-n5, + .mx-md-n5 { + margin-left: -3rem !important; + } .m-md-auto { margin: auto !important; } @@ -8472,6 +9265,101 @@ button.bg-dark:focus { .px-lg-5 { padding-left: 3rem !important; } + .m-lg-n1 { + margin: -0.25rem !important; + } + .mt-lg-n1, + .my-lg-n1 { + margin-top: -0.25rem !important; + } + .mr-lg-n1, + .mx-lg-n1 { + margin-right: -0.25rem !important; + } + .mb-lg-n1, + .my-lg-n1 { + margin-bottom: -0.25rem !important; + } + .ml-lg-n1, + .mx-lg-n1 { + margin-left: -0.25rem !important; + } + .m-lg-n2 { + margin: -0.5rem !important; + } + .mt-lg-n2, + .my-lg-n2 { + margin-top: -0.5rem !important; + } + .mr-lg-n2, + .mx-lg-n2 { + margin-right: -0.5rem !important; + } + .mb-lg-n2, + .my-lg-n2 { + margin-bottom: -0.5rem !important; + } + .ml-lg-n2, + .mx-lg-n2 { + margin-left: -0.5rem !important; + } + .m-lg-n3 { + margin: -1rem !important; + } + .mt-lg-n3, + .my-lg-n3 { + margin-top: -1rem !important; + } + .mr-lg-n3, + .mx-lg-n3 { + margin-right: -1rem !important; + } + .mb-lg-n3, + .my-lg-n3 { + margin-bottom: -1rem !important; + } + .ml-lg-n3, + .mx-lg-n3 { + margin-left: -1rem !important; + } + .m-lg-n4 { + margin: -1.5rem !important; + } + .mt-lg-n4, + .my-lg-n4 { + margin-top: -1.5rem !important; + } + .mr-lg-n4, + .mx-lg-n4 { + margin-right: -1.5rem !important; + } + .mb-lg-n4, + .my-lg-n4 { + margin-bottom: -1.5rem !important; + } + .ml-lg-n4, + .mx-lg-n4 { + margin-left: -1.5rem !important; + } + .m-lg-n5 { + margin: -3rem !important; + } + .mt-lg-n5, + .my-lg-n5 { + margin-top: -3rem !important; + } + .mr-lg-n5, + .mx-lg-n5 { + margin-right: -3rem !important; + } + .mb-lg-n5, + .my-lg-n5 { + margin-bottom: -3rem !important; + } + .ml-lg-n5, + .mx-lg-n5 { + margin-left: -3rem !important; + } .m-lg-auto { margin: auto !important; } @@ -8722,6 +9610,101 @@ button.bg-dark:focus { .px-xl-5 { padding-left: 3rem !important; } + .m-xl-n1 { + margin: -0.25rem !important; + } + .mt-xl-n1, + .my-xl-n1 { + margin-top: -0.25rem !important; + } + .mr-xl-n1, + .mx-xl-n1 { + margin-right: -0.25rem !important; + } + .mb-xl-n1, + .my-xl-n1 { + margin-bottom: -0.25rem !important; + } + .ml-xl-n1, + .mx-xl-n1 { + margin-left: -0.25rem !important; + } + .m-xl-n2 { + margin: -0.5rem !important; + } + .mt-xl-n2, + .my-xl-n2 { + margin-top: -0.5rem !important; + } + .mr-xl-n2, + .mx-xl-n2 { + margin-right: -0.5rem !important; + } + .mb-xl-n2, + .my-xl-n2 { + margin-bottom: -0.5rem !important; + } + .ml-xl-n2, + .mx-xl-n2 { + margin-left: -0.5rem !important; + } + .m-xl-n3 { + margin: -1rem !important; + } + .mt-xl-n3, + .my-xl-n3 { + margin-top: -1rem !important; + } + .mr-xl-n3, + .mx-xl-n3 { + margin-right: -1rem !important; + } + .mb-xl-n3, + .my-xl-n3 { + margin-bottom: -1rem !important; + } + .ml-xl-n3, + .mx-xl-n3 { + margin-left: -1rem !important; + } + .m-xl-n4 { + margin: -1.5rem !important; + } + .mt-xl-n4, + .my-xl-n4 { + margin-top: -1.5rem !important; + } + .mr-xl-n4, + .mx-xl-n4 { + margin-right: -1.5rem !important; + } + .mb-xl-n4, + .my-xl-n4 { + margin-bottom: -1.5rem !important; + } + .ml-xl-n4, + .mx-xl-n4 { + margin-left: -1.5rem !important; + } + .m-xl-n5 { + margin: -3rem !important; + } + .mt-xl-n5, + .my-xl-n5 { + margin-top: -3rem !important; + } + .mr-xl-n5, + .mx-xl-n5 { + margin-right: -3rem !important; + } + .mb-xl-n5, + .my-xl-n5 { + margin-bottom: -3rem !important; + } + .ml-xl-n5, + .mx-xl-n5 { + margin-left: -3rem !important; + } .m-xl-auto { margin: auto !important; } @@ -8744,13 +9727,17 @@ button.bg-dark:focus { } .text-monospace { - font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !important; } .text-justify { text-align: justify !important; } +.text-wrap { + white-space: normal !important; +} + .text-nowrap { white-space: nowrap !important; } @@ -8837,6 +9824,10 @@ button.bg-dark:focus { font-weight: 300 !important; } +.font-weight-lighter { + font-weight: lighter !important; +} + .font-weight-normal { font-weight: 400 !important; } @@ -8845,6 +9836,10 @@ button.bg-dark:focus { font-weight: 700 !important; } +.font-weight-bolder { + font-weight: bolder !important; +} + .font-italic { font-style: italic !important; } @@ -8858,7 +9853,7 @@ button.bg-dark:focus { } a.text-primary:hover, a.text-primary:focus { - color: #0062cc !important; + color: #0056b3 !important; } .text-secondary { @@ -8866,7 +9861,7 @@ a.text-primary:hover, a.text-primary:focus { } a.text-secondary:hover, a.text-secondary:focus { - color: #545b62 !important; + color: #494f54 !important; } .text-success { @@ -8874,7 +9869,7 @@ a.text-secondary:hover, a.text-secondary:focus { } a.text-success:hover, a.text-success:focus { - color: #1e7e34 !important; + color: #19692c !important; } .text-info { @@ -8882,7 +9877,7 @@ a.text-success:hover, a.text-success:focus { } a.text-info:hover, a.text-info:focus { - color: #117a8b !important; + color: #0f6674 !important; } .text-warning { @@ -8890,7 +9885,7 @@ a.text-info:hover, a.text-info:focus { } a.text-warning:hover, a.text-warning:focus { - color: #d39e00 !important; + color: #ba8b00 !important; } .text-danger { @@ -8898,7 +9893,7 @@ a.text-warning:hover, a.text-warning:focus { } a.text-danger:hover, a.text-danger:focus { - color: #bd2130 !important; + color: #a71d2a !important; } .text-light { @@ -8906,7 +9901,7 @@ a.text-danger:hover, a.text-danger:focus { } a.text-light:hover, a.text-light:focus { - color: #dae0e5 !important; + color: #cbd3da !important; } .text-dark { @@ -8914,7 +9909,7 @@ a.text-light:hover, a.text-light:focus { } a.text-dark:hover, a.text-dark:focus { - color: #1d2124 !important; + color: #121416 !important; } .text-body { @@ -8941,6 +9936,19 @@ a.text-dark:hover, a.text-dark:focus { border: 0; } +.text-decoration-none { + text-decoration: none !important; +} + +.text-break { + word-break: break-word !important; + overflow-wrap: break-word !important; +} + +.text-reset { + color: inherit !important; +} + .visible { visibility: visible !important; } diff --git a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map index cd35b271..7eb15816 100644 --- a/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map +++ b/save-points/3-Front-End-started/ConferencePlanner/FrontEnd/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map @@ -1 +1 @@ -{"version":3,"sources":["../../scss/bootstrap.scss","../../scss/_root.scss","../../scss/_reboot.scss","../../scss/_variables.scss","bootstrap.css","../../scss/mixins/_hover.scss","../../scss/_type.scss","../../scss/mixins/_lists.scss","../../scss/_images.scss","../../scss/mixins/_image.scss","../../scss/mixins/_border-radius.scss","../../scss/_code.scss","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_breakpoints.scss","../../scss/mixins/_grid-framework.scss","../../scss/_tables.scss","../../scss/mixins/_table-row.scss","../../scss/_functions.scss","../../scss/_forms.scss","../../scss/mixins/_transition.scss","../../scss/mixins/_forms.scss","../../scss/mixins/_gradients.scss","../../scss/_buttons.scss","../../scss/mixins/_buttons.scss","../../scss/_transitions.scss","../../scss/_dropdown.scss","../../scss/mixins/_caret.scss","../../scss/mixins/_nav-divider.scss","../../scss/_button-group.scss","../../scss/_input-group.scss","../../scss/_custom-forms.scss","../../scss/_nav.scss","../../scss/_navbar.scss","../../scss/_card.scss","../../scss/_breadcrumb.scss","../../scss/_pagination.scss","../../scss/mixins/_pagination.scss","../../scss/_badge.scss","../../scss/mixins/_badge.scss","../../scss/_jumbotron.scss","../../scss/_alert.scss","../../scss/mixins/_alert.scss","../../scss/_progress.scss","../../scss/_media.scss","../../scss/_list-group.scss","../../scss/mixins/_list-group.scss","../../scss/_close.scss","../../scss/_modal.scss","../../scss/_tooltip.scss","../../scss/mixins/_reset-text.scss","../../scss/_popover.scss","../../scss/_carousel.scss","../../scss/utilities/_align.scss","../../scss/mixins/_background-variant.scss","../../scss/utilities/_background.scss","../../scss/utilities/_borders.scss","../../scss/mixins/_clearfix.scss","../../scss/utilities/_display.scss","../../scss/utilities/_embed.scss","../../scss/utilities/_flex.scss","../../scss/utilities/_float.scss","../../scss/mixins/_float.scss","../../scss/utilities/_position.scss","../../scss/utilities/_screenreaders.scss","../../scss/mixins/_screen-reader.scss","../../scss/utilities/_shadows.scss","../../scss/utilities/_sizing.scss","../../scss/utilities/_spacing.scss","../../scss/utilities/_text.scss","../../scss/mixins/_text-truncate.scss","../../scss/mixins/_text-emphasis.scss","../../scss/mixins/_text-hide.scss","../../scss/utilities/_visibility.scss","../../scss/mixins/_visibility.scss","../../scss/_print.scss"],"names":[],"mappings":"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EACb,2BAA0B;CAC3B;;AAMD;EACE,sBAAqB;CACtB;;AAED;EACE,mBAAkB;EAClB,gBAAe;CAChB;;AAED;EACE,cAAa;CACd;;AExHD;EF6HE,yBAAwB;CACzB;;AI5dD;;EAEE,sBHyQyC;EGxQzC,qBHyQmC;EGxQnC,iBHyQ+B;EGxQ/B,iBHyQ+B;EGxQ/B,eHyQmC;CGxQpC;;AAED;EAAU,kBH2PyC;CG3Pb;;AACtC;EAAU,gBH2PuC;CG3PX;;AACtC;EAAU,mBH2P0C;CG3Pd;;AACtC;EAAU,kBH2PyC;CG3Pb;;AACtC;EAAU,mBH2P0C;CG3Pd;;AACtC;EAAU,gBH2OwB;CG3OI;;AAEtC;EACE,mBH2QoD;EG1QpD,iBH2Q+B;CG1QhC;;AAGD;EACE,gBH0PgC;EGzPhC,iBH8P+B;EG7P/B,iBHqP+B;CGpPhC;;AACD;EACE,kBHsPkC;EGrPlC,iBH0P+B;EGzP/B,iBHgP+B;CG/OhC;;AACD;EACE,kBHkPkC;EGjPlC,iBHsP+B;EGrP/B,iBH2O+B;CG1OhC;;AACD;EACE,kBH8OkC;EG7OlC,iBHkP+B;EGjP/B,iBHsO+B;CGrOhC;;AJmCD;EI3BE,iBHwEW;EGvEX,oBHuEW;EGtEX,UAAS;EACT,yCHtCa;CGuCd;;AAOD;;EAEE,eHiO+B;EGhO/B,iBH+L+B;CG9LhC;;AAED;;EAEE,eHqOgC;EGpOhC,0BH6OmC;CG5OpC;;AAOD;EC/EE,gBAAe;EACf,iBAAgB;CDgFjB;;AAGD;ECpFE,gBAAe;EACf,iBAAgB;CDqFjB;;AACD;EACE,sBAAqB;CAKtB;;AAND;EAII,qBHuN+B;CGtNhC;;AASH;EACE,eAAc;EACd,0BAAyB;CAC1B;;AAGD;EACE,oBHeW;EGdX,mBHyLoD;CGxLrD;;AAED;EACE,eAAc;EACd,eAAc;EACd,eHvGgB;CG4GjB;;AARD;EAMI,uBAAsB;CACvB;;AEpHH;ECIE,gBAAe;EAGf,aAAY;CDLb;;AAID;EACE,iBL61BwC;EK51BxC,uBLLa;EKMb,0BLHgB;EOTd,uBP+NgC;EMxNlC,gBAAe;EAGf,aAAY;CDQb;;AAMD;EAEE,sBAAqB;CACtB;;AAED;EACE,sBAA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,wBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;CXoxCV;;AY70CD;EACE,YAAW;EACX,oBbyHW;EaxHX,8Bb6TuC;CaxSxC;;AAxBD;;EAOI,iBbsTgC;EarThC,oBAAmB;EACnB,8BbAc;CaCf;;AAVH;EAaI,uBAAsB;EACtB,iCbLc;CaMf;;AAfH;EAkBI,8BbTc;CaUf;;AAnBH;EAsBI,uBbhBW;CaiBZ;;AAQH;;EAGI,gBb4R+B;Ca3RhC;;AAQH;EACE,0BbnCgB;CagDjB;;AAdD;;EAKI,0BbvCc;CawCf;;AANH;;EAWM,yBAA8C;CAC/C;;AAIL;;;;EAKI,UAAS;CACV;;AAOH;EAEI,sCb1DW;Ca2DZ;;AXnED;EW8EI,uCbtES;CERS;;AYPtB;;;EAII,0BC2E4D;CD1E7D;;AZEH;EYQM,0BAJsC;CZJtB;;AYGtB;;EASQ,0BARoC;CASrC;;AApBP;;;EAII,0BC2E4D;CD1E7D;;AZEH;EYQM,0BAJsC;CZJtB;;AYGtB;;EASQ,0BARoC;CASrC;;AApBP;;;EAII,0BC2E4D;CD1E7D;;AZEH;EYQM,0BAJsC;CZJtB;;AYGtB;;EASQ,0BARoC;CASrC;;AApBP;;;EAII,0BC2E4D;CD1E7D;;AZEH;EYQM,0BAJsC;CZJtB;;AYGtB;;EASQ,0BARoC;CASrC;;AApBP;;;EAII,0BC2E4D;CD1E7D;;AZEH;EYQM,0BAJsC;CZJtB;;AYGtB;;EASQ,0BARoC;CASrC;;AApBP;;;EAII,0BC2E4D;CD1E7D;;AZEH;EYQM,0BAJsC;CZJtB;;AYGtB;;EASQ,0BARoC;CASrC;;AApBP;;;EAII,0BC2E4D;CD1E7D;;AZEH;EYQM,0BAJsC;CZJtB;;AYGtB;;EASQ,0BARoC;CASrC;;AApBP;;;EAII,0BC2E4D;CD1E7D;;AZEH;EYQM,0BAJsC;CZJtB;;AYGtB;;EASQ,0BARoC;CASrC;;AApBP;;;EAII,uCdWS;CcVV;;AZEH;EYQM,uCAJsC;CZJtB;;AYGtB;;EASQ,uCARoC;CASrC;;ADwFT;EAGM,Yb1GS;Ea2GT,0BblGY;EamGZ,sBb4NgD;Ca3NjD;;AANL;EAWM,eb3GY;Ea4GZ,0BbjHY;EakH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AChB;;AAaH;;EAEE,qBAAoB;CACrB;;AAQC;ECxDA,YrBIa;EmBJX,0BnBkCa;EqBhCf,sBrBgCe;CoBwBd;;AlBpDD;EmBAE,YrBFW;EmBJX,0BEDoF;EASpF,sBATyH;CnBOrG;;AmBKtB;EAMI,gDrBiBW;CqBfd;;AAGD;EAEE,YrBpBW;EqBqBX,0BrBSa;EqBRb,sBrBQa;CqBPd;;AAED;;EAGE,YrB5BW;EqB6BX,0BAlCuK;EAsCvK,sBAtC+M;CAgDhN;;AARC;;EAKI,gDrBVS;CqBYZ;;ADUH;ECxDA,YrBIa;EmBJX,0BnBUc;EqBRhB,sBrBQgB;CoBgDf;;AlBpDD;EmBAE,YrBFW;EmBJX,0BEDoF;EASpF,sBATyH;CnBOrG;;AmBKtB;EAMI,kDrBPY;CqBSf;;AAGD;EAEE,YrBpBW;EqBqBX,0BrBfc;EqBgBd,sBrBhBc;CqBiBf;;AAED;;EAGE,YrB5BW;EqB6BX,0BAlCuK;EAsCvK,sBAtC+M;CAgDhN;;AARC;;EAKI,kDrBlCU;CqBoCb;;ADUH;ECxDA,YrBIa;EmBJX,0BnByCa;EqBvCf,sBrBuCe;CoBiBd;;AlBpDD;EmBAE,YrBFW;EmBJX,0BEDoF;EASpF,sBATyH;CnBOrG;;AmBKtB;EAMI,gDrBwBW;CqBtBd;;AAGD;EAEE,YrBpBW;EqBqBX,0BrBgBa;EqBfb,sBrBea;CqBdd;;AAED;;EAGE,YrB5BW;EqB6BX,0BAlCuK;EAsCvK,sBAtC+M;CAgDhN;;AARC;;EAKI,gDrBHS;CqBKZ;;ADUH;ECxDA,YrBIa;EmBJX,0BnB2Ca;EqBzCf,sBrByCe;CoBed;;AlBpDD;EmBAE,YrBFW;EmBJX,0BEDoF;EASpF,sBATyH;CnBOrG;;AmBKtB;EAMI,iDrB0BW;CqBxBd;;AAGD;EAEE,YrBpBW;EqBqBX,0BrBkBa;EqBjBb,sBrBiBa;CqBhBd;;AAED;;EAGE,YrB5BW;EqB6BX,0BAlCuK;EAsCvK,sBAtC+M;CAgDhN;;AARC;;EAKI,iDrBDS;CqBGZ;;ADUH;ECxDA,erBagB;EmBbd,0BnBwCa;EqBtCf,sBrBsCe;CoBkBd;;AlBpDD;EmBAE,erBOc;EmBbd,0BEDoF;EASpF,sBATyH;CnBOrG;;AmBKtB;EAMI,gDrBuBW;CqBrBd;;AAGD;EAEE,erBXc;EqBYd,0BrBea;EqBdb,sBrBca;CqBbd;;AAED;;EAGE,erBnBc;EqBoBd,0BAlCuK;EAsCvK,sBAtC+M;CAgDhN;;AARC;;EAKI,gDrBJS;CqBMZ;;ADUH;ECxDA,YrBIa;EmBJX,0BnBsCa;EqBpCf,sBrBoCe;CoBoBd;;AlBpDD;EmBAE,YrBFW;EmBJX,0BEDoF;EASpF,sBATyH;CnBOrG;;AmBKtB;EAMI,gDrBqBW;CqBnBd;;AAGD;EAEE,YrBpBW;EqBqBX,0BrBaa;EqBZb,sBrBYa;CqBXd;;AAED;;EAGE,YrB5BW;EqB6BX,0BAlCuK;EAsCvK,sBAtC+M;CAgDhN;;AARC;;EAKI,gDrBNS;CqBQZ;;ADUH;ECxDA,erBagB;EmBbd,0BnBKc;EqBHhB,sBrBGgB;CoBqDf;;AlBpDD;EmBAE,erBOc;EmBbd,0BEDoF;EASpF,sBATyH;CnBOrG;;AmBKtB;EAMI,kDrBZY;CqBcf;;AAGD;EAEE,erBXc;EqBYd,0BrBpBc;EqBqBd,sBrBrBc;CqBsBf;;AAED;;EAGE,erBnBc;EqBoBd,0BAlCuK;EAsCvK,sBAtC+M;CAgDhN;;AARC;;EAKI,kDrBvCU;CqByCb;;ADUH;ECxDA,YrBIa;EmBJX,0BnBYc;EqBVhB,sBrBUgB;CoB8Cf;;AlBpDD;EmBAE,YrBFW;EmBJX,0BEDoF;EASpF,sBATyH;CnBOrG;;AmBKtB;EAMI,+CrBLY;CqBOf;;AAGD;EAEE,YrBpBW;EqBqBX,0BrBbc;EqBcd,sBrBdc;CqBef;;AAED;;EAGE,YrB5BW;EqB6BX,0BAlCuK;EAsCvK,sBAtC+M;CAgDhN;;AARC;;EAKI,+CrBhCU;CqBkCb;;ADgBH;ECXA,erBjBe;EqBkBf,8BAA6B;EAC7B,uBAAsB;EACtB,sBrBpBe;CoB8Bd;;ACRD;EACE,YrBrDW;EqBsDX,0BrBxBa;EqByBb,sBrBzBa;CqB0Bd;;AAED;EAEE,gDrB9Ba;CqB+Bd;;AAED;EAEE,erBnCa;EqBoCb,8BAA6B;CAC9B;;AAED;;EAGE,YrBxEW;EqByEX,0BrB3Ca;EqB4Cb,sBrB5Ca;CqBsDd;;AARC;;EAKI,gDrBnDS;CqBqDZ;;ADzBH;ECXA,erBzCgB;EqB0ChB,8BAA6B;EAC7B,uBAAsB;EACtB,sBrB5CgB;CoBsDf;;ACRD;EACE,YrBrDW;EqBsDX,0BrBhDc;EqBiDd,sBrBjDc;CqBkDf;;AAED;EAEE,kDrBtDc;CqBuDf;;AAED;EAEE,erB3Dc;EqB4Dd,8BAA6B;CAC9B;;AAED;;EAGE,YrBxEW;EqByEX,0BrBnEc;EqBoEd,sBrBpEc;CqB8Ef;;AARC;;EAKI,kDrB3EU;CqB6Eb;;ADzBH;ECXA,erBVe;EqBWf,8BAA6B;EAC7B,uBAAsB;EACtB,sBrBbe;CoBuBd;;ACRD;EACE,YrBrDW;EqBsDX,0BrBjBa;EqBkBb,sBrBlBa;CqBmBd;;AAED;EAEE,gDrBvBa;CqBwBd;;AAED;EAEE,erB5Ba;EqB6Bb,8BAA6B;CAC9B;;AAED;;EAGE,YrBxEW;EqByEX,0BrBpCa;EqBqCb,sBrBrCa;CqB+Cd;;AARC;;EAKI,gDrB5CS;CqB8CZ;;ADzBH;ECXA,erBRe;EqBSf,8BAA6B;EAC7B,uBAAsB;EACtB,sBrBXe;CoBqBd;;ACRD;EACE,YrBrDW;EqBsDX,0BrBfa;EqBgBb,sBrBhBa;CqBiBd;;AAED;EAEE,iDrBrBa;CqBsBd;;AAED;EAEE,erB1Ba;EqB2Bb,8BAA6B;CAC9B;;AAED;;EAGE,YrBxEW;EqByEX,0BrBlCa;EqBmCb,sBrBnCa;CqB6Cd;;AARC;;EAKI,iDrB1CS;CqB4CZ;;ADzBH;ECXA,erBXe;EqBYf,8BAA6B;EAC7B,uBAAsB;EACtB,sBrBde;CoBwBd;;ACRD;EACE,erB5Cc;EqB6Cd,0BrBlBa;EqBmBb,sBrBnBa;CqBoBd;;AAED;EAEE,gDrBxBa;CqByBd;;AAED;EAEE,erB7Ba;EqB8Bb,8BAA6B;CAC9B;;AAED;;EAGE,erB/Dc;EqBgEd,0BrBrCa;EqBsCb,sBrBtCa;CqBgDd;;AARC;;EAKI,gDrB7CS;CqB+CZ;;ADzBH;ECXA,erBbe;EqBcf,8BAA6B;EAC7B,uBAAsB;EACtB,sBrBhBe;CoB0Bd;;ACRD;EACE,YrBrDW;EqBsDX,0BrBpBa;EqBqBb,sBrBrBa;CqBsBd;;AAED;EAEE,gDrB1Ba;CqB2Bd;;AAED;EAEE,erB/Ba;EqBgCb,8BAA6B;CAC9B;;AAED;;EAGE,YrBxEW;EqByEX,0BrBvCa;EqBwCb,sBrBxCa;CqBkDd;;AARC;;EAKI,gDrB/CS;CqBiDZ;;ADzBH;ECXA,erB9CgB;EqB+ChB,8BAA6B;EAC7B,uBAAsB;EACtB,sBrBjDgB;CoB2Df;;ACRD;EACE,erB5Cc;EqB6Cd,0BrBrDc;EqBsDd,sBrBtDc;CqBuDf;;AAED;EAEE,kDrB3Dc;CqB4Df;;AAED;EAEE,erBhEc;EqBiEd,8BAA6B;CAC9B;;AAED;;EAGE,erB/Dc;EqBgEd,0BrBxEc;EqByEd,sBrBzEc;CqBmFf;;AARC;;EAKI,kDrBhFU;CqBkFb;;ADzBH;ECXA,erBvCgB;EqBwChB,8BAA6B;EAC7B,uBAAsB;EACtB,sBrB1CgB;CoBoDf;;ACRD;EACE,YrBrDW;EqBsDX,0BrB9Cc;EqB+Cd,sBrB/Cc;CqBgDf;;AAED;EAEE,+CrBpDc;CqBqDf;;AAED;EAEE,erBzDc;EqB0Dd,8BAA6B;CAC9B;;AAED;;EAGE,YrBxEW;EqByEX,0BrBjEc;EqBkEd,sBrBlEc;CqB4Ef;;AARC;;EAKI,+CrBzEU;CqB2Eb;;ADdL;EACE,iBpBoL+B;EoBnL/B,epBzCe;EoB0Cf,8BAA6B;CAuB9B;;AlB7FC;EkByEE,epBoFgD;EoBnFhD,2BpBoFiC;EoBnFjC,8BAA6B;EAC7B,0BAAyB;ClB5EL;;AkBmExB;EAcI,2BpB6EiC;EoB5EjC,0BAAyB;EACzB,iBAAgB;CACjB;;AAjBH;EAqBI,epBpFc;EoBqFd,qBAAoB;CACrB;;AAUH;ECbE,qBrBuQgC;EqBtQhC,mBrB4JoD;EqB3JpD,iBrBwH+B;EqBrH7B,sBrB4H+B;CoBlHlC;;AAED;ECjBE,wBrBmQiC;EqBlQjC,oBrB6JoD;EqB5JpD,iBrByH+B;EqBtH7B,sBrB6H+B;CoB/GlC;;AAOD;EACE,eAAc;EACd,YAAW;CAMZ;;AARD;EAMI,mBpBwQ+B;CoBvQhC;;AAIH;;;EAII,YAAW;CACZ;;AE3IH;ELGM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M,kB5BySQ;C4BxST;;AAIL;EACE,mBAAkB;EAClB,OAAM;EACN,SAAQ;EACR,QAAO;EACP,WAAU;EACV,4B5BoK4F;E4BnK5F,0B5BoEkC;E4BnElC,iB5BnB+B;E4BoB/B,e5B3QgB;E4B4QhB,uB5BnRa;E4BoRb,0B5BhRgB;EOVd,uBP+NgC;C4B+EnC;;AA/BD;EAgBI,mBAAkB;EAClB,OAAM;EACN,SAAQ;EACR,UAAS;EACT,WAAU;EACV,eAAc;EACd,gB5BmJ2G;E4BlJ3G,0B5BoDgC;E4BnDhC,iB5BnC6B;E4BoC7B,e5B3Rc;E4B4Rd,kBAAiB;ETvSjB,0BnBMc;E4BmSd,+B5BjSc;EOVd,mCqB4SgF;CACjF;;AASH;EACE,YAAW;EACX,gBAAe;EACf,8BAA6B;EAC7B,yBAAgB;EAAhB,sBAAgB;EAAhB,iBAAgB;CA4GjB;;AAhHD;EAOI,cAAa;CAOd;;AAdH;EAW8B,iE5B7Rb;C4B6RiE;;AAXlF;EAY8B,iE5B9Rb;C4B8RiE;;AAZlF;EAa8B,iE5B/Rb;C4B+RiE;;AAblF;EAiBI,UAAS;CACV;;AAlBH;EAqBI,Y5B4M6C;E4B3M7C,a5B2M6C;E4B1M7C,qBAA2E;ET3U3E,0BnBkCa;E4B2Sb,U5B2M0C;EO1hB1C,oBP2hB6C;EiB1hB3C,6GjBid+H;E4B/HjI,yBAAgB;EAAhB,iBAAgB;CAKjB;;AXnVD;EWiTF;IXhTI,iBAAgB;GWkVjB;C3B2nGF;;A2B7pGD;ETpTI,0BnB6hB2E;C4BxM1E;;AAjCL;EAqCI,Y5BqLoC;E4BpLpC,e5BqLqC;E4BpLrC,mBAAkB;EAClB,gB5BoLuC;E4BnLvC,0B5BtVc;E4BuVd,0BAAyB;ErBhWzB,oBPohBoC;C4BjLrC;;AA7CH;EAgDI,Y5BiL6C;E4BhL7C,a5BgL6C;EmBrhB7C,0BnBkCa;E4BqUb,U5BiL0C;EO1hB1C,oBP2hB6C;EiB1hB3C,6GjBid+H;E4BrGjI,sBAAgB;EAAhB,iBAAgB;CAKjB;;AX7WD;EWiTF;IXhTI,iBAAgB;GW4WjB;C3B+nGF;;A2B3rGD;ETpTI,0BnB6hB2E;C4B9K1E;;AA3DL;EA+DI,Y5B2JoC;E4B1JpC,e5B2JqC;E4B1JrC,mBAAkB;EAClB,gB5B0JuC;E4BzJvC,0B5BhXc;E4BiXd,0BAAyB;ErB1XzB,oBPohBoC;C4BvJrC;;AAvEH;EA0EI,Y5BuJ6C;E4BtJ7C,a5BsJ6C;E4BrJ7C,cAAa;EACb,qB5BtC+B;E4BuC/B,oB5BvC+B;EmB3V/B,0BnBkCa;E4BkWb,U5BoJ0C;EO1hB1C,oBP2hB6C;EiB1hB3C,6GjBid+H;E4BxEjI,iBAAgB;CAKjB;;AX1YD;EWiTF;IXhTI,iBAAgB;GWyYjB;C3BmoGF;;A2B5tGD;ETpTI,0BnB6hB2E;C4BjJ1E;;AAxFL;EA4FI,Y5B8HoC;E4B7HpC,e5B8HqC;E4B7HrC,mBAAkB;EAClB,gB5B6HuC;E4B5HvC,8BAA6B;EAC7B,0BAAyB;EACzB,qBAA+C;CAEhD;;AApGH;EAuGI,0B5BpZc;EOTd,oBPohBoC;C4BrHrC;;AAzGH;EA4GI,mBAAkB;EAClB,0B5B1Zc;EOTd,oBPohBoC;C4B/GrC;;AAGH;;;EXvaM,6GjBid+H;C4BtCpI;;AXvaC;EWmaF;;;IXlaI,iBAAgB;GWsanB;C3B6oGA;;A4BxjHD;EACE,qBAAa;EAAb,cAAa;EACb,oBAAe;EAAf,gBAAe;EACf,gBAAe;EACf,iBAAgB;EAChB,iBAAgB;CACjB;;AAED;EACE,eAAc;EACd,qB7BgmBsC;C6BtlBvC;;A3BTC;E2BEE,sBAAqB;C3BCtB;;A2BNH;EAUI,e7BPc;C6BQf;;AAOH;EACE,iC7BnBgB;C6BqDjB;;AAnCD;EAII,oB7B6L6B;C6B5L9B;;AALH;EAQI,8BAAgD;EtB7BhD,gCPyNgC;EOxNhC,iCPwNgC;C6BhLjC;;A3BnCD;E2B2BI,sC7B9BY;CEMf;;A2BYH;EAgBM,e7B/BY;E6BgCZ,8BAA6B;EAC7B,0BAAyB;CAC1B;;AAnBL;;EAwBI,e7BtCc;E6BuCd,uB7B9CW;E6B+CX,mC7B/CW;C6BgDZ;;AA3BH;EA+BI,iB7BkK6B;EOtN7B,0BsBsD4B;EtBrD5B,2BsBqD4B;CAC7B;;AAQH;EtBrEI,uBP+NgC;C6BvJjC;;AAHH;;EAOI,Y7BtEW;E6BuEX,0B7BzCa;C6B0Cd;;AAQH;EAEI,mBAA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C3NnC;;AAED;EAGI,qBhCg3BqC;CgCx2BtC;;AAXH;EAMM,sBAAqB;EACrB,sBhC42BmC;EgC32BnC,ehCFY;EgCGZ,ahCi3BuC;CgCh3BxC;;AAVL;EAoBI,2BAA0B;CAC3B;;AArBH;EAwBI,sBAAqB;CACtB;;AAzBH;EA4BI,ehCtBc;CgCuBf;;ACvCH;EACE,qBAAa;EAAb,cAAa;E7BGb,gBAAe;EACf,iBAAgB;EGDd,uBP+NgC;CiC/NnC;;AAED;EACE,mBAAkB;EAClB,eAAc;EACd,wBjC2pBwC;EiC1pBxC,kBjCsN+B;EiCrN/B,kBjC8pBsC;EiC7pBtC,ejC4Be;EiC3Bf,uBjCHa;EiCIb,0BjCDgB;CiCqBjB;;AA5BD;EAWI,WAAU;EACV,ejCuJgD;EiCtJhD,sBAAqB;EACrB,0BjCRc;EiCSd,sBjCRc;CiCSf;;AAhBH;EAmBI,WAAU;EACV,WjCupBiC;EiCtpBjC,iDjCaa;CiCZd;;AAtBH;EA0BI,gBAAe;CAChB;;AAGH;EAGM,eAAc;E1BRhB,gCPoMgC;EOnMhC,mCPmMgC;CiC1L/B;;AALL;E1BnBI,iCPkNgC;EOjNhC,oCPiNgC;CiCrL/B;;AAVL;EAcI,WAAU;EACV,YjCzCW;EiC0CX,0BjCZa;EiCab,sBjCba;CiCcd;;AAlBH;EAqBI,ejCzCc;EiC0Cd,qBAAoB;EAEpB,aAAY;EACZ,uBjCnDW;EiCoDX,sBjCjDc;CiCkDf;;AC5DD;EACE,wBlCoqBsC;EkCnqBtC,mBlC2PkD;EkC1PlD,iBlCuN6B;CkCtN9B;;AAIG;E3BoBF,+BPqM+B;EOpM/B,kCPoM+B;CkCvN5B;;AAGD;E3BCF,gCPmN+B;EOlN/B,mCPkN+B;CkClN5B;;AAfL;EACE,wBlCkqBqC;EkCjqBrC,oBlC4PkD;EkC3PlD,iBlCwN6B;CkCvN9B;;AAIG;E3BoBF,+BPsM+B;EOrM/B,kCPqM+B;CkCxN5B;;AAGD;E3BCF,gCPoN+B;EOnN/B,mCPmN+B;CkCnN5B;;ACbP;EACE,sBAAqB;EACrB,sBnCowBsC;EmCnwBtC,enCgwBqC;EmC/vBrC,iBnC4P+B;EmC3P/B,eAAc;EACd,mBAAkB;EAClB,oBAAmB;EACnB,yBAAwB;E5BTtB,uBP+NgC;CmC/MnC;;AAfD;EAaI,cAAa;CACd;;AAIH;EACE,mBAAkB;EAClB,UAAS;CACV;;AAMD;EACE,qBnC6uBsC;EmC5uBtC,oBnC4uBsC;EO1wBpC,qBP6wBqC;CmC7uBxC;;AAOC;EC1CA,YpCSa;EoCRb,0BpCsCe;CmCKd;;AjC7BD;EkCVI,YpCIS;EoCHT,sBAAqB;EACrB,0BAAkC;ClCWrC;;AiCwBD;EC1CA,YpCSa;EoCRb,0BpCcgB;CmC6Bf;;AjC7BD;EkCVI,YpCIS;EoCHT,sBAAqB;EACrB,0BAAkC;ClCWrC;;AiCwBD;EC1CA,YpCSa;EoCRb,0BpC6Ce;CmCFd;;AjC7BD;EkCVI,YpCIS;EoCHT,sBAAqB;EACrB,0BAAkC;ClCWrC;;AiCwBD;EC1CA,YpCSa;EoCRb,0BpC+Ce;CmCJd;;AjC7BD;EkCVI,YpCIS;EoCHT,sBAAqB;EACrB,0BAAkC;ClCWrC;;AiCwBD;EC1CA,epCkBgB;EoCjBhB,0BpC4Ce;CmCDd;;AjC7BD;EkCVI,epCaY;EoCZZ,sBAAqB;EACrB,0BAAkC;ClCWrC;;AiCwBD;EC1CA,YpCSa;EoCRb,0BpC0Ce;CmCCd;;AjC7BD;EkCVI,YpCIS;EoCHT,sBAAqB;EACrB,0BAAkC;ClCWrC;;AiCwBD;EC1CA,epCkBgB;EoCjBhB,0BpCSgB;CmCkCf;;AjC7BD;EkCVI,epCaY;EoCZZ,sBAAqB;EACrB,0BAAkC;ClCWrC;;AiCwBD;EC1CA,YpCSa;EoCRb,0BpCgBgB;CmC2Bf;;AjC7BD;EkCVI,YpCIS;EoCHT,sBAAqB;EACrB,0BAAkC;ClCWrC;;AmCnBH;EACE,mBAAoD;EACpD,oBrCgsBsC;EqC/rBtC,0BrCSgB;EORd,sBPgO+B;CqC3NlC;;A1BmDG;E0B5DJ;IAOI,mBrC2rBoC;GqCzrBvC;CpC++IA;;AoC7+ID;EACE,iBAAgB;EAChB,gBAAe;E9BTb,iB8BUsB;CACzB;;ACXD;EACE,mBAAkB;EAClB,yBtCmzByC;EsClzBzC,oBtCmzBsC;EsClzBtC,8BAA6C;E/BJ3C,uBP+NgC;CsCzNnC;;AAGD;EAEE,eAAc;CACf;;AAG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E2CKP,0B5BqE0D;E4BpE1D,sB5BoE0D;C4BnE3D;;AAdL;EACE,e5BgF8D;E4B/E9D,0B5B+E8D;C4BjE/D;;AzCHD;EyCPM,e5B2E0D;E4B1E1D,0BAAyC;CzCS9C;;AyChBD;EAWM,Y3CJO;E2CKP,0B5BqE0D;E4BpE1D,sB5BoE0D;C4BnE3D;;AAdL;EACE,e5BgF8D;E4B/E9D,0B5B+E8D;C4BjE/D;;AzCHD;EyCPM,e5B2E0D;E4B1E1D,0BAAyC;CzCS9C;;AyChBD;EAWM,Y3CJO;E2CKP,0B5BqE0D;E4BpE1D,sB5BoE0D;C4BnE3D;;AAdL;EACE,e5BgF8D;E4B/E9D,0B5B+E8D;C4BjE/D;;AzCHD;EyCPM,e5B2E0D;E4B1E1D,0BAAyC;CzCS9C;;AyChBD;EAWM,Y3CJO;E2CKP,0B5BqE0D;E4BpE1D,sB5BoE0D;C4BnE3D;;AAdL;EACE,e5BgF8D;E4B/E9D,0B5B+E8D;C4BjE/D;;AzCHD;EyCPM,e5B2E0D;E4B1E1D,0BAAyC;CzCS9C;;AyChBD;EAWM,Y3CJO;E2CKP,0B5BqE0D;E4BpE1D,sB5BoE0D;C4BnE3D;;AAdL;EACE,e5BgF8D;E4B/E9D,0B5B+E8D;C4BjE/D;;AzCHD;EyCPM,e5B2E0D;E4B1E1D,0BAAyC;CzCS9C;;AyChBD;EAWM,Y3CJO;E2CKP,0B5BqE0D;E4BpE1D,sB5BoE0D;C4BnE3D;;AAdL;EACE,e5BgF8D;E4B/E9D,0B5B+E8D;C4BjE/D;;AzCHD;EyCPM,e5B2E0D;E4B1E1D,0BAAyC;CzCS9C;;AyChBD;EAWM,Y3CJO;E2CKP,0B5BqE0D;E4BpE1D,sB5BoE0D;C4BnE3D;;AAdL;EACE,e5BgF8D;E4B/E9D,0B5B+E8D;C4BjE/D;;AzCHD;EyCPM,e5B2E0D;E4B1E1D,0BAAyC;CzCS9C;;AyChBD;EAWM,Y3CJO;E2CKP,0B5BqE0D;E4BpE1D,sB5BoE0D;C4BnE3D;;ACjBP;EACE,aAAY;EACZ,kB5C+5BuD;E4C95BvD,iB5CkQ+B;E4CjQ/B,eAAc;EACd,Y5Cea;E4Cdb,0B5CIa;E4CHb,YAAW;CAaZ;;AApBD;EAkBI,gBAAe;CAChB;;A1CHD;E0CJI,Y5CQS;E4CPT,sBAAqB;EACrB,aAAY;C1CKf;;A0CSH;EACE,WAAU;EACV,8BAA6B;EAC7B,UAAS;EACT,yBAAwB;CACzB;;AC3BD;EAEE,iBAAgB;CAMjB;;AARD;EAKI,mBAAkB;EAClB,iBAAgB;CACjB;;AAIH;EACE,gBAAe;EACf,OAAM;EACN,SAAQ;EACR,UAAS;EACT,QAAO;EACP,c7CilBsC;E6ChlBtC,cAAa;EACb,iBAAgB;EAGhB,WAAU;CAIX;;AAGD;EACE,mBAAkB;EAClB,YAAW;EACX,e7CmvBuC;E6CjvBvC,qBAAoB;CAUrB;;AAPC;E5BtCI,4CjB4yBoD;EiB5yBpD,oCjB4yBoD;EiB5yBpD,qEjB4yBoD;E6CpwBtD,sCAA6B;EAA7B,8BAA6B;CAC9B;;A5BrCD;E4BkCA;I5BjCE,iBAAgB;G4BoCjB;C5C85JF;;A4C75JC;EACE,mCAA0B;EAA1B,2BAA0B;CAC3B;;AAGH;EACE,qBAAa;EAAb,cAAa;EACb,uBAAmB;EAAnB,oBAAmB;EACnB,sCAAsD;CAQvD;;AAXD;EAOI,eAAc;EACd,mCAAmD;EACnD,YAAW;CACZ;;AAIH;EACE,mBAAkB;EAClB,qBAAa;EAAb,cAAa;EACb,2BAAsB;EAAtB,uBAAsB;EACtB,YAAW;EAEX,qBAAoB;EACpB,uB7C/Da;E6CgEb,6BAA4B;EAC5B,qC7CvDa;EOhBX,sBPgO+B;E6CrJjC,WAAU;CACX;;AAGD;EACE,gBAAe;EACf,OAAM;EACN,SAAQ;EACR,UAAS;EACT,QAAO;EACP,c7C8gBsC;E6C7gBtC,uB7CtEa;C6C2Ed;;AAZD;EAUW,WAAU;CAAI;;AAVzB;EAWW,a7CwsB2B;C6CxsBS;;AAK/C;EACE,qBAAa;EAAb,cAAa;EACb,sBAAuB;EAAvB,wBAAuB;EACvB,uBAA8B;EAA9B,+BAA8B;EAC9B,c7CosBsC;E6CnsBtC,iC7C5FgB;EOFd,+BP0N+B;EOzN/B,gCPyN+B;C6CpHlC;;AAbD;EASI,c7C+rBoC;E6C7rBpC,+BAAuF;CACxF;;AAIH;EACE,iBAAgB;EAChB,iB7CmJ+B;C6ClJhC;;AAID;EACE,mBAAkB;EAGlB,mBAAc;EAAd,eAAc;EACd,c7CwpBsC;C6CvpBvC;;AAGD;EACE,qBAAa;EAAb,cAAa;EACb,uBAAmB;EAAnB,oBAAmB;EACnB,mBAAyB;EAAzB,0BAAyB;EACzB,c7CgpBsC;E6C/oBtC,8B7C5HgB;C6CiIjB;;AAVD;EAQyB,oBAAmB;CAAI;;AARhD;EASwB,qBAAoB;CAAI;;AAIhD;EACE,mBAAkB;EAClB,aAAY;EACZ,YAAW;EACX,aAAY;EACZ,iBAAgB;CACjB;;AlC1FG;EkCzBJ;IAyHI,iB7CkpBqC;I6CjpBrC,qBAAyC;GAC1C;EA1GH;IA6GI,uCAA8D;GAM/D;EAnHH;IAgHM,oCAA2D;GAC5D;EAQH;IAAY,iB7CkoB2B;G6CloBH;C5Cg5JrC;;AUjgKG;EkCsHF;IAAY,iB7C2nB2B;G6C3nBH;C5Ci5JrC;;A6ClkKD;EACE,mBAAkB;EAClB,c9CumBsC;E8CtmBtC,eAAc;EACd,U9CguBmC;E+CpuBnC,sL/CyPoM;E+CvPpM,mBAAkB;EAClB,iB/CgQ+B;E+C/P/B,iB/CmQ+B;E+ClQ/B,iBAAgB;EAChB,kBAAiB;EACjB,sBAAqB;EACrB,kBAAiB;EACjB,qBAAoB;EACpB,uBAAsB;EACtB,mBAAkB;EAClB,qBAAoB;EACpB,oBAAmB;EACnB,iBAAgB;EDNhB,oB9CwPoD;E8CtPpD,sBAAqB;EACrB,WAAU;CAiBX;;AA5BD;EAaW,a9CotB2B;C8CptBE;;AAbxC;EAgBI,mBAAkB;EAClB,eAAc;EACd,c9CotBqC;E8CntBrC,e9CotBqC;C8C5sBtC;;AA3BH;EAsBM,mBAAkB;EAClB,YAAW;EACX,0BAAyB;EACzB,oBAAmB;CACpB;;AAIL;EACE,kBAAgC;CAWjC;;AAZD;EAII,UAAS;CAOV;;AAXH;EAOM,OAAM;EACN,8BAAgE;EAChE,uB9CpBS;C8CqBV;;AAIL;EACE,kB9C0rBuC;C8C7qBxC;;AAdD;EAII,QAAO;EACP,c9CsrBqC;E8CrrBrC,e9CorBqC;C8C7qBtC;;AAbH;EASM,SAAQ;EACR,qCAA2F;EAC3F,yB9CpCS;C8CqCV;;AAIL;EACE,kBAAgC;CAWjC;;AAZD;EAII,OAAM;CAOP;;AAXH;EAOM,UAAS;EACT,8B9CmqBmC;E8ClqBnC,0B9ClDS;C8CmDV;;AAIL;EACE,kB9C4pBuC;C8C/oBxC;;AAdD;EAII,SAAQ;EACR,c9CwpBqC;E8CvpBrC,e9CspBqC;C8C/oBtC;;AAbH;EASM,QAAO;EACP,qC9CmpBmC;E8ClpBnC,wB9ClES;C8CmEV;;AAoBL;EACE,iB9CknBuC;E8CjnBvC,wB9CunBuC;E8CtnBvC,Y9CpGa;E8CqGb,mBAAkB;EAClB,uB9C5Fa;EOhBX,uBP+NgC;C8CjHnC;;AElHD;EACE,mBAAkB;EAClB,OAAM;EACN,QAAO;EACP,chDqmBsC;EgDpmBtC,eAAc;EACd,iBhD0uBuC;E+C/uBvC,sL/CyPoM;E+CvPpM,mBAAkB;EAClB,iB/CgQ+B;E+C/P/B,iB/CmQ+B;E+ClQ/B,iBAAgB;EAChB,kBAAiB;EACjB,sBAAqB;EACrB,kBAAiB;EACjB,qBAAoB;EACpB,uBAAsB;EACtB,mBAAkB;EAClB,qBAAoB;EACpB,oBAAmB;EACnB,iBAAgB;ECLhB,oBhDuPoD;EgDrPpD,sBAAqB;EACrB,uBhDHa;EgDIb,6BAA4B;EAC5B,qChDKa;EOhBX,sBPgO+B;CgDjMlC;;AAnCD;EAoBI,mBAAkB;EAClB,eAAc;EACd,YhDyuBoC;EgDxuBpC,ehDyuBqC;EgDxuBrC,iBhD4M+B;CgDlMhC;;AAlCH;EA4BM,mBAAkB;EAClB,eAAc;EACd,YAAW;EACX,0BAAyB;EACzB,oBAAmB;CACpB;;AAIL;EACE,sBhD0tBuC;CgDtsBxC;;AArBD;EAII,kCAAwE;CACzE;;AALH;;;EASI,8BAAgE;CACjE;;AAVH;EAaI,UAAS;EACT,sChDgtBmE;CgD/sBpE;;;AAfH;;EAkBI,YhDyK6B;EgDxK7B,uBhD9CW;CgD+CZ;;AAGH;EACE,oBhDmsBuC;CgD5qBxC;;AAxBD;EAII,gCAAsE;EACtE,chD+rBqC;EgD9rBrC,ahD6rBoC;EgD5rBpC,iBAA2B;CAC5B;;AARH;;;EAYI,qCAA2F;CAC5F;;AAbH;EAgBI,QAAO;EACP,wChDsrBmE;CgDrrBpE;;;AAlBH;;EAqBI,UhD+I6B;EgD9I7B,yBhDxEW;CgDyEZ;;AAGH;EACE,mBhDyqBuC;CgDzoBxC;;AAjCD;EAII,+BAAqE;CACtE;;AALH;;;EASI,qCAA2F;CAC5F;;AAVH;EAaI,OAAM;EACN,yChD+pBmE;CgD9pBpE;;;AAfH;;EAkBI,ShDwH6B;EgDvH7B,0BhD/FW;CgDgGZ;;AApBH;EAwBI,mBAAkB;EAClB,OAAM;EACN,UAAS;EACT,eAAc;EACd,YhD6oBoC;EgD5oBpC,qBAAwC;EACxC,YAAW;EACX,iChDioBuD;CgDhoBxD;;AAGH;EACE,qBhDsoBuC;CgD/mBxC;;AAxBD;EAII,iCAAuE;EACvE,chDkoBqC;EgDjoBrC,ahDgoBoC;EgD/nBpC,iBAA2B;CAC5B;;AARH;;;EAYI,qChD2nBqC;CgD1nBtC;;AAbH;EAgBI,SAAQ;EACR,uChDynBmE;CgDxnBpE;;;AAlBH;;EAqBI,WhDkF6B;EgDjF7B,wBhDrIW;CgDsIZ;;AAoBH;EACE,wBhDolBwC;EgDnlBxC,iBAAgB;EAChB,gBhDwFgC;EgDvFhC,ehD6GmC;EgD5GnC,0BhD6kByD;EgD5kBzD,iCAAyE;EzChKvE,2CyCiKyE;EzChKzE,4CyCgKyE;CAM5E;;AAbD;EAWI,cAAa;CACd;;AAGH;EACE,wBhDqkBwC;EgDpkBxC,ehDlKgB;CgDmKjB;;AC5KD;EACE,mBAAkB;CACnB;;AAED;EACE,mBAAkB;EAClB,YAAW;EACX,iBAAgB;CACjB;;AAED;EACE,mBAAkB;EAClB,cAAa;EACb,uBAAmB;EAAnB,oBAAmB;EACnB,YAAW;EACX,oCAA2B;EAA3B,4BAA2B;EAC3B,4BAAmB;EAAnB,oBAAmB;CACpB;;AAED;;;EAGE,eAAc;EhC3BV,wCjBu5BgD;EiBv5BhD,gCjBu5BgD;EiBv5BhD,6DjBu5BgD;CiD13BrD;;AhCzBC;EgCoBF;;;IhCnBI,iBAAgB;GgCwBnB;ChD42KA;;AgD12KD;;EAEE,mBAAkB;EAClB,OAAM;CACP;;AAED;;EAEE,iCAAwB;EAAxB,yBAAwB;CAKzB;;AAHyC;EAJ1C;;IAKI,wCAA+B;IAA/B,gCAA+B;GAElC;ChD+2KA;;AgD72KD;;EAEE,oCAA2B;EAA3B,4BAA2B;CAK5B;;AAHyC;EAJ1C;;IAKI,2CAAkC;IAAlC,mCAAkC;GAErC;ChDk3KA;;AgDh3KD;;EAEE,qCAA4B;EAA5B,6BAA4B;CAK7B;;AAHyC;EAJ1C;;IAKI,4CAAmC;IAAnC,oCAAmC;GAEtC;ChDq3KA;;AgD92KD;EAEI,WAAU;EACV,yBAAwB;EACxB,6BAA4B;CAC7B;;AALH;;;EAUI,WAAU;CACX;;AAXH;;EAeI,WAAU;CACX;;AAhBH;;;;;EAuBI,iCAAwB;EAAxB,yBAAwB;CAKzB;;AAHyC;EAzB5C;;;;;IA0BM,wCAA+B;IAA/B,gCAA+B;GAElC;ChDq3KF;;AgD72KD;;EAEE,mBAAkB;EAClB,OAAM;EACN,UAAS;EAET,qBAAa;EAAb,cAAa;EACb,uBAAmB;EAAnB,oBAAmB;EACnB,sBAAuB;EAAvB,wBAAuB;EACvB,WjDqxBqC;EiDpxBrC,YjD9Ga;EiD+Gb,mBAAkB;EAClB,ajDmxBoC;CiDxwBrC;;A/CrHC;;;E+CgHE,YjDtHW;EiDuHX,sBAAqB;EACrB,WAAU;EACV,YAAW;C/ChHZ;;A+CmHH;EACE,QAAO;CAIR;;AACD;EACE,SAAQ;CAIT;;AAGD;;EAEE,sBAAqB;EACrB,YjDgwBsC;EiD/vBtC,ajD+vBsC;EiD9vBtC,gDAA+C;EAC/C,2BAA0B;CAC3B;;AACD;EACE,iNlCjHyI;CkCkH1I;;AACD;EACE,iNlCpHyI;CkCqH1I;;AAQD;EACE,mBAAkB;EAClB,SAAQ;EACR,aAAY;EACZ,QAAO;EACP,YAAW;EACX,qBAAa;EAAb,cAAa;EACb,sBAAuB;EAAvB,wBAAuB;EACvB,gBAAe;EAEf,kBjDytBqC;EiDxtBrC,iBjDwtBqC;EiDvtBrC,iBAAgB;CAqCjB;;AAjDD;EAeI,mBAAkB;EAClB,mBAAc;EAAd,eAAc;EACd,YjDqtBoC;EiDptBpC,YjDqtBmC;EiDptBnC,kBjDqtBmC;EiDptBnC,iBjDotBmC;EiDntBnC,oBAAmB;EACnB,gBAAe;EACf,2CjDtLW;CiD2MZ;;AA5CH;EA2BM,mBAAkB;EAClB,WAAU;EACV,QAAO;EACP,sBAAqB;EACrB,YAAW;EACX,aAAY;EACZ,YAAW;CACZ;;AAlCL;EAoCM,mBAAkB;EAClB,cAAa;EACb,QAAO;EACP,sBAAqB;EACrB,YAAW;EACX,aAAY;EACZ,YAAW;CACZ;;AA3CL;EA+CI,uBjD9MW;CiD+MZ;;AAQH;EACE,mBAAkB;EAClB,WAA6C;EAC7C,aAAY;EACZ,UAA4C;EAC5C,YAAW;EACX,kBAAiB;EACjB,qBAAoB;EACpB,YjD/Na;EiDgOb,mBAAkB;CACnB;;ACzOD;EAAqB,oCAAmC;CAAI;;AAC5D;EAAqB,+BAA8B;CAAI;;AACvD;EAAqB,kCAAiC;CAAI;;AAC1D;EAAqB,kCAAiC;CAAI;;AAC1D;EAAqB,uCAAsC;CAAI;;AAC/D;EAAqB,oCAAmC;CAAI;;ACF1D;EACE,qCAAmC;CACpC;;AjDSD;;;EiDLI,qCAAgD;CjDQnD;;AiDdD;EACE,qCAAmC;CACpC;;AjDSD;;;EiDLI,qCAAgD;CjDQnD;;AiDdD;EACE,qCAAmC;CACpC;;AjDSD;;;EiDLI,qCAAgD;CjDQnD;;AiDdD;EACE,qCAAmC;CACpC;;AjDSD;;;EiDLI,qCAAgD;CjDQnD;;AiDdD;EACE,qCAAmC;CACpC;;AjDSD;;;EiDLI,qCAAgD;CjDQnD;;AiDdD;EACE,qCAAmC;CACpC;;AjDSD;;;EiDLI,qCAAgD;CjDQnD;;AiDdD;EACE,qCAAmC;CACpC;;AjDSD;;;EiDLI,qCAAgD;CjDQnD;;AiDdD;EACE,qCAAmC;CACpC;;AjDSD;;;EiDLI,qCAAgD;CjDQnD;;AkDPH;EACE,kCAAmC;CACpC;;AAED;EACE,yCAAwC;CACzC;;ACZD;EAAkB,qCAAoD;CAAI;;AAC1E;EAAkB,yCAAwD;CAAI;;AAC9E;EAAkB,2CAA0D;CAAI;;AAChF;EAAkB,4CAA2D;CAAI;;AACjF;EAAkB,0CAAyD;CAAI;;AAE/E;EAAmB,qBAAoB;CAAI;;AAC3C;EAAmB,yBAAwB;CAAI;;AAC/C;EAAmB,2BAA0B;CAAI;;AACjD;EAAmB,4BAA2B;CAAI;;AAClD;EAAmB,0BAAyB;CAAI;;AAG9C;EACE,iCAA+B;CAChC;;AAFD;EACE,iCAA+B;CAChC;;AAFD;EACE,iCAA+B;CAChC;;AAFD;EACE,iCAA+B;CAChC;;AAFD;EACE,iCAA+B;CAChC;;AAFD;EACE,iCAA+B;CAChC;;AAFD;EACE,iCAA+B;CAChC;;AAFD;EACE,iCAA+B;CAChC;;AAGH;EACE,8BAA+B;CAChC;;AAMD;EACE,kCAAwC;CACzC;;AACD;EACE,2CAAiD;EACjD,4CAAkD;CACnD;;AACD;EACE,4CAAkD;EAClD,+CAAqD;CACtD;;AACD;EACE,+CAAqD;EACrD,8CAAoD;CACrD;;AACD;EACE,2CAAiD;EACjD,8CAAoD;CACrD;;AAED;EACE,8BAA6B;CAC9B;;AAED;EACE,4BAA2B;CAC5B;;ACzDC;EACE,eAAc;EACd,YAAW;EACX,YAAW;CACZ;;ACKC;EAA2B,yBAAwB;CAAI;;AACvD;EAA2B,2BAA0B;CAAI;;AACzD;EAA2B,iCAAgC;CAAI;;AAC/D;EAA2B,0BAAyB;CAAI;;AACxD;EAA2B,0BAAyB;CAAI;;AACxD;EAA2B,8BAA6B;CAAI;;AAC5D;EAA2B,+BAA8B;CAAI;;AAC7D;EAA2B,gCAAwB;EAAxB,yBAAwB;CAAI;;AACvD;EAA2B,uCAA+B;EAA/B,gCAA+B;CAAI;;A5C0C9D;E4ClDA;IAA2B,yBAAwB;GAAI;EACvD;IAA2B,2BAA0B;GAAI;EACzD;IAA2B,iCAAgC;GAAI;EAC/D;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,8BAA6B;GAAI;EAC5D;IAA2B,+BAA8B;GAAI;EAC7D;IAA2B,gCAAwB;IAAxB,yBAAwB;GAAI;EACvD;IAA2B,uCAA+B;IAA/B,gCAA+B;GAAI;CtD21LjE;;AUjzLG;E4ClDA;IAA2B,yBAAwB;GAAI;EACvD;IAA2B,2BAA0B;GAAI;EACzD;IAA2B,iCAAgC;GAAI;EAC/D;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,8BAA6B;GAAI;EAC5D;IAA2B,+BAA8B;GAAI;EAC7D;IAA2B,gCAAwB;IAAxB,yBAAwB;GAAI;EACvD;IAA2B,uCAA+B;IAA/B,gCAA+B;GAAI;CtDy3LjE;;AU/0LG;E4ClDA;IAA2B,yBAAwB;GAAI;EACvD;IAA2B,2BAA0B;GAAI;EACzD;IAA2B,iCAAgC;GAAI;EAC/D;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,8BAA6B;GAAI;EAC5D;IAA2B,+BAA8B;GAAI;EAC7D;IAA2B,gCAAwB;IAAxB,yBAAwB;GAAI;EACvD;IAA2B,uCAA+B;IAA/B,gCAA+B;GAAI;CtDu5LjE;;AU72LG;E4ClDA;IAA2B,yBAAwB;GAAI;EACvD;IAA2B,2BAA0B;GAAI;EACzD;IAA2B,iCAAgC;GAAI;EAC/D;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,8BAA6B;GAAI;EAC5D;IAA2B,+BAA8B;GAAI;EAC7D;IAA2B,gCAAwB;IAAxB,yBAAwB;GAAI;EACvD;IAA2B,uCAA+B;IAA/B,gCAA+B;GAAI;CtDq7LjE;;AsD56LD;EACE;IAAwB,yBAAwB;GAAI;EACpD;IAAwB,2BAA0B;GAAI;EACtD;IAAwB,iCAAgC;GAAI;EAC5D;IAAwB,0BAAyB;GAAI;EACrD;IAAwB,0BAAyB;GAAI;EACrD;IAAwB,8BAA6B;GAAI;EACzD;IAAwB,+BAA8B;GAAI;EAC1D;IAAwB,gCAAwB;IAAxB,yBAAwB;GAAI;EACpD;IAAwB,uCAA+B;IAA/B,gCAA+B;GAAI;CtDi8L5D;;AuDn+LD;EACE,mBAAkB;EAClB,eAAc;EACd,YAAW;EACX,WAAU;EACV,iBAAgB;CAoBjB;;AAzBD;EAQI,eAAc;EACd,YAAW;CACZ;;AAVH;;;;;EAiBI,mBAAkB;EAClB,OAAM;EACN,UAAS;EACT,QAAO;EACP,YAAW;EACX,aAAY;EACZ,UAAS;CACV;;AAGH;EAEI,wBAA+B;CAChC;;AAGH;EAEI,oBAA+B;CAChC;;AAGH;EAEI,iBAA8B;CAC/B;;AAGH;EAEI,kBAA8B;CAC/B;;ACxCC;EAAgC,mCAA8B;EAA9B,+BAA8B;CAAI;;AAClE;EAAgC,sCAAiC;EAAjC,kCAAiC;CAAI;;AACrE;EAAgC,2CAAsC;EAAtC,uCAAsC;CAAI;;AAC1E;EAAgC,8CAAyC;EAAzC,0CAAyC;CAAI;;AAE7E;EAA8B,+BAA0B;EAA1B,2BAA0B;CAAI;;AAC5D;EAA8B,iCAA4B;EAA5B,6BAA4B;CAAI;;AAC9D;EAA8B,uCAAkC;EAAlC,mCAAkC;CAAI;;AACpE;EAA8B,8BAAyB;EAAzB,0BAAyB;CAAI;;AAC3D;EAA8B,gCAAuB;EAAvB,wBAAuB;CAAI;;AACzD;EAA8B,gCAAuB;EAAvB,wBAAuB;CAAI;;AACzD;EAA8B,gCAAyB;EAAzB,0BAAyB;CAAI;;AAC3D;EAA8B,gCAAyB;EAAzB,0BAAyB;CAAI;;AAE3D;EAAoC,gCAAsC;EAAtC,uCAAsC;CAAI;;AAC9E;EAAoC,8BAAoC;EAApC,qCAAoC;CAAI;;AAC5E;EAAoC,iCAAkC;EAAlC,mCAAkC;CAAI;;AAC1E;EAAoC,kCAAyC;EAAzC,0CAAyC;CAAI;;AACjF;EAAoC,qCAAwC;EAAxC,yCAAwC;CAAI;;AAEhF;EAAiC,iCAAkC;EAAlC,mCAAkC;CAAI;;AACvE;EAAiC,+BAAgC;EAAhC,iCAAgC;CAAI;;AACrE;EAAiC,kCAA8B;EAA9B,+BAA8B;CAAI;;AACnE;EAAiC,oCAAgC;EAAhC,iCAAgC;CAAI;;AACrE;EAAiC,mCAA+B;EAA/B,gCAA+B;CAAI;;AAEpE;EAAkC,qCAAoC;EAApC,qCAAoC;CAAI;;AAC1E;EAAkC,mCAAkC;EAAlC,mCAAkC;CAAI;;AACxE;EAAkC,sCAAgC;EAAhC,iCAAgC;CAAI;;AACtE;EAAkC,uCAAuC;EAAvC,wCAAuC;CAAI;;AAC7E;EAAkC,0CAAsC;EAAtC,uCAAsC;CAAI;;AAC5E;EAAkC,uCAAiC;EAAjC,kCAAiC;CAAI;;AAEvE;EAAgC,qCAA2B;EAA3B,4BAA2B;CAAI;;AAC/D;EAAgC,sCAAiC;EAAjC,kCAAiC;CAAI;;AACrE;EAAgC,oCAA+B;EAA/B,gCAA+B;CAAI;;AACnE;EAAgC,uCAA6B;EAA7B,8BAA6B;CAAI;;AACjE;EAAgC,yCAA+B;EAA/B,gCAA+B;CAAI;;AACnE;EAAgC,wCAA8B;EAA9B,+BAA8B;CAAI;;A9CYlE;E8ClDA;IAAgC,mCAA8B;IAA9B,+BAA8B;GAAI;EAClE;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,2CAAsC;IAAtC,uCAAsC;GAAI;EAC1E;IAAgC,8CAAyC;IAAzC,0CAAyC;GAAI;EAE7E;IAA8B,+BAA0B;IAA1B,2BAA0B;GAAI;EAC5D;IAA8B,iCAA4B;IAA5B,6BAA4B;GAAI;EAC9D;IAA8B,uCAAkC;IAAlC,mCAAkC;GAAI;EACpE;IAA8B,8BAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAE3D;IAAoC,gCAAsC;IAAtC,uCAAsC;GAAI;EAC9E;IAAoC,8BAAoC;IAApC,qCAAoC;GAAI;EAC5E;IAAoC,iCAAkC;IAAlC,mCAAkC;GAAI;EAC1E;IAAoC,kCAAyC;IAAzC,0CAAyC;GAAI;EACjF;IAAoC,qCAAwC;IAAxC,yCAAwC;GAAI;EAEhF;IAAiC,iCAAkC;IAAlC,mCAAkC;GAAI;EACvE;IAAiC,+BAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,kCAA8B;IAA9B,+BAA8B;GAAI;EACnE;IAAiC,oCAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,mCAA+B;IAA/B,gCAA+B;GAAI;EAEpE;IAAkC,qCAAoC;IAApC,qCAAoC;GAAI;EAC1E;IAAkC,mCAAkC;IAAlC,mCAAkC;GAAI;EACxE;IAAkC,sCAAgC;IAAhC,iCAAgC;GAAI;EACtE;IAAkC,uCAAuC;IAAvC,wCAAuC;GAAI;EAC7E;IAAkC,0CAAsC;IAAtC,uCAAsC;GAAI;EAC5E;IAAkC,uCAAiC;IAAjC,kCAAiC;GAAI;EAEvE;IAAgC,qCAA2B;IAA3B,4BAA2B;GAAI;EAC/D;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,oCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,uCAA6B;IAA7B,8BAA6B;GAAI;EACjE;IAAgC,yCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,wCAA8B;IAA9B,+BAA8B;GAAI;CxDitMrE;;AUrsMG;E8ClDA;IAAgC,mCAA8B;IAA9B,+BAA8B;GAAI;EAClE;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,2CAAsC;IAAtC,uCAAsC;GAAI;EAC1E;IAAgC,8CAAyC;IAAzC,0CAAyC;GAAI;EAE7E;IAA8B,+BAA0B;IAA1B,2BAA0B;GAAI;EAC5D;IAA8B,iCAA4B;IAA5B,6BAA4B;GAAI;EAC9D;IAA8B,uCAAkC;IAAlC,mCAAkC;GAAI;EACpE;IAA8B,8BAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAE3D;IAAoC,gCAAsC;IAAtC,uCAAsC;GAAI;EAC9E;IAAoC,8BAAoC;IAApC,qCAAoC;GAAI;EAC5E;IAAoC,iCAAkC;IAAlC,mCAAkC;GAAI;EAC1E;IAAoC,kCAAyC;IAAzC,0CAAyC;GAAI;EACjF;IAAoC,qCAAwC;IAAxC,yCAAwC;GAAI;EAEhF;IAAiC,iCAAkC;IAAlC,mCAAkC;GAAI;EACvE;IAAiC,+BAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,kCAA8B;IAA9B,+BAA8B;GAAI;EACnE;IAAiC,oCAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,mCAA+B;IAA/B,gCAA+B;GAAI;EAEpE;IAAkC,qCAAoC;IAApC,qCAAoC;GAAI;EAC1E;IAAkC,mCAAkC;IAAlC,mCAAkC;GAAI;EACxE;IAAkC,sCAAgC;IAAhC,iCAAgC;GAAI;EACtE;IAAkC,uCAAuC;IAAvC,wCAAuC;GAAI;EAC7E;IAAkC,0CAAsC;IAAtC,uCAAsC;GAAI;EAC5E;IAAkC,uCAAiC;IAAjC,kCAAiC;GAAI;EAEvE;IAAgC,qCAA2B;IAA3B,4BAA2B;GAAI;EAC/D;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,oCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,uCAA6B;IAA7B,8BAA6B;GAAI;EACjE;IAAgC,yCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,wCAA8B;IAA9B,+BAA8B;GAAI;CxD0zMrE;;AU9yMG;E8ClDA;IAAgC,mCAA8B;IAA9B,+BAA8B;GAAI;EAClE;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,2CAAsC;IAAtC,uCAAsC;GAAI;EAC1E;IAAgC,8CAAyC;IAAzC,0CAAyC;GAAI;EAE7E;IAA8B,+BAA0B;IAA1B,2BAA0B;GAAI;EAC5D;IAA8B,iCAA4B;IAA5B,6BAA4B;GAAI;EAC9D;IAA8B,uCAAkC;IAAlC,mCAAkC;GAAI;EACpE;IAA8B,8BAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAE3D;IAAoC,gCAAsC;IAAtC,uCAAsC;GAAI;EAC9E;IAAoC,8BAAoC;IAApC,qCAAoC;GAAI;EAC5E;IAAoC,iCAAkC;IAAlC,mCAAkC;GAAI;EAC1E;IAAoC,kCAAyC;IAAzC,0CAAyC;GAAI;EACjF;IAAoC,qCAAwC;IAAxC,yCAAwC;GAAI;EAEhF;IAAiC,iCAAkC;IAAlC,mCAAkC;GAAI;EACvE;IAAiC,+BAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,kCAA8B;IAA9B,+BAA8B;GAAI;EACnE;IAAiC,oCAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,mCAA+B;IAA/B,gCAA+B;GAAI;EAEpE;IAAkC,qCAAoC;IAApC,qCAAoC;GAAI;EAC1E;IAAkC,mCAAkC;IAAlC,mCAAkC;GAAI;EACxE;IAAkC,sCAAgC;IAAhC,iCAAgC;GAAI;EACtE;IAAkC,uCAAuC;IAAvC,wCAAuC;GAAI;EAC7E;IAAkC,0CAAsC;IAAtC,uCAAsC;GAAI;EAC5E;IAAkC,uCAAiC;IAAjC,kCAAiC;GAAI;EAEvE;IAAgC,qCAA2B;IAA3B,4BAA2B;GAAI;EAC/D;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,oCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,uCAA6B;IAA7B,8BAA6B;GAAI;EACjE;IAAgC,yCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,wCAA8B;IAA9B,+BAA8B;GAAI;CxDm6MrE;;AUv5MG;E8ClDA;IAAgC,mCAA8B;IAA9B,+BAA8B;GAAI;EAClE;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,2CAAsC;IAAtC,uCAAsC;GAAI;EAC1E;IAAgC,8CAAyC;IAAzC,0CAAyC;GAAI;EAE7E;IAA8B,+BAA0B;IAA1B,2BAA0B;GAAI;EAC5D;IAA8B,iCAA4B;IAA5B,6BAA4B;GAAI;EAC9D;IAA8B,uCAAkC;IAAlC,mCAAkC;GAAI;EACpE;IAA8B,8BAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAE3D;IAAoC,gCAAsC;IAAtC,uCAAsC;GAAI;EAC9E;IAAoC,8BAAoC;IAApC,qCAAoC;GAAI;EAC5E;IAAoC,iCAAkC;IAAlC,mCAAkC;GAAI;EAC1E;IAAoC,kCAAyC;IAAzC,0CAAyC;GAAI;EACjF;IAAoC,qCAAwC;IAAxC,yCAAwC;GAAI;EAEhF;IAAiC,iCAAkC;IAAlC,mCAAkC;GAAI;EACvE;IAAiC,+BAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,kCAA8B;IAA9B,+BAA8B;GAAI;EACnE;IAAiC,oCAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,mCAA+B;IAA/B,gCAA+B;GAAI;EAEpE;IAAkC,qCAAoC;IAApC,qCAAoC;GAAI;EAC1E;IAAkC,mCAAkC;IAAlC,mCAAkC;GAAI;EACxE;IAAkC,sCAAgC;IAAhC,iCAAgC;GAAI;EACtE;IAAkC,uCAAuC;IAAvC,wCAAuC;GAAI;EAC7E;IAAkC,0CAAsC;IAAtC,uCAAsC;GAAI;EAC5E;IAAkC,uCAAiC;IAAjC,kCAAiC;GAAI;EAEvE;IAAgC,qCAA2B;IAA3B,4BAA2B;GAAI;EAC/D;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,oCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,uCAA6B;IAA7B,8BAA6B;GAAI;EACjE;IAAgC,yCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,wCAA8B;IAA9B,+BAA8B;GAAI;CxD4gNrE;;AyDxjNG;ECDF,uBAAsB;CDC2B;;AAC/C;ECCF,wBAAuB;CDD2B;;AAChD;ECGF,uBAAsB;CDH2B;;A/CsD/C;E+CxDA;ICDF,uBAAsB;GDC2B;EAC/C;ICCF,wBAAuB;GDD2B;EAChD;ICGF,uBAAsB;GDH2B;CzD8kNlD;;AUxhNG;E+CxDA;ICDF,uBAAsB;GDC2B;EAC/C;ICCF,wBAAuB;GDD2B;EAChD;ICGF,uBAAsB;GDH2B;CzD0lNlD;;AUpiNG;E+CxDA;ICDF,uBAAsB;GDC2B;EAC/C;ICCF,wBAAuB;GDD2B;EAChD;ICGF,uBAAsB;GDH2B;CzDsmNlD;;AUhjNG;E+CxDA;ICDF,uBAAsB;GDC2B;EAC/C;ICCF,wBAAuB;GDD2B;EAChD;ICGF,uBAAsB;GDH2B;CzDknNlD;;A2D/mNC;EAAyB,4BAA8B;CAAI;;AAA3D;EAAyB,8BAA8B;CAAI;;AAA3D;EAAyB,8BAA8B;CAAI;;AAA3D;EAAyB,2BAA8B;CAAI;;AAA3D;EAAyB,oCAA8B;EAA9B,4BAA8B;CAAI;;AAK7D;EACE,gBAAe;EACf,OAAM;EACN,SAAQ;EACR,QAAO;EACP,c5DmlBsC;C4DllBvC;;AAED;EACE,gBAAe;EACf,SAAQ;EACR,UAAS;EACT,QAAO;EACP,c5D2kBsC;C4D1kBvC;;AAG6B;EAD9B;IAEI,yBAAgB;IAAhB,iBAAgB;IAChB,OAAM;IACN,c5DmkBoC;G4DjkBvC;C3DgoNA;;A4DhqND;ECEE,mBAAkB;EAClB,WAAU;EACV,YAAW;EACX,WAAU;EACV,iBAAgB;EAChB,uBAAsB;EACtB,oBAAmB;EACnB,UAAS;CDPV;;ACiBC;EAEE,iBAAgB;EAChB,YAAW;EACX,aAAY;EACZ,kBAAiB;EACjB,WAAU;EACV,oBAAmB;CACpB;;AC7BH;EAAa,+DAAqC;CAAI;;AACtD;EAAU,yDAAkC;CAAI;;AAChD;EAAa,wDAAqC;CAAI;;AACtD;EAAe,4BAA2B;CAAI;;ACC1C;EAAuB,sBAA4B;CAAI;;AAAvD;EAAuB,sBAA4B;CAAI;;AAAvD;EAAuB,sBAA4B;CAAI;;AAAvD;EAAuB,uBAA4B;CAAI;;AAAvD;EAAuB,uBAA4B;CAAI;;AAAvD;EAAuB,uBAA4B;CAAI;;AAAvD;EAAuB,uBAA4B;CAAI;;AAAvD;EAAuB,uBAA4B;CAAI;;AAAvD;EAAuB,wBAA4B;CAAI;;AAAvD;EAAuB,wBAA4B;CAAI;;AAI3D;EAAU,2BAA0B;CAAI;;AACxC;EAAU,4BAA2B;CAAI;;ACAjC;EAAgC,qBAA4B;CAAI;;AAChE;;EAEE,yBAAoC;CACrC;;AACD;;EAEE,2BAAwC;CACzC;;AACD;;EAEE,4BAA0C;CAC3C;;AACD;;EAEE,0BAAsC;CACvC;;AAhBD;EAAgC,2BAA4B;CAAI;;AAChE;;EAEE,+BAAoC;CACrC;;AACD;;EAEE,iCAAwC;CACzC;;AACD;;EAEE,kCAA0C;CAC3C;;AACD;;EAEE,gCAAsC;CACvC;;AAhBD;EAAgC,0BAA4B;CAAI;;AAChE;;EAEE,8BAAoC;CACrC;;AACD;;EAEE,gCAAwC;CACzC;;AACD;;EAEE,iCAA0C;CAC3C;;AACD;;EAEE,+BAAsC;CACvC;;AAhBD;EAAgC,wBAA4B;CAAI;;AAChE;;EAEE,4BAAoC;CACrC;;AACD;;EAEE,8BAAwC;CACzC;;AACD;;EAEE,+BAA0C;CAC3C;;AACD;;EAEE,6BAAsC;CACvC;;AAhBD;EAAgC,0BAA4B;CAAI;;AAChE;;EAEE,8BAAoC;CACrC;;AACD;;EAEE,gCAAwC;CACzC;;AACD;;EAEE,iCAA0C;CAC3C;;AACD;;EAEE,+BAAsC;CACvC;;AAhBD;EAAgC,wBAA4B;CAAI;;AAChE;;EAEE,4BAAoC;CACrC;;AACD;;EAEE,8BAAwC;CACzC;;AACD;;EAEE,+BAA0C;CAC3C;;AACD;;EAEE,6BAAsC;CACvC;;AAhBD;EAAgC,sBAA4B;CAAI;;AAChE;;EAEE,0BAAoC;CACrC;;AACD;;EAEE,4BAAwC;CACzC;;AACD;;EAEE,6BAA0C;CAC3C;;AACD;;EAEE,2BAAsC;CACvC;;AAhBD;EAAgC,4BAA4B;CAAI;;AAChE;;EAEE,gCAAoC;CACrC;;AACD;;EAEE,kCAAwC;CACzC;;AACD;;EAEE,mCAA0C;CAC3C;;AACD;;EAEE,iCAAsC;CACvC;;AAhBD;EAAgC,2BAA4B;CAAI;;AAChE;;EAEE,+BAAoC;CACrC;;AACD;;EAEE,iCAAwC;CACzC;;AACD;;EAEE,kCAA0C;CAC3C;;AACD;;EAEE,gCAAsC;CACvC;;AAhBD;EAAgC,yBAA4B;CAAI;;AAChE;;EAEE,6BAAoC;CACrC;;AACD;;EAEE,+BAAwC;CACzC;;AACD;;EAEE,gCAA0C;CAC3C;;AACD;;EAEE,8BAAsC;CACvC;;AAhBD;EAAgC,2BAA4B;CAAI;;AAChE;;EAEE,+BAAoC;CACrC;;AACD;;EAEE,iCAAwC;CACzC;;AACD;;EAEE,kCAA0C;CAC3C;;AACD;;EAEE,gCAAsC;CACvC;;AAhBD;EAAgC,yBAA4B;CAAI;;AAChE;;EAEE,6BAAoC;CACrC;;AACD;;EAEE,+BAAwC;CACzC;;AACD;;EAEE,gCAA0C;CAC3C;;AACD;;EAEE,8BAAsC;CACvC;;AAKL;EAAmB,wBAAuB;CAAI;;AAC9C;;EAEE,4BAA2B;CAC5B;;AACD;;EAEE,8BAA6B;CAC9B;;AACD;;EAEE,+BAA8B;CAC/B;;AACD;;EAEE,6BAA4B;CAC7B;;AtDYD;EsDjDI;IAAgC,qBAA4B;GAAI;EAChE;;IAEE,yBAAoC;GACrC;EACD;;IAEE,2BAAwC;GACzC;EACD;;IAEE,4BAA0C;GAC3C;EACD;;IAEE,0BAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,0BAA4B;GAAI;EAChE;;IAEE,8BAAoC;GACrC;EACD;;IAEE,gCAAwC;GACzC;EACD;;IAEE,iCAA0C;GAC3C;EACD;;IAEE,+BAAsC;GACvC;EAhBD;IAAgC,wBAA4B;GAAI;EAChE;;IAEE,4BAAoC;GACrC;EACD;;IAEE,8BAAwC;GACzC;EACD;;IAEE,+BAA0C;GAC3C;EACD;;IAEE,6BAAsC;GACvC;EAhBD;IAAgC,0BAA4B;GAAI;EAChE;;IAEE,8BAAoC;GACrC;EACD;;IAEE,gCAAwC;GACzC;EACD;;IAEE,iCAA0C;GAC3C;EACD;;IAEE,+BAAsC;GACvC;EAhBD;IAAgC,wBAA4B;GAAI;EAChE;;IAEE,4BAAoC;GACrC;EACD;;IAEE,8BAAwC;GACzC;EACD;;IAEE,+BAA0C;GAC3C;EACD;;IAEE,6BAAsC;GACvC;EAhBD;IAAgC,sBAA4B;GAAI;EAChE;;IAEE,0BAAoC;GACrC;EACD;;IAEE,4BAAwC;GACzC;EACD;;IAEE,6BAA0C;GAC3C;EACD;;IAEE,2BAAsC;GACvC;EAhBD;IAAgC,4BAA4B;GAAI;EAChE;;IAEE,gCAAoC;GACrC;EACD;;IAEE,kCAAwC;GACzC;EACD;;IAEE,mCAA0C;GAC3C;EACD;;IAEE,iCAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,yBAA4B;GAAI;EAChE;;IAEE,6BAAoC;GACrC;EACD;;IAEE,+BAAwC;GACzC;EACD;;IAEE,gCAA0C;GAC3C;EACD;;IAEE,8BAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,yBAA4B;GAAI;EAChE;;IAEE,6BAAoC;GACrC;EACD;;IAEE,+BAAwC;GACzC;EACD;;IAEE,gCAA0C;GAC3C;EACD;;IAEE,8BAAsC;GACvC;EAKL;IAAmB,wBAAuB;GAAI;EAC9C;;IAEE,4BAA2B;GAC5B;EACD;;IAEE,8BAA6B;GAC9B;EACD;;IAEE,+BAA8B;GAC/B;EACD;;IAEE,6BAA4B;GAC7B;ChE0vOJ;;AU9uOG;EsDjDI;IAAgC,qBAA4B;GAAI;EAChE;;IAEE,yBAAoC;GACrC;EACD;;IAEE,2BAAwC;GACzC;EACD;;IAEE,4BAA0C;GAC3C;EACD;;IAEE,0BAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,0BAA4B;GAAI;EAChE;;IAEE,8BAAoC;GACrC;EACD;;IAEE,gCAAwC;GACzC;EACD;;IAEE,iCAA0C;GAC3C;EACD;;IAEE,+BAAsC;GACvC;EAhBD;IAAgC,wBAA4B;GAAI;EAChE;;IAEE,4BAAoC;GACrC;EACD;;IAEE,8BAAwC;GACzC;EACD;;IAEE,+BAA0C;GAC3C;EACD;;IAEE,6BAAsC;GACvC;EAhBD;IAAgC,0BAA4B;GAAI;EAChE;;IAEE,8BAAoC;GACrC;EACD;;IAEE,gCAAwC;GACzC;EACD;;IAEE,iCAA0C;GAC3C;EACD;;IAEE,+BAAsC;GACvC;EAhBD;IAAgC,wBAA4B;GAAI;EAChE;;IAEE,4BAAoC;GACrC;EACD;;IAEE,8BAAwC;GACzC;EACD;;IAEE,+BAA0C;GAC3C;EACD;;IAEE,6BAAsC;GACvC;EAhBD;IAAgC,sBAA4B;GAAI;EAChE;;IAEE,0BAAoC;GACrC;EACD;;IAEE,4BAAwC;GACzC;EACD;;IAEE,6BAA0C;GAC3C;EACD;;IAEE,2BAAsC;GACvC;EAhBD;IAAgC,4BAA4B;GAAI;EAChE;;IAEE,gCAAoC;GACrC;EACD;;IAEE,kCAAwC;GACzC;EACD;;IAEE,mCAA0C;GAC3C;EACD;;IAEE,iCAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,yBAA4B;GAAI;EAChE;;IAEE,6BAAoC;GACrC;EACD;;IAEE,+BAAwC;GACzC;EACD;;IAEE,gCAA0C;GAC3C;EACD;;IAEE,8BAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,yBAA4B;GAAI;EAChE;;IAEE,6BAAoC;GACrC;EACD;;IAEE,+BAAwC;GACzC;EACD;;IAEE,gCAA0C;GAC3C;EACD;;IAEE,8BAAsC;GACvC;EAKL;IAAmB,wBAAuB;GAAI;EAC9C;;IAEE,4BAA2B;GAC5B;EACD;;IAEE,8BAA6B;GAC9B;EACD;;IAEE,+BAA8B;GAC/B;EACD;;IAEE,6BAA4B;GAC7B;ChEo/OJ;;AUx+OG;EsDjDI;IAAgC,qBAA4B;GAAI;EAChE;;IAEE,yBAAoC;GACrC;EACD;;IAEE,2BAAwC;GACzC;EACD;;IAEE,4BAA0C;GAC3C;EACD;;IAEE,0BAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,0BAA4B;GAAI;EAChE;;IAEE,8BAAoC;GACrC;EACD;;IAEE,gCAAwC;GACzC;EACD;;IAEE,iCAA0C;GAC3C;EACD;;IAEE,+BAAsC;GACvC;EAhBD;IAAgC,wBAA4B;GAAI;EAChE;;IAEE,4BAAoC;GACrC;EACD;;IAEE,8BAAwC;GACzC;EACD;;IAEE,+BAA0C;GAC3C;EACD;;IAEE,6BAAsC;GACvC;EAhBD;IAAgC,0BAA4B;GAAI;EAChE;;IAEE,8BAAoC;GACrC;EACD;;IAEE,gCAAwC;GACzC;EACD;;IAEE,iCAA0C;GAC3C;EACD;;IAEE,+BAAsC;GACvC;EAhBD;IAAgC,wBAA4B;GAAI;EAChE;;IAEE,4BAAoC;GACrC;EACD;;IAEE,8BAAwC;GACzC;EACD;;IAEE,+BAA0C;GAC3C;EACD;;IAEE,6BAAsC;GACvC;EAhBD;IAAgC,sBAA4B;GAAI;EAChE;;IAEE,0BAAoC;GACrC;EACD;;IAEE,4BAAwC;GACzC;EACD;;IAEE,6BAA0C;GAC3C;EACD;;IAEE,2BAAsC;GACvC;EAhBD;IAAgC,4BAA4B;GAAI;EAChE;;IAEE,gCAAoC;GACrC;EACD;;IAEE,kCAAwC;GACzC;EACD;;IAEE,mCAA0C;GAC3C;EACD;;IAEE,iCAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,yBAA4B;GAAI;EAChE;;IAEE,6BAAoC;GACrC;EACD;;IAEE,+BAAwC;GACzC;EACD;;IAEE,gCAA0C;GAC3C;EACD;;IAEE,8BAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,yBAA4B;GAAI;EAChE;;IAEE,6BAAoC;GACrC;EACD;;IAEE,+BAAwC;GACzC;EACD;;IAEE,gCAA0C;GAC3C;EACD;;IAEE,8BAAsC;GACvC;EAKL;IAAmB,wBAAuB;GAAI;EAC9C;;IAEE,4BAA2B;GAC5B;EACD;;IAEE,8BAA6B;GAC9B;EACD;;IAEE,+BAA8B;GAC/B;EACD;;IAEE,6BAA4B;GAC7B;ChE8uPJ;;AUluPG;EsDjDI;IAAgC,qBAA4B;GAAI;EAChE;;IAEE,yBAAoC;GACrC;EACD;;IAEE,2BAAwC;GACzC;EACD;;IAEE,4BAA0C;GAC3C;EACD;;IAEE,0BAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,0BAA4B;GAAI;EAChE;;IAEE,8BAAoC;GACrC;EACD;;IAEE,gCAAwC;GACzC;EACD;;IAEE,iCAA0C;GAC3C;EACD;;IAEE,+BAAsC;GACvC;EAhBD;IAAgC,wBAA4B;GAAI;EAChE;;IAEE,4BAAoC;GACrC;EACD;;IAEE,8BAAwC;GACzC;EACD;;IAEE,+BAA0C;GAC3C;EACD;;IAEE,6BAAsC;GACvC;EAhBD;IAAgC,0BAA4B;GAAI;EAChE;;IAEE,8BAAoC;GACrC;EACD;;IAEE,gCAAwC;GACzC;EACD;;IAEE,iCAA0C;GAC3C;EACD;;IAEE,+BAAsC;GACvC;EAhBD;IAAgC,wBAA4B;GAAI;EAChE;;IAEE,4BAAoC;GACrC;EACD;;IAEE,8BAAwC;GACzC;EACD;;IAEE,+BAA0C;GAC3C;EACD;;IAEE,6BAAsC;GACvC;EAhBD;IAAgC,sBAA4B;GAAI;EAChE;;IAEE,0BAAoC;GACrC;EACD;;IAEE,4BAAwC;GACzC;EACD;;IAEE,6BAA0C;GAC3C;EACD;;IAEE,2BAAsC;GACvC;EAhBD;IAAgC,4BAA4B;GAAI;EAChE;;IAEE,gCAAoC;GACrC;EACD;;IAEE,kCAAwC;GACzC;EACD;;IAEE,mCAA0C;GAC3C;EACD;;IAEE,iCAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,yBAA4B;GAAI;EAChE;;IAEE,6BAAoC;GACrC;EACD;;IAEE,+BAAwC;GACzC;EACD;;IAEE,gCAA0C;GAC3C;EACD;;IAEE,8BAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,yBAA4B;GAAI;EAChE;;IAEE,6BAAoC;GACrC;EACD;;IAEE,+BAAwC;GACzC;EACD;;IAEE,gCAA0C;GAC3C;EACD;;IAEE,8BAAsC;GACvC;EAKL;IAAmB,wBAAuB;GAAI;EAC9C;;IAEE,4BAA2B;GAC5B;EACD;;IAEE,8BAA6B;GAC9B;EACD;;IAEE,+BAA8B;GAC/B;EACD;;IAEE,6BAA4B;GAC7B;ChEw+PJ;;AiElhQD;EAAkB,kGlEqPgG;CkErPzD;;AAIzD;EAAiB,+BAA8B;CAAI;;AACnD;EAAiB,+BAA8B;CAAI;;AACnD;ECRE,iBAAgB;EAChB,wBAAuB;EACvB,oBAAmB;CDMsB;;AAQvC;EAAwB,4BAA2B;CAAI;;AACvD;EAAwB,6BAA4B;CAAI;;AACxD;EAAwB,8BAA6B;CAAI;;AvDsCzD;EuDxCA;IAAwB,4BAA2B;GAAI;EACvD;IAAwB,6BAA4B;GAAI;EACxD;IAAwB,8BAA6B;GAAI;CjE4iQ5D;;AUtgQG;EuDxCA;IAAwB,4BAA2B;GAAI;EACvD;IAAwB,6BAA4B;GAAI;EACxD;IAAwB,8BAA6B;GAAI;CjEwjQ5D;;AUlhQG;EuDxCA;IAAwB,4BAA2B;GAAI;EACvD;IAAwB,6BAA4B;GAAI;EACxD;IAAwB,8BAA6B;GAAI;CjEokQ5D;;AU9hQG;EuDxCA;IAAwB,4BAA2B;GAAI;EACvD;IAAwB,6BAA4B;GAAI;EACxD;IAAwB,8BAA6B;GAAI;CjEglQ5D;;AiE1kQD;EAAmB,qCAAoC;CAAI;;AAC3D;EAAmB,qCAAoC;CAAI;;AAC3D;EAAmB,sCAAqC;CAAI;;AAI5D;EAAsB,4BAA0C;CAAI;;AACpE;EAAsB,4BAA2C;CAAI;;AACrE;EAAsB,4BAAyC;CAAI;;AACnE;EAAsB,8BAA6B;CAAI;;AAIvD;EAAc,uBAAwB;CAAI;;AEpCxC;EACE,0BAAwB;CACzB;;AlESD;EkENI,0BAAqC;ClESxC;;AkEdD;EACE,0BAAwB;CACzB;;AlESD;EkENI,0BAAqC;ClESxC;;AkEdD;EACE,0BAAwB;CACzB;;AlESD;EkENI,0BAAqC;ClESxC;;AkEdD;EACE,0BAAwB;CACzB;;AlESD;EkENI,0BAAqC;ClESxC;;AkEdD;EACE,0BAAwB;CACzB;;AlESD;EkENI,0BAAqC;ClESxC;;AkEdD;EACE,0BAAwB;CACzB;;AlESD;EkENI,0BAAqC;ClESxC;;AkEdD;EACE,0BAAwB;CACzB;;AlESD;EkENI,0BAAqC;ClESxC;;AkEdD;EACE,0BAAwB;CACzB;;AlESD;EkENI,0BAAqC;ClESxC;;AgE4BH;EAAa,0BAA6B;CAAI;;AAC9C;EAAc,0BAA6B;CAAI;;AAE/C;EAAiB,qCAAkC;CAAI;;AACvD;EAAiB,2CAAkC;CAAI;;AAIvD;EGpDE,YAAW;EACX,mBAAkB;EAClB,kBAAiB;EACjB,8BAA6B;EAC7B,UAAS;CHkDV;;AIrDD;ECCE,+BAAkC;CDCnC;;AAED;ECHE,8BAAkC;CDKnC;;AECC;EzESF;;;IyEHM,6BAA4B;IAE5B,4BAA2B;GAC5B;EAED;IAEI,2BAA0B;GAC3B;EAQH;IACE,8BAA6B;GAC9B;EzE+ML;IyEjMM,iCAAgC;GACjC;EACD;;IAEE,0BxEtCY;IwEuCZ,yBAAwB;GACzB;EAOD;IACE,4BAA2B;GAC5B;EAED;;IAEE,yBAAwB;GACzB;EAED;;;IAGE,WAAU;IACV,UAAS;GACV;EAED;;IAEE,wBAAuB;GACxB;EAOD;IACE,SxE61BgC;GC01OnC;EFxtQH;IyEoCM,4BAA2C;GAC5C;E/DxFH;I+D0FI,4BAA2C;GAC5C;E1C/EL;I0CmFM,cAAa;GACd;ErChGL;IqCkGM,uBxEnFS;GwEoFV;E3DpGL;I2DuGM,qCAAoC;GAMrC;EAPD;;IAKI,kCAAmC;GACpC;E3DjEP;;I2DuEQ,qCAAsC;GACvC;E3DYP;I2DRM,eAAc;GAQf;EATD;;;;IAOI,sBxEpHU;GwEqHX;E3DjBP;I2DqBM,eAAc;IACd,sBxE1HY;GwE2Hb;CvE6qQJ","file":"bootstrap.css","sourcesContent":["/*!\n * Bootstrap v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n@import \"functions\";\n@import \"variables\";\n@import \"mixins\";\n@import \"root\";\n@import \"reboot\";\n@import \"type\";\n@import \"images\";\n@import \"code\";\n@import \"grid\";\n@import \"tables\";\n@import \"forms\";\n@import \"buttons\";\n@import \"transitions\";\n@import \"dropdown\";\n@import \"button-group\";\n@import \"input-group\";\n@import \"custom-forms\";\n@import \"nav\";\n@import \"navbar\";\n@import \"card\";\n@import \"breadcrumb\";\n@import \"pagination\";\n@import \"badge\";\n@import \"jumbotron\";\n@import \"alert\";\n@import \"progress\";\n@import \"media\";\n@import \"list-group\";\n@import \"close\";\n@import \"modal\";\n@import \"tooltip\";\n@import \"popover\";\n@import \"carousel\";\n@import \"utilities\";\n@import \"print\";\n",":root {\n // Custom variable values only support SassScript inside `#{}`.\n @each $color, $value in $colors {\n --#{$color}: #{$value};\n }\n\n @each $color, $value in $theme-colors {\n --#{$color}: #{$value};\n }\n\n @each $bp, $value in $grid-breakpoints {\n --breakpoint-#{$bp}: #{$value};\n }\n\n // Use `inspect` for lists so that quoted items keep the quotes.\n // See https://github.com/sass/sass/issues/2383#issuecomment-336349172\n --font-family-sans-serif: #{inspect($font-family-sans-serif)};\n --font-family-monospace: #{inspect($font-family-monospace)};\n}\n","// stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix\n\n// Reboot\n//\n// Normalization of HTML elements, manually forked from Normalize.css to remove\n// styles targeting irrelevant browsers while applying new styles.\n//\n// Normalize is licensed MIT. https://github.com/necolas/normalize.css\n\n\n// Document\n//\n// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.\n// 2. Change the default font family in all browsers.\n// 3. Correct the line height in all browsers.\n// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.\n// 5. Setting @viewport causes scrollbars to overlap content in IE11 and Edge, so\n// we force a non-overlapping, non-auto-hiding scrollbar to counteract.\n// 6. Change the default tap highlight to be completely transparent in iOS.\n\n*,\n*::before,\n*::after {\n box-sizing: border-box; // 1\n}\n\nhtml {\n font-family: sans-serif; // 2\n line-height: 1.15; // 3\n -webkit-text-size-adjust: 100%; // 4\n -ms-text-size-adjust: 100%; // 4\n -ms-overflow-style: scrollbar; // 5\n -webkit-tap-highlight-color: rgba($black, 0); // 6\n}\n\n// IE10+ doesn't honor `` in some cases.\n@at-root {\n @-ms-viewport {\n width: device-width;\n }\n}\n\n// stylelint-disable selector-list-comma-newline-after\n// Shim for \"new\" HTML5 structural elements to display correctly (IE10, older browsers)\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n// stylelint-enable selector-list-comma-newline-after\n\n// Body\n//\n// 1. Remove the margin in all browsers.\n// 2. As a best practice, apply a default `background-color`.\n// 3. Set an explicit initial text-align value so that we can later use the\n// the `inherit` value on things like `` elements.\n\nbody {\n margin: 0; // 1\n font-family: $font-family-base;\n font-size: $font-size-base;\n font-weight: $font-weight-base;\n line-height: $line-height-base;\n color: $body-color;\n text-align: left; // 3\n background-color: $body-bg; // 2\n}\n\n// Suppress the focus outline on elements that cannot be accessed via keyboard.\n// This prevents an unwanted focus outline from appearing around elements that\n// might still respond to pointer events.\n//\n// Credit: https://github.com/suitcss/base\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\n\n// Content grouping\n//\n// 1. Add the correct box sizing in Firefox.\n// 2. Show the overflow in Edge and IE.\n\nhr {\n box-sizing: content-box; // 1\n height: 0; // 1\n overflow: visible; // 2\n}\n\n\n//\n// Typography\n//\n\n// Remove top margins from headings\n//\n// By default, `

    `-`

    ` all receive top and bottom margins. We nuke the top\n// margin for easier control within type scales as it avoids margin collapsing.\n// stylelint-disable selector-list-comma-newline-after\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: $headings-margin-bottom;\n}\n// stylelint-enable selector-list-comma-newline-after\n\n// Reset margins on paragraphs\n//\n// Similarly, the top margin on `

    `s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n// Abbreviations\n//\n// 1. Remove the bottom border in Firefox 39-.\n// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Duplicate behavior to the data-* attribute for our tooltip plugin\n\nabbr[title],\nabbr[data-original-title] { // 4\n text-decoration: underline; // 2\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n border-bottom: 0; // 1\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // Undo browser default\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\ndfn {\n font-style: italic; // Add the correct font style in Android 4.3-\n}\n\n// stylelint-disable font-weight-notation\nb,\nstrong {\n font-weight: bolder; // Add the correct font weight in Chrome, Edge, and Safari\n}\n// stylelint-enable font-weight-notation\n\nsmall {\n font-size: 80%; // Add the correct font size in all browsers\n}\n\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n//\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n//\n// Links\n//\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n background-color: transparent; // Remove the gray background on active links in IE 10.\n -webkit-text-decoration-skip: objects; // Remove gaps in links underline in iOS 8+ and Safari 8+.\n\n @include hover {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href)\n// which have not been made explicitly keyboard-focusable (without tabindex).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n\n @include hover-focus {\n color: inherit;\n text-decoration: none;\n }\n\n &:focus {\n outline: 0;\n }\n}\n\n\n//\n// Code\n//\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-monospace;\n font-size: 1em; // Correct the odd `em` font sizing in all browsers.\n}\n\npre {\n // Remove browser default top margin\n margin-top: 0;\n // Reset browser default of `1em` to use `rem`s\n margin-bottom: 1rem;\n // Don't allow content to break outside\n overflow: auto;\n // We have @viewport set which causes scrollbars to overlap content in IE11 and Edge, so\n // we force a non-overlapping, non-auto-hiding scrollbar to counteract.\n -ms-overflow-style: scrollbar;\n}\n\n\n//\n// Figures\n//\n\nfigure {\n // Apply a consistent margin strategy (matches our type styles).\n margin: 0 0 1rem;\n}\n\n\n//\n// Images and content\n//\n\nimg {\n vertical-align: middle;\n border-style: none; // Remove the border on images inside links in IE 10-.\n}\n\nsvg {\n // Workaround for the SVG overflow bug in IE10/11 is still required.\n // See https://github.com/twbs/bootstrap/issues/26878\n overflow: hidden;\n vertical-align: middle;\n}\n\n\n//\n// Tables\n//\n\ntable {\n border-collapse: collapse; // Prevent double borders\n}\n\ncaption {\n padding-top: $table-cell-padding;\n padding-bottom: $table-cell-padding;\n color: $table-caption-color;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n // Matches default `` alignment by inheriting from the ``, or the\n // closest parent with a set `text-align`.\n text-align: inherit;\n}\n\n\n//\n// Forms\n//\n\nlabel {\n // Allow labels to use `margin` for spacing.\n display: inline-block;\n margin-bottom: $label-margin-bottom;\n}\n\n// Remove the default `border-radius` that macOS Chrome adds.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24093\nbutton {\n border-radius: 0;\n}\n\n// Work around a Firefox/IE bug where the transparent `button` background\n// results in a loss of the default `button` focus styles.\n//\n// Credit: https://github.com/suitcss/base/\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0; // Remove the margin in Firefox and Safari\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible; // Show the overflow in Edge\n}\n\nbutton,\nselect {\n text-transform: none; // Remove the inheritance of text transform in Firefox\n}\n\n// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`\n// controls in Android 4.\n// 2. Correct the inability to style clickable types in iOS and Safari.\nbutton,\nhtml [type=\"button\"], // 1\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button; // 2\n}\n\n// Remove inner border and padding from Firefox, but don't restore the outline like Normalize.\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box; // 1. Add the correct box sizing in IE 10-\n padding: 0; // 2. Remove the padding in IE 10-\n}\n\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n // Remove the default appearance of temporal inputs to avoid a Mobile Safari\n // bug where setting a custom line-height prevents text from being vertically\n // centered within the input.\n // See https://bugs.webkit.org/show_bug.cgi?id=139848\n // and https://github.com/twbs/bootstrap/issues/11266\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto; // Remove the default vertical scrollbar in IE.\n // Textareas should really only resize vertically so they don't break their (horizontal) containers.\n resize: vertical;\n}\n\nfieldset {\n // Browsers set a default `min-width: min-content;` on fieldsets,\n // unlike e.g. `

    `s, which have `min-width: 0;` by default.\n // So we reset that to ensure fieldsets behave more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359\n // and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements\n min-width: 0;\n // Reset the default outline behavior of fieldsets so they don't affect page layout.\n padding: 0;\n margin: 0;\n border: 0;\n}\n\n// 1. Correct the text wrapping in Edge and IE.\n// 2. Correct the color inheritance from `fieldset` elements in IE.\nlegend {\n display: block;\n width: 100%;\n max-width: 100%; // 1\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit; // 2\n white-space: normal; // 1\n}\n\nprogress {\n vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera.\n}\n\n// Correct the cursor style of increment and decrement buttons in Chrome.\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n // This overrides the extra rounded corners on search inputs in iOS so that our\n // `.form-control` class can properly style them. Note that this cannot simply\n // be added to `.form-control` as it's not specific enough. For details, see\n // https://github.com/twbs/bootstrap/issues/11586.\n outline-offset: -2px; // 2. Correct the outline style in Safari.\n -webkit-appearance: none;\n}\n\n//\n// Remove the inner padding and cancel buttons in Chrome and Safari on macOS.\n//\n\n[type=\"search\"]::-webkit-search-cancel-button,\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// 1. Correct the inability to style clickable types in iOS and Safari.\n// 2. Change font properties to `inherit` in Safari.\n//\n\n::-webkit-file-upload-button {\n font: inherit; // 2\n -webkit-appearance: button; // 1\n}\n\n//\n// Correct element displays\n//\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item; // Add the correct display in all browsers\n cursor: pointer;\n}\n\ntemplate {\n display: none; // Add the correct display in IE\n}\n\n// Always hide an element with the `hidden` HTML attribute (from PureCSS).\n// Needed for proper display in IE 10-.\n[hidden] {\n display: none !important;\n}\n","// Variables\n//\n// Variables should follow the `$component-state-property-size` formula for\n// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs.\n\n\n//\n// Color system\n//\n\n$white: #fff !default;\n$gray-100: #f8f9fa !default;\n$gray-200: #e9ecef !default;\n$gray-300: #dee2e6 !default;\n$gray-400: #ced4da !default;\n$gray-500: #adb5bd !default;\n$gray-600: #6c757d !default;\n$gray-700: #495057 !default;\n$gray-800: #343a40 !default;\n$gray-900: #212529 !default;\n$black: #000 !default;\n\n$grays: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$grays: map-merge(\n (\n \"100\": $gray-100,\n \"200\": $gray-200,\n \"300\": $gray-300,\n \"400\": $gray-400,\n \"500\": $gray-500,\n \"600\": $gray-600,\n \"700\": $gray-700,\n \"800\": $gray-800,\n \"900\": $gray-900\n ),\n $grays\n);\n\n\n$blue: #007bff !default;\n$indigo: #6610f2 !default;\n$purple: #6f42c1 !default;\n$pink: #e83e8c !default;\n$red: #dc3545 !default;\n$orange: #fd7e14 !default;\n$yellow: #ffc107 !default;\n$green: #28a745 !default;\n$teal: #20c997 !default;\n$cyan: #17a2b8 !default;\n\n$colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$colors: map-merge(\n (\n \"blue\": $blue,\n \"indigo\": $indigo,\n \"purple\": $purple,\n \"pink\": $pink,\n \"red\": $red,\n \"orange\": $orange,\n \"yellow\": $yellow,\n \"green\": $green,\n \"teal\": $teal,\n \"cyan\": $cyan,\n \"white\": $white,\n \"gray\": $gray-600,\n \"gray-dark\": $gray-800\n ),\n $colors\n);\n\n$primary: $blue !default;\n$secondary: $gray-600 !default;\n$success: $green !default;\n$info: $cyan !default;\n$warning: $yellow !default;\n$danger: $red !default;\n$light: $gray-100 !default;\n$dark: $gray-800 !default;\n\n$theme-colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$theme-colors: map-merge(\n (\n \"primary\": $primary,\n \"secondary\": $secondary,\n \"success\": $success,\n \"info\": $info,\n \"warning\": $warning,\n \"danger\": $danger,\n \"light\": $light,\n \"dark\": $dark\n ),\n $theme-colors\n);\n\n// Set a specific jump point for requesting color jumps\n$theme-color-interval: 8% !default;\n\n// The yiq lightness value that determines when the lightness of color changes from \"dark\" to \"light\". Acceptable values are between 0 and 255.\n$yiq-contrasted-threshold: 150 !default;\n\n// Customize the light and dark text colors for use in our YIQ color contrast function.\n$yiq-text-dark: $gray-900 !default;\n$yiq-text-light: $white !default;\n\n// Options\n//\n// Quickly modify global styling by enabling or disabling optional features.\n\n$enable-caret: true !default;\n$enable-rounded: true !default;\n$enable-shadows: false !default;\n$enable-gradients: false !default;\n$enable-transitions: true !default;\n$enable-hover-media-query: false !default; // Deprecated, no longer affects any compiled CSS\n$enable-grid-classes: true !default;\n$enable-print-styles: true !default;\n\n\n// Spacing\n//\n// Control the default styling of most Bootstrap elements by modifying these\n// variables. Mostly focused on spacing.\n// You can add more entries to the $spacers map, should you need more variation.\n\n$spacer: 1rem !default;\n$spacers: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$spacers: map-merge(\n (\n 0: 0,\n 1: ($spacer * .25),\n 2: ($spacer * .5),\n 3: $spacer,\n 4: ($spacer * 1.5),\n 5: ($spacer * 3)\n ),\n $spacers\n);\n\n// This variable affects the `.h-*` and `.w-*` classes.\n$sizes: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$sizes: map-merge(\n (\n 25: 25%,\n 50: 50%,\n 75: 75%,\n 100: 100%,\n auto: auto\n ),\n $sizes\n);\n\n// Body\n//\n// Settings for the `` element.\n\n$body-bg: $white !default;\n$body-color: $gray-900 !default;\n\n// Links\n//\n// Style anchor elements.\n\n$link-color: theme-color(\"primary\") !default;\n$link-decoration: none !default;\n$link-hover-color: darken($link-color, 15%) !default;\n$link-hover-decoration: underline !default;\n\n// Paragraphs\n//\n// Style p element.\n\n$paragraph-margin-bottom: 1rem !default;\n\n\n// Grid breakpoints\n//\n// Define the minimum dimensions at which your layout will change,\n// adapting to different screen sizes, for use in media queries.\n\n$grid-breakpoints: (\n xs: 0,\n sm: 576px,\n md: 768px,\n lg: 992px,\n xl: 1200px\n) !default;\n\n@include _assert-ascending($grid-breakpoints, \"$grid-breakpoints\");\n@include _assert-starts-at-zero($grid-breakpoints);\n\n\n// Grid containers\n//\n// Define the maximum width of `.container` for different screen sizes.\n\n$container-max-widths: (\n sm: 540px,\n md: 720px,\n lg: 960px,\n xl: 1140px\n) !default;\n\n@include _assert-ascending($container-max-widths, \"$container-max-widths\");\n\n\n// Grid columns\n//\n// Set the number of columns and specify the width of the gutters.\n\n$grid-columns: 12 !default;\n$grid-gutter-width: 30px !default;\n\n// Components\n//\n// Define common padding and border radius sizes and more.\n\n$line-height-lg: 1.5 !default;\n$line-height-sm: 1.5 !default;\n\n$border-width: 1px !default;\n$border-color: $gray-300 !default;\n\n$border-radius: .25rem !default;\n$border-radius-lg: .3rem !default;\n$border-radius-sm: .2rem !default;\n\n$box-shadow-sm: 0 .125rem .25rem rgba($black, .075) !default;\n$box-shadow: 0 .5rem 1rem rgba($black, .15) !default;\n$box-shadow-lg: 0 1rem 3rem rgba($black, .175) !default;\n\n$component-active-color: $white !default;\n$component-active-bg: theme-color(\"primary\") !default;\n\n$caret-width: .3em !default;\n\n$transition-base: all .2s ease-in-out !default;\n$transition-fade: opacity .15s linear !default;\n$transition-collapse: height .35s ease !default;\n\n\n// Fonts\n//\n// Font, line-height, and color for body text, headings, and more.\n\n// stylelint-disable value-keyword-case\n$font-family-sans-serif: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\" !default;\n$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace !default;\n$font-family-base: $font-family-sans-serif !default;\n// stylelint-enable value-keyword-case\n\n$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`\n$font-size-lg: ($font-size-base * 1.25) !default;\n$font-size-sm: ($font-size-base * .875) !default;\n\n$font-weight-light: 300 !default;\n$font-weight-normal: 400 !default;\n$font-weight-bold: 700 !default;\n\n$font-weight-base: $font-weight-normal !default;\n$line-height-base: 1.5 !default;\n\n$h1-font-size: $font-size-base * 2.5 !default;\n$h2-font-size: $font-size-base * 2 !default;\n$h3-font-size: $font-size-base * 1.75 !default;\n$h4-font-size: $font-size-base * 1.5 !default;\n$h5-font-size: $font-size-base * 1.25 !default;\n$h6-font-size: $font-size-base !default;\n\n$headings-margin-bottom: ($spacer / 2) !default;\n$headings-font-family: inherit !default;\n$headings-font-weight: 500 !default;\n$headings-line-height: 1.2 !default;\n$headings-color: inherit !default;\n\n$display1-size: 6rem !default;\n$display2-size: 5.5rem !default;\n$display3-size: 4.5rem !default;\n$display4-size: 3.5rem !default;\n\n$display1-weight: 300 !default;\n$display2-weight: 300 !default;\n$display3-weight: 300 !default;\n$display4-weight: 300 !default;\n$display-line-height: $headings-line-height !default;\n\n$lead-font-size: ($font-size-base * 1.25) !default;\n$lead-font-weight: 300 !default;\n\n$small-font-size: 80% !default;\n\n$text-muted: $gray-600 !default;\n\n$blockquote-small-color: $gray-600 !default;\n$blockquote-font-size: ($font-size-base * 1.25) !default;\n\n$hr-border-color: rgba($black, .1) !default;\n$hr-border-width: $border-width !default;\n\n$mark-padding: .2em !default;\n\n$dt-font-weight: $font-weight-bold !default;\n\n$kbd-box-shadow: inset 0 -.1rem 0 rgba($black, .25) !default;\n$nested-kbd-font-weight: $font-weight-bold !default;\n\n$list-inline-padding: .5rem !default;\n\n$mark-bg: #fcf8e3 !default;\n\n$hr-margin-y: $spacer !default;\n\n\n// Tables\n//\n// Customizes the `.table` component with basic values, each used across all table variations.\n\n$table-cell-padding: .75rem !default;\n$table-cell-padding-sm: .3rem !default;\n\n$table-bg: transparent !default;\n$table-accent-bg: rgba($black, .05) !default;\n$table-hover-bg: rgba($black, .075) !default;\n$table-active-bg: $table-hover-bg !default;\n\n$table-border-width: $border-width !default;\n$table-border-color: $gray-300 !default;\n\n$table-head-bg: $gray-200 !default;\n$table-head-color: $gray-700 !default;\n\n$table-dark-bg: $gray-900 !default;\n$table-dark-accent-bg: rgba($white, .05) !default;\n$table-dark-hover-bg: rgba($white, .075) !default;\n$table-dark-border-color: lighten($gray-900, 7.5%) !default;\n$table-dark-color: $body-bg !default;\n\n$table-striped-order: odd !default;\n\n$table-caption-color: $text-muted !default;\n\n// Buttons + Forms\n//\n// Shared variables that are reassigned to `$input-` and `$btn-` specific variables.\n\n$input-btn-padding-y: .375rem !default;\n$input-btn-padding-x: .75rem !default;\n$input-btn-line-height: $line-height-base !default;\n\n$input-btn-focus-width: .2rem !default;\n$input-btn-focus-color: rgba($component-active-bg, .25) !default;\n$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default;\n\n$input-btn-padding-y-sm: .25rem !default;\n$input-btn-padding-x-sm: .5rem !default;\n$input-btn-line-height-sm: $line-height-sm !default;\n\n$input-btn-padding-y-lg: .5rem !default;\n$input-btn-padding-x-lg: 1rem !default;\n$input-btn-line-height-lg: $line-height-lg !default;\n\n$input-btn-border-width: $border-width !default;\n\n\n// Buttons\n//\n// For each of Bootstrap's buttons, define text, background, and border color.\n\n$btn-padding-y: $input-btn-padding-y !default;\n$btn-padding-x: $input-btn-padding-x !default;\n$btn-line-height: $input-btn-line-height !default;\n\n$btn-padding-y-sm: $input-btn-padding-y-sm !default;\n$btn-padding-x-sm: $input-btn-padding-x-sm !default;\n$btn-line-height-sm: $input-btn-line-height-sm !default;\n\n$btn-padding-y-lg: $input-btn-padding-y-lg !default;\n$btn-padding-x-lg: $input-btn-padding-x-lg !default;\n$btn-line-height-lg: $input-btn-line-height-lg !default;\n\n$btn-border-width: $input-btn-border-width !default;\n\n$btn-font-weight: $font-weight-normal !default;\n$btn-box-shadow: inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default;\n$btn-focus-width: $input-btn-focus-width !default;\n$btn-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$btn-disabled-opacity: .65 !default;\n$btn-active-box-shadow: inset 0 3px 5px rgba($black, .125) !default;\n\n$btn-link-disabled-color: $gray-600 !default;\n\n$btn-block-spacing-y: .5rem !default;\n\n// Allows for customizing button radius independently from global border radius\n$btn-border-radius: $border-radius !default;\n$btn-border-radius-lg: $border-radius-lg !default;\n$btn-border-radius-sm: $border-radius-sm !default;\n\n$btn-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n\n// Forms\n\n$label-margin-bottom: .5rem !default;\n\n$input-padding-y: $input-btn-padding-y !default;\n$input-padding-x: $input-btn-padding-x !default;\n$input-line-height: $input-btn-line-height !default;\n\n$input-padding-y-sm: $input-btn-padding-y-sm !default;\n$input-padding-x-sm: $input-btn-padding-x-sm !default;\n$input-line-height-sm: $input-btn-line-height-sm !default;\n\n$input-padding-y-lg: $input-btn-padding-y-lg !default;\n$input-padding-x-lg: $input-btn-padding-x-lg !default;\n$input-line-height-lg: $input-btn-line-height-lg !default;\n\n$input-bg: $white !default;\n$input-disabled-bg: $gray-200 !default;\n\n$input-color: $gray-700 !default;\n$input-border-color: $gray-400 !default;\n$input-border-width: $input-btn-border-width !default;\n$input-box-shadow: inset 0 1px 1px rgba($black, .075) !default;\n\n$input-border-radius: $border-radius !default;\n$input-border-radius-lg: $border-radius-lg !default;\n$input-border-radius-sm: $border-radius-sm !default;\n\n$input-focus-bg: $input-bg !default;\n$input-focus-border-color: lighten($component-active-bg, 25%) !default;\n$input-focus-color: $input-color !default;\n$input-focus-width: $input-btn-focus-width !default;\n$input-focus-box-shadow: $input-btn-focus-box-shadow !default;\n\n$input-placeholder-color: $gray-600 !default;\n$input-plaintext-color: $body-color !default;\n\n$input-height-border: $input-border-width * 2 !default;\n\n$input-height-inner: ($font-size-base * $input-btn-line-height) + ($input-btn-padding-y * 2) !default;\n$input-height: calc(#{$input-height-inner} + #{$input-height-border}) !default;\n\n$input-height-inner-sm: ($font-size-sm * $input-btn-line-height-sm) + ($input-btn-padding-y-sm * 2) !default;\n$input-height-sm: calc(#{$input-height-inner-sm} + #{$input-height-border}) !default;\n\n$input-height-inner-lg: ($font-size-lg * $input-btn-line-height-lg) + ($input-btn-padding-y-lg * 2) !default;\n$input-height-lg: calc(#{$input-height-inner-lg} + #{$input-height-border}) !default;\n\n$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$form-text-margin-top: .25rem !default;\n\n$form-check-input-gutter: 1.25rem !default;\n$form-check-input-margin-y: .3rem !default;\n$form-check-input-margin-x: .25rem !default;\n\n$form-check-inline-margin-x: .75rem !default;\n$form-check-inline-input-margin-x: .3125rem !default;\n\n$form-group-margin-bottom: 1rem !default;\n\n$input-group-addon-color: $input-color !default;\n$input-group-addon-bg: $gray-200 !default;\n$input-group-addon-border-color: $input-border-color !default;\n\n$custom-forms-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$custom-control-gutter: 1.5rem !default;\n$custom-control-spacer-x: 1rem !default;\n\n$custom-control-indicator-size: 1rem !default;\n$custom-control-indicator-bg: $gray-300 !default;\n$custom-control-indicator-bg-size: 50% 50% !default;\n$custom-control-indicator-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;\n\n$custom-control-indicator-disabled-bg: $gray-200 !default;\n$custom-control-label-disabled-color: $gray-600 !default;\n\n$custom-control-indicator-checked-color: $component-active-color !default;\n$custom-control-indicator-checked-bg: $component-active-bg !default;\n$custom-control-indicator-checked-disabled-bg: rgba(theme-color(\"primary\"), .5) !default;\n$custom-control-indicator-checked-box-shadow: none !default;\n\n$custom-control-indicator-focus-box-shadow: 0 0 0 1px $body-bg, $input-btn-focus-box-shadow !default;\n\n$custom-control-indicator-active-color: $component-active-color !default;\n$custom-control-indicator-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-control-indicator-active-box-shadow: none !default;\n\n$custom-checkbox-indicator-border-radius: $border-radius !default;\n$custom-checkbox-indicator-icon-checked: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n\n$custom-checkbox-indicator-indeterminate-bg: $component-active-bg !default;\n$custom-checkbox-indicator-indeterminate-color: $custom-control-indicator-checked-color !default;\n$custom-checkbox-indicator-icon-indeterminate: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$custom-checkbox-indicator-indeterminate-box-shadow: none !default;\n\n$custom-radio-indicator-border-radius: 50% !default;\n$custom-radio-indicator-icon-checked: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='#{$custom-control-indicator-checked-color}'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n\n$custom-select-padding-y: .375rem !default;\n$custom-select-padding-x: .75rem !default;\n$custom-select-height: $input-height !default;\n$custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator\n$custom-select-line-height: $input-btn-line-height !default;\n$custom-select-color: $input-color !default;\n$custom-select-disabled-color: $gray-600 !default;\n$custom-select-bg: $input-bg !default;\n$custom-select-disabled-bg: $gray-200 !default;\n$custom-select-bg-size: 8px 10px !default; // In pixels because image dimensions\n$custom-select-indicator-color: $gray-800 !default;\n$custom-select-indicator: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$custom-select-border-width: $input-btn-border-width !default;\n$custom-select-border-color: $input-border-color !default;\n$custom-select-border-radius: $border-radius !default;\n$custom-select-box-shadow: inset 0 1px 2px rgba($black, .075) !default;\n\n$custom-select-focus-border-color: $input-focus-border-color !default;\n$custom-select-focus-width: $input-btn-focus-width !default;\n$custom-select-focus-box-shadow: 0 0 0 $custom-select-focus-width rgba($custom-select-focus-border-color, .5) !default;\n\n$custom-select-font-size-sm: 75% !default;\n$custom-select-height-sm: $input-height-sm !default;\n\n$custom-select-font-size-lg: 125% !default;\n$custom-select-height-lg: $input-height-lg !default;\n\n$custom-range-track-width: 100% !default;\n$custom-range-track-height: .5rem !default;\n$custom-range-track-cursor: pointer !default;\n$custom-range-track-bg: $gray-300 !default;\n$custom-range-track-border-radius: 1rem !default;\n$custom-range-track-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;\n\n$custom-range-thumb-width: 1rem !default;\n$custom-range-thumb-height: $custom-range-thumb-width !default;\n$custom-range-thumb-bg: $component-active-bg !default;\n$custom-range-thumb-border: 0 !default;\n$custom-range-thumb-border-radius: 1rem !default;\n$custom-range-thumb-box-shadow: 0 .1rem .25rem rgba($black, .1) !default;\n$custom-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-btn-focus-box-shadow !default;\n$custom-range-thumb-focus-box-shadow-width: $input-btn-focus-width !default; // For focus box shadow issue in IE/Edge\n$custom-range-thumb-active-bg: lighten($component-active-bg, 35%) !default;\n\n$custom-file-height: $input-height !default;\n$custom-file-height-inner: $input-height-inner !default;\n$custom-file-focus-border-color: $input-focus-border-color !default;\n$custom-file-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$custom-file-disabled-bg: $input-disabled-bg !default;\n\n$custom-file-padding-y: $input-btn-padding-y !default;\n$custom-file-padding-x: $input-btn-padding-x !default;\n$custom-file-line-height: $input-btn-line-height !default;\n$custom-file-color: $input-color !default;\n$custom-file-bg: $input-bg !default;\n$custom-file-border-width: $input-btn-border-width !default;\n$custom-file-border-color: $input-border-color !default;\n$custom-file-border-radius: $input-border-radius !default;\n$custom-file-box-shadow: $input-box-shadow !default;\n$custom-file-button-color: $custom-file-color !default;\n$custom-file-button-bg: $input-group-addon-bg !default;\n$custom-file-text: (\n en: \"Browse\"\n) !default;\n\n\n// Form validation\n$form-feedback-margin-top: $form-text-margin-top !default;\n$form-feedback-font-size: $small-font-size !default;\n$form-feedback-valid-color: theme-color(\"success\") !default;\n$form-feedback-invalid-color: theme-color(\"danger\") !default;\n\n\n// Dropdowns\n//\n// Dropdown menu container and contents.\n\n$dropdown-min-width: 10rem !default;\n$dropdown-padding-y: .5rem !default;\n$dropdown-spacer: .125rem !default;\n$dropdown-bg: $white !default;\n$dropdown-border-color: rgba($black, .15) !default;\n$dropdown-border-radius: $border-radius !default;\n$dropdown-border-width: $border-width !default;\n$dropdown-divider-bg: $gray-200 !default;\n$dropdown-box-shadow: 0 .5rem 1rem rgba($black, .175) !default;\n\n$dropdown-link-color: $gray-900 !default;\n$dropdown-link-hover-color: darken($gray-900, 5%) !default;\n$dropdown-link-hover-bg: $gray-100 !default;\n\n$dropdown-link-active-color: $component-active-color !default;\n$dropdown-link-active-bg: $component-active-bg !default;\n\n$dropdown-link-disabled-color: $gray-600 !default;\n\n$dropdown-item-padding-y: .25rem !default;\n$dropdown-item-padding-x: 1.5rem !default;\n\n$dropdown-header-color: $gray-600 !default;\n\n\n// Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n\n$zindex-dropdown: 1000 !default;\n$zindex-sticky: 1020 !default;\n$zindex-fixed: 1030 !default;\n$zindex-modal-backdrop: 1040 !default;\n$zindex-modal: 1050 !default;\n$zindex-popover: 1060 !default;\n$zindex-tooltip: 1070 !default;\n\n// Navs\n\n$nav-link-padding-y: .5rem !default;\n$nav-link-padding-x: 1rem !default;\n$nav-link-disabled-color: $gray-600 !default;\n\n$nav-tabs-border-color: $gray-300 !default;\n$nav-tabs-border-width: $border-width !default;\n$nav-tabs-border-radius: $border-radius !default;\n$nav-tabs-link-hover-border-color: $gray-200 $gray-200 $nav-tabs-border-color !default;\n$nav-tabs-link-active-color: $gray-700 !default;\n$nav-tabs-link-active-bg: $body-bg !default;\n$nav-tabs-link-active-border-color: $gray-300 $gray-300 $nav-tabs-link-active-bg !default;\n\n$nav-pills-border-radius: $border-radius !default;\n$nav-pills-link-active-color: $component-active-color !default;\n$nav-pills-link-active-bg: $component-active-bg !default;\n\n$nav-divider-color: $gray-200 !default;\n$nav-divider-margin-y: ($spacer / 2) !default;\n\n// Navbar\n\n$navbar-padding-y: ($spacer / 2) !default;\n$navbar-padding-x: $spacer !default;\n\n$navbar-nav-link-padding-x: .5rem !default;\n\n$navbar-brand-font-size: $font-size-lg !default;\n// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link\n$nav-link-height: ($font-size-base * $line-height-base + $nav-link-padding-y * 2) !default;\n$navbar-brand-height: $navbar-brand-font-size * $line-height-base !default;\n$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) / 2 !default;\n\n$navbar-toggler-padding-y: .25rem !default;\n$navbar-toggler-padding-x: .75rem !default;\n$navbar-toggler-font-size: $font-size-lg !default;\n$navbar-toggler-border-radius: $btn-border-radius !default;\n\n$navbar-dark-color: rgba($white, .5) !default;\n$navbar-dark-hover-color: rgba($white, .75) !default;\n$navbar-dark-active-color: $white !default;\n$navbar-dark-disabled-color: rgba($white, .25) !default;\n$navbar-dark-toggler-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$navbar-dark-toggler-border-color: rgba($white, .1) !default;\n\n$navbar-light-color: rgba($black, .5) !default;\n$navbar-light-hover-color: rgba($black, .7) !default;\n$navbar-light-active-color: rgba($black, .9) !default;\n$navbar-light-disabled-color: rgba($black, .3) !default;\n$navbar-light-toggler-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$navbar-light-toggler-border-color: rgba($black, .1) !default;\n\n// Pagination\n\n$pagination-padding-y: .5rem !default;\n$pagination-padding-x: .75rem !default;\n$pagination-padding-y-sm: .25rem !default;\n$pagination-padding-x-sm: .5rem !default;\n$pagination-padding-y-lg: .75rem !default;\n$pagination-padding-x-lg: 1.5rem !default;\n$pagination-line-height: 1.25 !default;\n\n$pagination-color: $link-color !default;\n$pagination-bg: $white !default;\n$pagination-border-width: $border-width !default;\n$pagination-border-color: $gray-300 !default;\n\n$pagination-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$pagination-focus-outline: 0 !default;\n\n$pagination-hover-color: $link-hover-color !default;\n$pagination-hover-bg: $gray-200 !default;\n$pagination-hover-border-color: $gray-300 !default;\n\n$pagination-active-color: $component-active-color !default;\n$pagination-active-bg: $component-active-bg !default;\n$pagination-active-border-color: $pagination-active-bg !default;\n\n$pagination-disabled-color: $gray-600 !default;\n$pagination-disabled-bg: $white !default;\n$pagination-disabled-border-color: $gray-300 !default;\n\n\n// Jumbotron\n\n$jumbotron-padding: 2rem !default;\n$jumbotron-bg: $gray-200 !default;\n\n\n// Cards\n\n$card-spacer-y: .75rem !default;\n$card-spacer-x: 1.25rem !default;\n$card-border-width: $border-width !default;\n$card-border-radius: $border-radius !default;\n$card-border-color: rgba($black, .125) !default;\n$card-inner-border-radius: calc(#{$card-border-radius} - #{$card-border-width}) !default;\n$card-cap-bg: rgba($black, .03) !default;\n$card-bg: $white !default;\n\n$card-img-overlay-padding: 1.25rem !default;\n\n$card-group-margin: ($grid-gutter-width / 2) !default;\n$card-deck-margin: $card-group-margin !default;\n\n$card-columns-count: 3 !default;\n$card-columns-gap: 1.25rem !default;\n$card-columns-margin: $card-spacer-y !default;\n\n\n// Tooltips\n\n$tooltip-font-size: $font-size-sm !default;\n$tooltip-max-width: 200px !default;\n$tooltip-color: $white !default;\n$tooltip-bg: $black !default;\n$tooltip-border-radius: $border-radius !default;\n$tooltip-opacity: .9 !default;\n$tooltip-padding-y: .25rem !default;\n$tooltip-padding-x: .5rem !default;\n$tooltip-margin: 0 !default;\n\n$tooltip-arrow-width: .8rem !default;\n$tooltip-arrow-height: .4rem !default;\n$tooltip-arrow-color: $tooltip-bg !default;\n\n\n// Popovers\n\n$popover-font-size: $font-size-sm !default;\n$popover-bg: $white !default;\n$popover-max-width: 276px !default;\n$popover-border-width: $border-width !default;\n$popover-border-color: rgba($black, .2) !default;\n$popover-border-radius: $border-radius-lg !default;\n$popover-box-shadow: 0 .25rem .5rem rgba($black, .2) !default;\n\n$popover-header-bg: darken($popover-bg, 3%) !default;\n$popover-header-color: $headings-color !default;\n$popover-header-padding-y: .5rem !default;\n$popover-header-padding-x: .75rem !default;\n\n$popover-body-color: $body-color !default;\n$popover-body-padding-y: $popover-header-padding-y !default;\n$popover-body-padding-x: $popover-header-padding-x !default;\n\n$popover-arrow-width: 1rem !default;\n$popover-arrow-height: .5rem !default;\n$popover-arrow-color: $popover-bg !default;\n\n$popover-arrow-outer-color: fade-in($popover-border-color, .05) !default;\n\n\n// Badges\n\n$badge-font-size: 75% !default;\n$badge-font-weight: $font-weight-bold !default;\n$badge-padding-y: .25em !default;\n$badge-padding-x: .4em !default;\n$badge-border-radius: $border-radius !default;\n\n$badge-pill-padding-x: .6em !default;\n// Use a higher than normal value to ensure completely rounded edges when\n// customizing padding or font-size on labels.\n$badge-pill-border-radius: 10rem !default;\n\n\n// Modals\n\n// Padding applied to the modal body\n$modal-inner-padding: 1rem !default;\n\n$modal-dialog-margin: .5rem !default;\n$modal-dialog-margin-y-sm-up: 1.75rem !default;\n\n$modal-title-line-height: $line-height-base !default;\n\n$modal-content-bg: $white !default;\n$modal-content-border-color: rgba($black, .2) !default;\n$modal-content-border-width: $border-width !default;\n$modal-content-border-radius: $border-radius-lg !default;\n$modal-content-box-shadow-xs: 0 .25rem .5rem rgba($black, .5) !default;\n$modal-content-box-shadow-sm-up: 0 .5rem 1rem rgba($black, .5) !default;\n\n$modal-backdrop-bg: $black !default;\n$modal-backdrop-opacity: .5 !default;\n$modal-header-border-color: $gray-200 !default;\n$modal-footer-border-color: $modal-header-border-color !default;\n$modal-header-border-width: $modal-content-border-width !default;\n$modal-footer-border-width: $modal-header-border-width !default;\n$modal-header-padding: 1rem !default;\n\n$modal-lg: 800px !default;\n$modal-md: 500px !default;\n$modal-sm: 300px !default;\n\n$modal-transition: transform .3s ease-out !default;\n\n\n// Alerts\n//\n// Define alert colors, border radius, and padding.\n\n$alert-padding-y: .75rem !default;\n$alert-padding-x: 1.25rem !default;\n$alert-margin-bottom: 1rem !default;\n$alert-border-radius: $border-radius !default;\n$alert-link-font-weight: $font-weight-bold !default;\n$alert-border-width: $border-width !default;\n\n$alert-bg-level: -10 !default;\n$alert-border-level: -9 !default;\n$alert-color-level: 6 !default;\n\n\n// Progress bars\n\n$progress-height: 1rem !default;\n$progress-font-size: ($font-size-base * .75) !default;\n$progress-bg: $gray-200 !default;\n$progress-border-radius: $border-radius !default;\n$progress-box-shadow: inset 0 .1rem .1rem rgba($black, .1) !default;\n$progress-bar-color: $white !default;\n$progress-bar-bg: theme-color(\"primary\") !default;\n$progress-bar-animation-timing: 1s linear infinite !default;\n$progress-bar-transition: width .6s ease !default;\n\n// List group\n\n$list-group-bg: $white !default;\n$list-group-border-color: rgba($black, .125) !default;\n$list-group-border-width: $border-width !default;\n$list-group-border-radius: $border-radius !default;\n\n$list-group-item-padding-y: .75rem !default;\n$list-group-item-padding-x: 1.25rem !default;\n\n$list-group-hover-bg: $gray-100 !default;\n$list-group-active-color: $component-active-color !default;\n$list-group-active-bg: $component-active-bg !default;\n$list-group-active-border-color: $list-group-active-bg !default;\n\n$list-group-disabled-color: $gray-600 !default;\n$list-group-disabled-bg: $list-group-bg !default;\n\n$list-group-action-color: $gray-700 !default;\n$list-group-action-hover-color: $list-group-action-color !default;\n\n$list-group-action-active-color: $body-color !default;\n$list-group-action-active-bg: $gray-200 !default;\n\n\n// Image thumbnails\n\n$thumbnail-padding: .25rem !default;\n$thumbnail-bg: $body-bg !default;\n$thumbnail-border-width: $border-width !default;\n$thumbnail-border-color: $gray-300 !default;\n$thumbnail-border-radius: $border-radius !default;\n$thumbnail-box-shadow: 0 1px 2px rgba($black, .075) !default;\n\n\n// Figures\n\n$figure-caption-font-size: 90% !default;\n$figure-caption-color: $gray-600 !default;\n\n\n// Breadcrumbs\n\n$breadcrumb-padding-y: .75rem !default;\n$breadcrumb-padding-x: 1rem !default;\n$breadcrumb-item-padding: .5rem !default;\n\n$breadcrumb-margin-bottom: 1rem !default;\n\n$breadcrumb-bg: $gray-200 !default;\n$breadcrumb-divider-color: $gray-600 !default;\n$breadcrumb-active-color: $gray-600 !default;\n$breadcrumb-divider: quote(\"/\") !default;\n\n$breadcrumb-border-radius: $border-radius !default;\n\n\n// Carousel\n\n$carousel-control-color: $white !default;\n$carousel-control-width: 15% !default;\n$carousel-control-opacity: .5 !default;\n\n$carousel-indicator-width: 30px !default;\n$carousel-indicator-height: 3px !default;\n$carousel-indicator-spacer: 3px !default;\n$carousel-indicator-active-bg: $white !default;\n\n$carousel-caption-width: 70% !default;\n$carousel-caption-color: $white !default;\n\n$carousel-control-icon-width: 20px !default;\n\n$carousel-control-prev-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$carousel-control-next-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n\n$carousel-transition: transform .6s ease !default; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)\n\n\n// Close\n\n$close-font-size: $font-size-base * 1.5 !default;\n$close-font-weight: $font-weight-bold !default;\n$close-color: $black !default;\n$close-text-shadow: 0 1px 0 $white !default;\n\n// Code\n\n$code-font-size: 87.5% !default;\n$code-color: $pink !default;\n\n$kbd-padding-y: .2rem !default;\n$kbd-padding-x: .4rem !default;\n$kbd-font-size: $code-font-size !default;\n$kbd-color: $white !default;\n$kbd-bg: $gray-900 !default;\n\n$pre-color: $gray-900 !default;\n$pre-scrollable-max-height: 340px !default;\n\n\n// Printing\n$print-page-size: a3 !default;\n$print-body-min-width: map-get($grid-breakpoints, \"lg\") !default;\n","/*!\n * Bootstrap v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n:root {\n --blue: #007bff;\n --indigo: #6610f2;\n --purple: #6f42c1;\n --pink: #e83e8c;\n --red: #dc3545;\n --orange: #fd7e14;\n --yellow: #ffc107;\n --green: #28a745;\n --teal: #20c997;\n --cyan: #17a2b8;\n --white: #fff;\n --gray: #6c757d;\n --gray-dark: #343a40;\n --primary: #007bff;\n --secondary: #6c757d;\n --success: #28a745;\n --info: #17a2b8;\n --warning: #ffc107;\n --danger: #dc3545;\n --light: #f8f9fa;\n --dark: #343a40;\n --breakpoint-xs: 0;\n --breakpoint-sm: 576px;\n --breakpoint-md: 768px;\n --breakpoint-lg: 992px;\n --breakpoint-xl: 1200px;\n --font-family-sans-serif: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nhtml {\n font-family: sans-serif;\n line-height: 1.15;\n -webkit-text-size-adjust: 100%;\n -ms-text-size-adjust: 100%;\n -ms-overflow-style: scrollbar;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\n@-ms-viewport {\n width: device-width;\n}\n\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\nbody {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n text-align: left;\n background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\nhr {\n box-sizing: content-box;\n height: 0;\n overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n text-decoration: underline;\n text-decoration: underline dotted;\n cursor: help;\n border-bottom: 0;\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: 700;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0;\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\ndfn {\n font-style: italic;\n}\n\nb,\nstrong {\n font-weight: bolder;\n}\n\nsmall {\n font-size: 80%;\n}\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -.25em;\n}\n\nsup {\n top: -.5em;\n}\n\na {\n color: #007bff;\n text-decoration: none;\n background-color: transparent;\n -webkit-text-decoration-skip: objects;\n}\n\na:hover {\n color: #0056b3;\n text-decoration: underline;\n}\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):focus {\n outline: 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 1em;\n}\n\npre {\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n -ms-overflow-style: scrollbar;\n}\n\nfigure {\n margin: 0 0 1rem;\n}\n\nimg {\n vertical-align: middle;\n border-style: none;\n}\n\nsvg {\n overflow: hidden;\n vertical-align: middle;\n}\n\ntable {\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n color: #6c757d;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n text-align: inherit;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 0.5rem;\n}\n\nbutton {\n border-radius: 0;\n}\n\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible;\n}\n\nbutton,\nselect {\n text-transform: none;\n}\n\nbutton,\nhtml [type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box;\n padding: 0;\n}\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto;\n resize: vertical;\n}\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n max-width: 100%;\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit;\n white-space: normal;\n}\n\nprogress {\n vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n outline-offset: -2px;\n -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-cancel-button,\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button;\n}\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n}\n\ntemplate {\n display: none;\n}\n\n[hidden] {\n display: none !important;\n}\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n margin-bottom: 0.5rem;\n font-family: inherit;\n font-weight: 500;\n line-height: 1.2;\n color: inherit;\n}\n\nh1, .h1 {\n font-size: 2.5rem;\n}\n\nh2, .h2 {\n font-size: 2rem;\n}\n\nh3, .h3 {\n font-size: 1.75rem;\n}\n\nh4, .h4 {\n font-size: 1.5rem;\n}\n\nh5, .h5 {\n font-size: 1.25rem;\n}\n\nh6, .h6 {\n font-size: 1rem;\n}\n\n.lead {\n font-size: 1.25rem;\n font-weight: 300;\n}\n\n.display-1 {\n font-size: 6rem;\n font-weight: 300;\n line-height: 1.2;\n}\n\n.display-2 {\n font-size: 5.5rem;\n font-weight: 300;\n line-height: 1.2;\n}\n\n.display-3 {\n font-size: 4.5rem;\n font-weight: 300;\n line-height: 1.2;\n}\n\n.display-4 {\n font-size: 3.5rem;\n font-weight: 300;\n line-height: 1.2;\n}\n\nhr {\n margin-top: 1rem;\n margin-bottom: 1rem;\n border: 0;\n border-top: 1px solid rgba(0, 0, 0, 0.1);\n}\n\nsmall,\n.small {\n font-size: 80%;\n font-weight: 400;\n}\n\nmark,\n.mark {\n padding: 0.2em;\n background-color: #fcf8e3;\n}\n\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n.list-inline {\n padding-left: 0;\n list-style: none;\n}\n\n.list-inline-item {\n display: inline-block;\n}\n\n.list-inline-item:not(:last-child) {\n margin-right: 0.5rem;\n}\n\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\n\n.blockquote {\n margin-bottom: 1rem;\n font-size: 1.25rem;\n}\n\n.blockquote-footer {\n display: block;\n font-size: 80%;\n color: #6c757d;\n}\n\n.blockquote-footer::before {\n content: \"\\2014 \\00A0\";\n}\n\n.img-fluid {\n max-width: 100%;\n height: auto;\n}\n\n.img-thumbnail {\n padding: 0.25rem;\n background-color: #fff;\n border: 1px solid #dee2e6;\n border-radius: 0.25rem;\n max-width: 100%;\n height: auto;\n}\n\n.figure {\n display: inline-block;\n}\n\n.figure-img {\n margin-bottom: 0.5rem;\n line-height: 1;\n}\n\n.figure-caption {\n font-size: 90%;\n color: #6c757d;\n}\n\ncode {\n font-size: 87.5%;\n color: #e83e8c;\n word-break: break-word;\n}\n\na > code {\n color: inherit;\n}\n\nkbd {\n padding: 0.2rem 0.4rem;\n font-size: 87.5%;\n color: #fff;\n background-color: #212529;\n border-radius: 0.2rem;\n}\n\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: 700;\n}\n\npre {\n display: block;\n font-size: 87.5%;\n color: #212529;\n}\n\npre code {\n font-size: inherit;\n color: inherit;\n word-break: normal;\n}\n\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n\n.container {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n@media (min-width: 576px) {\n .container {\n max-width: 540px;\n }\n}\n\n@media (min-width: 768px) {\n .container {\n max-width: 720px;\n }\n}\n\n@media (min-width: 992px) {\n .container {\n max-width: 960px;\n }\n}\n\n@media (min-width: 1200px) {\n .container {\n max-width: 1140px;\n }\n}\n\n.container-fluid {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n.row {\n display: flex;\n flex-wrap: wrap;\n margin-right: -15px;\n margin-left: -15px;\n}\n\n.no-gutters {\n margin-right: 0;\n margin-left: 0;\n}\n\n.no-gutters > .col,\n.no-gutters > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n}\n\n.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n position: relative;\n width: 100%;\n min-height: 1px;\n padding-right: 15px;\n padding-left: 15px;\n}\n\n.col {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n}\n\n.col-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n}\n\n.col-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n}\n\n.col-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n}\n\n.col-3 {\n flex: 0 0 25%;\n max-width: 25%;\n}\n\n.col-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n}\n\n.col-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n}\n\n.col-6 {\n flex: 0 0 50%;\n max-width: 50%;\n}\n\n.col-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n}\n\n.col-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n}\n\n.col-9 {\n flex: 0 0 75%;\n max-width: 75%;\n}\n\n.col-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n}\n\n.col-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n}\n\n.col-12 {\n flex: 0 0 100%;\n max-width: 100%;\n}\n\n.order-first {\n order: -1;\n}\n\n.order-last {\n order: 13;\n}\n\n.order-0 {\n order: 0;\n}\n\n.order-1 {\n order: 1;\n}\n\n.order-2 {\n order: 2;\n}\n\n.order-3 {\n order: 3;\n}\n\n.order-4 {\n order: 4;\n}\n\n.order-5 {\n order: 5;\n}\n\n.order-6 {\n order: 6;\n}\n\n.order-7 {\n order: 7;\n}\n\n.order-8 {\n order: 8;\n}\n\n.order-9 {\n order: 9;\n}\n\n.order-10 {\n order: 10;\n}\n\n.order-11 {\n order: 11;\n}\n\n.order-12 {\n order: 12;\n}\n\n.offset-1 {\n margin-left: 8.333333%;\n}\n\n.offset-2 {\n margin-left: 16.666667%;\n}\n\n.offset-3 {\n margin-left: 25%;\n}\n\n.offset-4 {\n margin-left: 33.333333%;\n}\n\n.offset-5 {\n margin-left: 41.666667%;\n}\n\n.offset-6 {\n margin-left: 50%;\n}\n\n.offset-7 {\n margin-left: 58.333333%;\n}\n\n.offset-8 {\n margin-left: 66.666667%;\n}\n\n.offset-9 {\n margin-left: 75%;\n}\n\n.offset-10 {\n margin-left: 83.333333%;\n}\n\n.offset-11 {\n margin-left: 91.666667%;\n}\n\n@media (min-width: 576px) {\n .col-sm {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-sm-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-sm-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-sm-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-sm-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-sm-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-sm-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-sm-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-sm-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-sm-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-sm-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-sm-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-sm-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-sm-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-sm-first {\n order: -1;\n }\n .order-sm-last {\n order: 13;\n }\n .order-sm-0 {\n order: 0;\n }\n .order-sm-1 {\n order: 1;\n }\n .order-sm-2 {\n order: 2;\n }\n .order-sm-3 {\n order: 3;\n }\n .order-sm-4 {\n order: 4;\n }\n .order-sm-5 {\n order: 5;\n }\n .order-sm-6 {\n order: 6;\n }\n .order-sm-7 {\n order: 7;\n }\n .order-sm-8 {\n order: 8;\n }\n .order-sm-9 {\n order: 9;\n }\n .order-sm-10 {\n order: 10;\n }\n .order-sm-11 {\n order: 11;\n }\n .order-sm-12 {\n order: 12;\n }\n .offset-sm-0 {\n margin-left: 0;\n }\n .offset-sm-1 {\n margin-left: 8.333333%;\n }\n .offset-sm-2 {\n margin-left: 16.666667%;\n }\n .offset-sm-3 {\n margin-left: 25%;\n }\n .offset-sm-4 {\n margin-left: 33.333333%;\n }\n .offset-sm-5 {\n margin-left: 41.666667%;\n }\n .offset-sm-6 {\n margin-left: 50%;\n }\n .offset-sm-7 {\n margin-left: 58.333333%;\n }\n .offset-sm-8 {\n margin-left: 66.666667%;\n }\n .offset-sm-9 {\n margin-left: 75%;\n }\n .offset-sm-10 {\n margin-left: 83.333333%;\n }\n .offset-sm-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 768px) {\n .col-md {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-md-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-md-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-md-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-md-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-md-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-md-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-md-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-md-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-md-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-md-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-md-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-md-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-md-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-md-first {\n order: -1;\n }\n .order-md-last {\n order: 13;\n }\n .order-md-0 {\n order: 0;\n }\n .order-md-1 {\n order: 1;\n }\n .order-md-2 {\n order: 2;\n }\n .order-md-3 {\n order: 3;\n }\n .order-md-4 {\n order: 4;\n }\n .order-md-5 {\n order: 5;\n }\n .order-md-6 {\n order: 6;\n }\n .order-md-7 {\n order: 7;\n }\n .order-md-8 {\n order: 8;\n }\n .order-md-9 {\n order: 9;\n }\n .order-md-10 {\n order: 10;\n }\n .order-md-11 {\n order: 11;\n }\n .order-md-12 {\n order: 12;\n }\n .offset-md-0 {\n margin-left: 0;\n }\n .offset-md-1 {\n margin-left: 8.333333%;\n }\n .offset-md-2 {\n margin-left: 16.666667%;\n }\n .offset-md-3 {\n margin-left: 25%;\n }\n .offset-md-4 {\n margin-left: 33.333333%;\n }\n .offset-md-5 {\n margin-left: 41.666667%;\n }\n .offset-md-6 {\n margin-left: 50%;\n }\n .offset-md-7 {\n margin-left: 58.333333%;\n }\n .offset-md-8 {\n margin-left: 66.666667%;\n }\n .offset-md-9 {\n margin-left: 75%;\n }\n .offset-md-10 {\n margin-left: 83.333333%;\n }\n .offset-md-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 992px) {\n .col-lg {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-lg-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-lg-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-lg-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-lg-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-lg-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-lg-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-lg-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-lg-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-lg-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-lg-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-lg-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-lg-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-lg-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-lg-first {\n order: -1;\n }\n .order-lg-last {\n order: 13;\n }\n .order-lg-0 {\n order: 0;\n }\n .order-lg-1 {\n order: 1;\n }\n .order-lg-2 {\n order: 2;\n }\n .order-lg-3 {\n order: 3;\n }\n .order-lg-4 {\n order: 4;\n }\n .order-lg-5 {\n order: 5;\n }\n .order-lg-6 {\n order: 6;\n }\n .order-lg-7 {\n order: 7;\n }\n .order-lg-8 {\n order: 8;\n }\n .order-lg-9 {\n order: 9;\n }\n .order-lg-10 {\n order: 10;\n }\n .order-lg-11 {\n order: 11;\n }\n .order-lg-12 {\n order: 12;\n }\n .offset-lg-0 {\n margin-left: 0;\n }\n .offset-lg-1 {\n margin-left: 8.333333%;\n }\n .offset-lg-2 {\n margin-left: 16.666667%;\n }\n .offset-lg-3 {\n margin-left: 25%;\n }\n .offset-lg-4 {\n margin-left: 33.333333%;\n }\n .offset-lg-5 {\n margin-left: 41.666667%;\n }\n .offset-lg-6 {\n margin-left: 50%;\n }\n .offset-lg-7 {\n margin-left: 58.333333%;\n }\n .offset-lg-8 {\n margin-left: 66.666667%;\n }\n .offset-lg-9 {\n margin-left: 75%;\n }\n .offset-lg-10 {\n margin-left: 83.333333%;\n }\n .offset-lg-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 1200px) {\n .col-xl {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-xl-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-xl-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-xl-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-xl-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-xl-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-xl-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-xl-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-xl-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-xl-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-xl-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-xl-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-xl-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-xl-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-xl-first {\n order: -1;\n }\n .order-xl-last {\n order: 13;\n }\n .order-xl-0 {\n order: 0;\n }\n .order-xl-1 {\n order: 1;\n }\n .order-xl-2 {\n order: 2;\n }\n .order-xl-3 {\n order: 3;\n }\n .order-xl-4 {\n order: 4;\n }\n .order-xl-5 {\n order: 5;\n }\n .order-xl-6 {\n order: 6;\n }\n .order-xl-7 {\n order: 7;\n }\n .order-xl-8 {\n order: 8;\n }\n .order-xl-9 {\n order: 9;\n }\n .order-xl-10 {\n order: 10;\n }\n .order-xl-11 {\n order: 11;\n }\n .order-xl-12 {\n order: 12;\n }\n .offset-xl-0 {\n margin-left: 0;\n }\n .offset-xl-1 {\n margin-left: 8.333333%;\n }\n .offset-xl-2 {\n margin-left: 16.666667%;\n }\n .offset-xl-3 {\n margin-left: 25%;\n }\n .offset-xl-4 {\n margin-left: 33.333333%;\n }\n .offset-xl-5 {\n margin-left: 41.666667%;\n }\n .offset-xl-6 {\n margin-left: 50%;\n }\n .offset-xl-7 {\n margin-left: 58.333333%;\n }\n .offset-xl-8 {\n margin-left: 66.666667%;\n }\n .offset-xl-9 {\n margin-left: 75%;\n }\n .offset-xl-10 {\n margin-left: 83.333333%;\n }\n .offset-xl-11 {\n margin-left: 91.666667%;\n }\n}\n\n.table {\n width: 100%;\n margin-bottom: 1rem;\n background-color: transparent;\n}\n\n.table th,\n.table td {\n padding: 0.75rem;\n vertical-align: top;\n border-top: 1px solid #dee2e6;\n}\n\n.table thead th {\n vertical-align: bottom;\n border-bottom: 2px solid #dee2e6;\n}\n\n.table tbody + tbody {\n border-top: 2px solid #dee2e6;\n}\n\n.table .table {\n background-color: #fff;\n}\n\n.table-sm th,\n.table-sm td {\n padding: 0.3rem;\n}\n\n.table-bordered {\n border: 1px solid #dee2e6;\n}\n\n.table-bordered th,\n.table-bordered td {\n border: 1px solid #dee2e6;\n}\n\n.table-bordered thead th,\n.table-bordered thead td {\n border-bottom-width: 2px;\n}\n\n.table-borderless th,\n.table-borderless td,\n.table-borderless thead th,\n.table-borderless tbody + tbody {\n border: 0;\n}\n\n.table-striped tbody tr:nth-of-type(odd) {\n background-color: rgba(0, 0, 0, 0.05);\n}\n\n.table-hover tbody tr:hover {\n background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table-primary,\n.table-primary > th,\n.table-primary > td {\n background-color: #b8daff;\n}\n\n.table-hover .table-primary:hover {\n background-color: #9fcdff;\n}\n\n.table-hover .table-primary:hover > td,\n.table-hover .table-primary:hover > th {\n background-color: #9fcdff;\n}\n\n.table-secondary,\n.table-secondary > th,\n.table-secondary > td {\n background-color: #d6d8db;\n}\n\n.table-hover .table-secondary:hover {\n background-color: #c8cbcf;\n}\n\n.table-hover .table-secondary:hover > td,\n.table-hover .table-secondary:hover > th {\n background-color: #c8cbcf;\n}\n\n.table-success,\n.table-success > th,\n.table-success > td {\n background-color: #c3e6cb;\n}\n\n.table-hover .table-success:hover {\n background-color: #b1dfbb;\n}\n\n.table-hover .table-success:hover > td,\n.table-hover .table-success:hover > th {\n background-color: #b1dfbb;\n}\n\n.table-info,\n.table-info > th,\n.table-info > td {\n background-color: #bee5eb;\n}\n\n.table-hover .table-info:hover {\n background-color: #abdde5;\n}\n\n.table-hover .table-info:hover > td,\n.table-hover .table-info:hover > th {\n background-color: #abdde5;\n}\n\n.table-warning,\n.table-warning > th,\n.table-warning > td {\n background-color: #ffeeba;\n}\n\n.table-hover .table-warning:hover {\n background-color: #ffe8a1;\n}\n\n.table-hover .table-warning:hover > td,\n.table-hover .table-warning:hover > th {\n background-color: #ffe8a1;\n}\n\n.table-danger,\n.table-danger > th,\n.table-danger > td {\n background-color: #f5c6cb;\n}\n\n.table-hover .table-danger:hover {\n background-color: #f1b0b7;\n}\n\n.table-hover .table-danger:hover > td,\n.table-hover .table-danger:hover > th {\n background-color: #f1b0b7;\n}\n\n.table-light,\n.table-light > th,\n.table-light > td {\n background-color: #fdfdfe;\n}\n\n.table-hover .table-light:hover {\n background-color: #ececf6;\n}\n\n.table-hover .table-light:hover > td,\n.table-hover .table-light:hover > th {\n background-color: #ececf6;\n}\n\n.table-dark,\n.table-dark > th,\n.table-dark > td {\n background-color: #c6c8ca;\n}\n\n.table-hover .table-dark:hover {\n background-color: #b9bbbe;\n}\n\n.table-hover .table-dark:hover > td,\n.table-hover .table-dark:hover > th {\n background-color: #b9bbbe;\n}\n\n.table-active,\n.table-active > th,\n.table-active > td {\n background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table-hover .table-active:hover {\n background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table-hover .table-active:hover > td,\n.table-hover .table-active:hover > th {\n background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table .thead-dark th {\n color: #fff;\n background-color: #212529;\n border-color: #32383e;\n}\n\n.table .thead-light th {\n color: #495057;\n background-color: #e9ecef;\n border-color: #dee2e6;\n}\n\n.table-dark {\n color: #fff;\n background-color: #212529;\n}\n\n.table-dark th,\n.table-dark td,\n.table-dark thead th {\n border-color: #32383e;\n}\n\n.table-dark.table-bordered {\n border: 0;\n}\n\n.table-dark.table-striped tbody tr:nth-of-type(odd) {\n background-color: rgba(255, 255, 255, 0.05);\n}\n\n.table-dark.table-hover tbody tr:hover {\n background-color: rgba(255, 255, 255, 0.075);\n}\n\n@media (max-width: 575.98px) {\n .table-responsive-sm {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n }\n .table-responsive-sm > .table-bordered {\n border: 0;\n }\n}\n\n@media (max-width: 767.98px) {\n .table-responsive-md {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n }\n .table-responsive-md > .table-bordered {\n border: 0;\n }\n}\n\n@media (max-width: 991.98px) {\n .table-responsive-lg {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n }\n .table-responsive-lg > .table-bordered {\n border: 0;\n }\n}\n\n@media (max-width: 1199.98px) {\n .table-responsive-xl {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n }\n .table-responsive-xl > .table-bordered {\n border: 0;\n }\n}\n\n.table-responsive {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n}\n\n.table-responsive > .table-bordered {\n border: 0;\n}\n\n.form-control {\n display: block;\n width: 100%;\n height: calc(2.25rem + 2px);\n padding: 0.375rem 0.75rem;\n font-size: 1rem;\n line-height: 1.5;\n color: #495057;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #ced4da;\n border-radius: 0.25rem;\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .form-control {\n transition: none;\n }\n}\n\n.form-control::-ms-expand {\n background-color: transparent;\n border: 0;\n}\n\n.form-control:focus {\n color: #495057;\n background-color: #fff;\n border-color: #80bdff;\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.form-control::placeholder {\n color: #6c757d;\n opacity: 1;\n}\n\n.form-control:disabled, .form-control[readonly] {\n background-color: #e9ecef;\n opacity: 1;\n}\n\nselect.form-control:focus::-ms-value {\n color: #495057;\n background-color: #fff;\n}\n\n.form-control-file,\n.form-control-range {\n display: block;\n width: 100%;\n}\n\n.col-form-label {\n padding-top: calc(0.375rem + 1px);\n padding-bottom: calc(0.375rem + 1px);\n margin-bottom: 0;\n font-size: inherit;\n line-height: 1.5;\n}\n\n.col-form-label-lg {\n padding-top: calc(0.5rem + 1px);\n padding-bottom: calc(0.5rem + 1px);\n font-size: 1.25rem;\n line-height: 1.5;\n}\n\n.col-form-label-sm {\n padding-top: calc(0.25rem + 1px);\n padding-bottom: calc(0.25rem + 1px);\n font-size: 0.875rem;\n line-height: 1.5;\n}\n\n.form-control-plaintext {\n display: block;\n width: 100%;\n padding-top: 0.375rem;\n padding-bottom: 0.375rem;\n margin-bottom: 0;\n line-height: 1.5;\n color: #212529;\n background-color: transparent;\n border: solid transparent;\n border-width: 1px 0;\n}\n\n.form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg {\n padding-right: 0;\n padding-left: 0;\n}\n\n.form-control-sm {\n height: calc(1.8125rem + 2px);\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5;\n border-radius: 0.2rem;\n}\n\n.form-control-lg {\n height: calc(2.875rem + 2px);\n padding: 0.5rem 1rem;\n font-size: 1.25rem;\n line-height: 1.5;\n border-radius: 0.3rem;\n}\n\nselect.form-control[size], select.form-control[multiple] {\n height: auto;\n}\n\ntextarea.form-control {\n height: auto;\n}\n\n.form-group {\n margin-bottom: 1rem;\n}\n\n.form-text {\n display: block;\n margin-top: 0.25rem;\n}\n\n.form-row {\n display: flex;\n flex-wrap: wrap;\n margin-right: -5px;\n margin-left: -5px;\n}\n\n.form-row > .col,\n.form-row > [class*=\"col-\"] {\n padding-right: 5px;\n padding-left: 5px;\n}\n\n.form-check {\n position: relative;\n display: block;\n padding-left: 1.25rem;\n}\n\n.form-check-input {\n position: absolute;\n margin-top: 0.3rem;\n margin-left: -1.25rem;\n}\n\n.form-check-input:disabled ~ .form-check-label {\n color: #6c757d;\n}\n\n.form-check-label {\n margin-bottom: 0;\n}\n\n.form-check-inline {\n display: inline-flex;\n align-items: center;\n padding-left: 0;\n margin-right: 0.75rem;\n}\n\n.form-check-inline .form-check-input {\n position: static;\n margin-top: 0;\n margin-right: 0.3125rem;\n margin-left: 0;\n}\n\n.valid-feedback {\n display: none;\n width: 100%;\n margin-top: 0.25rem;\n font-size: 80%;\n color: #28a745;\n}\n\n.valid-tooltip {\n position: absolute;\n top: 100%;\n z-index: 5;\n display: none;\n max-width: 100%;\n padding: 0.25rem 0.5rem;\n margin-top: .1rem;\n font-size: 0.875rem;\n line-height: 1.5;\n color: #fff;\n background-color: rgba(40, 167, 69, 0.9);\n border-radius: 0.25rem;\n}\n\n.was-validated .form-control:valid, .form-control.is-valid, .was-validated\n.custom-select:valid,\n.custom-select.is-valid {\n border-color: #28a745;\n}\n\n.was-validated .form-control:valid:focus, .form-control.is-valid:focus, .was-validated\n.custom-select:valid:focus,\n.custom-select.is-valid:focus {\n border-color: #28a745;\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);\n}\n\n.was-validated .form-control:valid ~ .valid-feedback,\n.was-validated .form-control:valid ~ .valid-tooltip, .form-control.is-valid ~ .valid-feedback,\n.form-control.is-valid ~ .valid-tooltip, .was-validated\n.custom-select:valid ~ .valid-feedback,\n.was-validated\n.custom-select:valid ~ .valid-tooltip,\n.custom-select.is-valid ~ .valid-feedback,\n.custom-select.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated .form-control-file:valid ~ .valid-feedback,\n.was-validated .form-control-file:valid ~ .valid-tooltip, .form-control-file.is-valid ~ .valid-feedback,\n.form-control-file.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label {\n color: #28a745;\n}\n\n.was-validated .form-check-input:valid ~ .valid-feedback,\n.was-validated .form-check-input:valid ~ .valid-tooltip, .form-check-input.is-valid ~ .valid-feedback,\n.form-check-input.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated .custom-control-input:valid ~ .custom-control-label, .custom-control-input.is-valid ~ .custom-control-label {\n color: #28a745;\n}\n\n.was-validated .custom-control-input:valid ~ .custom-control-label::before, .custom-control-input.is-valid ~ .custom-control-label::before {\n background-color: #71dd8a;\n}\n\n.was-validated .custom-control-input:valid ~ .valid-feedback,\n.was-validated .custom-control-input:valid ~ .valid-tooltip, .custom-control-input.is-valid ~ .valid-feedback,\n.custom-control-input.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated .custom-control-input:valid:checked ~ .custom-control-label::before, .custom-control-input.is-valid:checked ~ .custom-control-label::before {\n background-color: #34ce57;\n}\n\n.was-validated .custom-control-input:valid:focus ~ .custom-control-label::before, .custom-control-input.is-valid:focus ~ .custom-control-label::before {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(40, 167, 69, 0.25);\n}\n\n.was-validated .custom-file-input:valid ~ .custom-file-label, .custom-file-input.is-valid ~ .custom-file-label {\n border-color: #28a745;\n}\n\n.was-validated .custom-file-input:valid ~ .custom-file-label::after, .custom-file-input.is-valid ~ .custom-file-label::after {\n border-color: inherit;\n}\n\n.was-validated .custom-file-input:valid ~ .valid-feedback,\n.was-validated .custom-file-input:valid ~ .valid-tooltip, .custom-file-input.is-valid ~ .valid-feedback,\n.custom-file-input.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated .custom-file-input:valid:focus ~ .custom-file-label, .custom-file-input.is-valid:focus ~ .custom-file-label {\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);\n}\n\n.invalid-feedback {\n display: none;\n width: 100%;\n margin-top: 0.25rem;\n font-size: 80%;\n color: #dc3545;\n}\n\n.invalid-tooltip {\n position: absolute;\n top: 100%;\n z-index: 5;\n display: none;\n max-width: 100%;\n padding: 0.25rem 0.5rem;\n margin-top: .1rem;\n font-size: 0.875rem;\n line-height: 1.5;\n color: #fff;\n background-color: rgba(220, 53, 69, 0.9);\n border-radius: 0.25rem;\n}\n\n.was-validated .form-control:invalid, .form-control.is-invalid, .was-validated\n.custom-select:invalid,\n.custom-select.is-invalid {\n border-color: #dc3545;\n}\n\n.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus, .was-validated\n.custom-select:invalid:focus,\n.custom-select.is-invalid:focus {\n border-color: #dc3545;\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);\n}\n\n.was-validated .form-control:invalid ~ .invalid-feedback,\n.was-validated .form-control:invalid ~ .invalid-tooltip, .form-control.is-invalid ~ .invalid-feedback,\n.form-control.is-invalid ~ .invalid-tooltip, .was-validated\n.custom-select:invalid ~ .invalid-feedback,\n.was-validated\n.custom-select:invalid ~ .invalid-tooltip,\n.custom-select.is-invalid ~ .invalid-feedback,\n.custom-select.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated .form-control-file:invalid ~ .invalid-feedback,\n.was-validated .form-control-file:invalid ~ .invalid-tooltip, .form-control-file.is-invalid ~ .invalid-feedback,\n.form-control-file.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label {\n color: #dc3545;\n}\n\n.was-validated .form-check-input:invalid ~ .invalid-feedback,\n.was-validated .form-check-input:invalid ~ .invalid-tooltip, .form-check-input.is-invalid ~ .invalid-feedback,\n.form-check-input.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated .custom-control-input:invalid ~ .custom-control-label, .custom-control-input.is-invalid ~ .custom-control-label {\n color: #dc3545;\n}\n\n.was-validated .custom-control-input:invalid ~ .custom-control-label::before, .custom-control-input.is-invalid ~ .custom-control-label::before {\n background-color: #efa2a9;\n}\n\n.was-validated .custom-control-input:invalid ~ .invalid-feedback,\n.was-validated .custom-control-input:invalid ~ .invalid-tooltip, .custom-control-input.is-invalid ~ .invalid-feedback,\n.custom-control-input.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before, .custom-control-input.is-invalid:checked ~ .custom-control-label::before {\n background-color: #e4606d;\n}\n\n.was-validated .custom-control-input:invalid:focus ~ .custom-control-label::before, .custom-control-input.is-invalid:focus ~ .custom-control-label::before {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(220, 53, 69, 0.25);\n}\n\n.was-validated .custom-file-input:invalid ~ .custom-file-label, .custom-file-input.is-invalid ~ .custom-file-label {\n border-color: #dc3545;\n}\n\n.was-validated .custom-file-input:invalid ~ .custom-file-label::after, .custom-file-input.is-invalid ~ .custom-file-label::after {\n border-color: inherit;\n}\n\n.was-validated .custom-file-input:invalid ~ .invalid-feedback,\n.was-validated .custom-file-input:invalid ~ .invalid-tooltip, .custom-file-input.is-invalid ~ .invalid-feedback,\n.custom-file-input.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated .custom-file-input:invalid:focus ~ .custom-file-label, .custom-file-input.is-invalid:focus ~ .custom-file-label {\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);\n}\n\n.form-inline {\n display: flex;\n flex-flow: row wrap;\n align-items: center;\n}\n\n.form-inline .form-check {\n width: 100%;\n}\n\n@media (min-width: 576px) {\n .form-inline label {\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 0;\n }\n .form-inline .form-group {\n display: flex;\n flex: 0 0 auto;\n flex-flow: row wrap;\n align-items: center;\n margin-bottom: 0;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-plaintext {\n display: inline-block;\n }\n .form-inline .input-group,\n .form-inline .custom-select {\n width: auto;\n }\n .form-inline .form-check {\n display: flex;\n align-items: center;\n justify-content: center;\n width: auto;\n padding-left: 0;\n }\n .form-inline .form-check-input {\n position: relative;\n margin-top: 0;\n margin-right: 0.25rem;\n margin-left: 0;\n }\n .form-inline .custom-control {\n align-items: center;\n justify-content: center;\n }\n .form-inline .custom-control-label {\n margin-bottom: 0;\n }\n}\n\n.btn {\n display: inline-block;\n font-weight: 400;\n text-align: center;\n white-space: nowrap;\n vertical-align: middle;\n user-select: none;\n border: 1px solid transparent;\n padding: 0.375rem 0.75rem;\n font-size: 1rem;\n line-height: 1.5;\n border-radius: 0.25rem;\n transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .btn {\n transition: none;\n }\n}\n\n.btn:hover, .btn:focus {\n text-decoration: none;\n}\n\n.btn:focus, .btn.focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.btn.disabled, .btn:disabled {\n opacity: 0.65;\n}\n\n.btn:not(:disabled):not(.disabled) {\n cursor: pointer;\n}\n\na.btn.disabled,\nfieldset:disabled a.btn {\n pointer-events: none;\n}\n\n.btn-primary {\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.btn-primary:hover {\n color: #fff;\n background-color: #0069d9;\n border-color: #0062cc;\n}\n\n.btn-primary:focus, .btn-primary.focus {\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);\n}\n\n.btn-primary.disabled, .btn-primary:disabled {\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active,\n.show > .btn-primary.dropdown-toggle {\n color: #fff;\n background-color: #0062cc;\n border-color: #005cbf;\n}\n\n.btn-primary:not(:disabled):not(.disabled):active:focus, .btn-primary:not(:disabled):not(.disabled).active:focus,\n.show > .btn-primary.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);\n}\n\n.btn-secondary {\n color: #fff;\n background-color: #6c757d;\n border-color: #6c757d;\n}\n\n.btn-secondary:hover {\n color: #fff;\n background-color: #5a6268;\n border-color: #545b62;\n}\n\n.btn-secondary:focus, .btn-secondary.focus {\n box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);\n}\n\n.btn-secondary.disabled, .btn-secondary:disabled {\n color: #fff;\n background-color: #6c757d;\n border-color: #6c757d;\n}\n\n.btn-secondary:not(:disabled):not(.disabled):active, .btn-secondary:not(:disabled):not(.disabled).active,\n.show > .btn-secondary.dropdown-toggle {\n color: #fff;\n background-color: #545b62;\n border-color: #4e555b;\n}\n\n.btn-secondary:not(:disabled):not(.disabled):active:focus, .btn-secondary:not(:disabled):not(.disabled).active:focus,\n.show > .btn-secondary.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);\n}\n\n.btn-success {\n color: #fff;\n background-color: #28a745;\n border-color: #28a745;\n}\n\n.btn-success:hover {\n color: #fff;\n background-color: #218838;\n border-color: #1e7e34;\n}\n\n.btn-success:focus, .btn-success.focus {\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);\n}\n\n.btn-success.disabled, .btn-success:disabled {\n color: #fff;\n background-color: #28a745;\n border-color: #28a745;\n}\n\n.btn-success:not(:disabled):not(.disabled):active, .btn-success:not(:disabled):not(.disabled).active,\n.show > .btn-success.dropdown-toggle {\n color: #fff;\n background-color: #1e7e34;\n border-color: #1c7430;\n}\n\n.btn-success:not(:disabled):not(.disabled):active:focus, .btn-success:not(:disabled):not(.disabled).active:focus,\n.show > .btn-success.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);\n}\n\n.btn-info {\n color: #fff;\n background-color: #17a2b8;\n border-color: #17a2b8;\n}\n\n.btn-info:hover {\n color: #fff;\n background-color: #138496;\n border-color: #117a8b;\n}\n\n.btn-info:focus, .btn-info.focus {\n box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);\n}\n\n.btn-info.disabled, .btn-info:disabled {\n color: #fff;\n background-color: #17a2b8;\n border-color: #17a2b8;\n}\n\n.btn-info:not(:disabled):not(.disabled):active, .btn-info:not(:disabled):not(.disabled).active,\n.show > .btn-info.dropdown-toggle {\n color: #fff;\n background-color: #117a8b;\n border-color: #10707f;\n}\n\n.btn-info:not(:disabled):not(.disabled):active:focus, .btn-info:not(:disabled):not(.disabled).active:focus,\n.show > .btn-info.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);\n}\n\n.btn-warning {\n color: #212529;\n background-color: #ffc107;\n border-color: #ffc107;\n}\n\n.btn-warning:hover {\n color: #212529;\n background-color: #e0a800;\n border-color: #d39e00;\n}\n\n.btn-warning:focus, .btn-warning.focus {\n box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);\n}\n\n.btn-warning.disabled, .btn-warning:disabled {\n color: #212529;\n background-color: #ffc107;\n border-color: #ffc107;\n}\n\n.btn-warning:not(:disabled):not(.disabled):active, .btn-warning:not(:disabled):not(.disabled).active,\n.show > .btn-warning.dropdown-toggle {\n color: #212529;\n background-color: #d39e00;\n border-color: #c69500;\n}\n\n.btn-warning:not(:disabled):not(.disabled):active:focus, .btn-warning:not(:disabled):not(.disabled).active:focus,\n.show > .btn-warning.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);\n}\n\n.btn-danger {\n color: #fff;\n background-color: #dc3545;\n border-color: #dc3545;\n}\n\n.btn-danger:hover {\n color: #fff;\n background-color: #c82333;\n border-color: #bd2130;\n}\n\n.btn-danger:focus, .btn-danger.focus {\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);\n}\n\n.btn-danger.disabled, .btn-danger:disabled {\n color: #fff;\n background-color: #dc3545;\n border-color: #dc3545;\n}\n\n.btn-danger:not(:disabled):not(.disabled):active, .btn-danger:not(:disabled):not(.disabled).active,\n.show > .btn-danger.dropdown-toggle {\n color: #fff;\n background-color: #bd2130;\n border-color: #b21f2d;\n}\n\n.btn-danger:not(:disabled):not(.disabled):active:focus, .btn-danger:not(:disabled):not(.disabled).active:focus,\n.show > .btn-danger.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);\n}\n\n.btn-light {\n color: #212529;\n background-color: #f8f9fa;\n border-color: #f8f9fa;\n}\n\n.btn-light:hover {\n color: #212529;\n background-color: #e2e6ea;\n border-color: #dae0e5;\n}\n\n.btn-light:focus, .btn-light.focus {\n box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);\n}\n\n.btn-light.disabled, .btn-light:disabled {\n color: #212529;\n background-color: #f8f9fa;\n border-color: #f8f9fa;\n}\n\n.btn-light:not(:disabled):not(.disabled):active, .btn-light:not(:disabled):not(.disabled).active,\n.show > .btn-light.dropdown-toggle {\n color: #212529;\n background-color: #dae0e5;\n border-color: #d3d9df;\n}\n\n.btn-light:not(:disabled):not(.disabled):active:focus, .btn-light:not(:disabled):not(.disabled).active:focus,\n.show > .btn-light.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);\n}\n\n.btn-dark {\n color: #fff;\n background-color: #343a40;\n border-color: #343a40;\n}\n\n.btn-dark:hover {\n color: #fff;\n background-color: #23272b;\n border-color: #1d2124;\n}\n\n.btn-dark:focus, .btn-dark.focus {\n box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);\n}\n\n.btn-dark.disabled, .btn-dark:disabled {\n color: #fff;\n background-color: #343a40;\n border-color: #343a40;\n}\n\n.btn-dark:not(:disabled):not(.disabled):active, .btn-dark:not(:disabled):not(.disabled).active,\n.show > .btn-dark.dropdown-toggle {\n color: #fff;\n background-color: #1d2124;\n border-color: #171a1d;\n}\n\n.btn-dark:not(:disabled):not(.disabled):active:focus, .btn-dark:not(:disabled):not(.disabled).active:focus,\n.show > .btn-dark.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);\n}\n\n.btn-outline-primary {\n color: #007bff;\n background-color: transparent;\n background-image: none;\n border-color: #007bff;\n}\n\n.btn-outline-primary:hover {\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.btn-outline-primary:focus, .btn-outline-primary.focus {\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);\n}\n\n.btn-outline-primary.disabled, .btn-outline-primary:disabled {\n color: #007bff;\n background-color: transparent;\n}\n\n.btn-outline-primary:not(:disabled):not(.disabled):active, .btn-outline-primary:not(:disabled):not(.disabled).active,\n.show > .btn-outline-primary.dropdown-toggle {\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.btn-outline-primary:not(:disabled):not(.disabled):active:focus, .btn-outline-primary:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-primary.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);\n}\n\n.btn-outline-secondary {\n color: #6c757d;\n background-color: transparent;\n background-image: none;\n border-color: #6c757d;\n}\n\n.btn-outline-secondary:hover {\n color: #fff;\n background-color: #6c757d;\n border-color: #6c757d;\n}\n\n.btn-outline-secondary:focus, .btn-outline-secondary.focus {\n box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);\n}\n\n.btn-outline-secondary.disabled, .btn-outline-secondary:disabled {\n color: #6c757d;\n background-color: transparent;\n}\n\n.btn-outline-secondary:not(:disabled):not(.disabled):active, .btn-outline-secondary:not(:disabled):not(.disabled).active,\n.show > .btn-outline-secondary.dropdown-toggle {\n color: #fff;\n background-color: #6c757d;\n border-color: #6c757d;\n}\n\n.btn-outline-secondary:not(:disabled):not(.disabled):active:focus, .btn-outline-secondary:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-secondary.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);\n}\n\n.btn-outline-success {\n color: #28a745;\n background-color: transparent;\n background-image: none;\n border-color: #28a745;\n}\n\n.btn-outline-success:hover {\n color: #fff;\n background-color: #28a745;\n border-color: #28a745;\n}\n\n.btn-outline-success:focus, .btn-outline-success.focus {\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);\n}\n\n.btn-outline-success.disabled, .btn-outline-success:disabled {\n color: #28a745;\n background-color: transparent;\n}\n\n.btn-outline-success:not(:disabled):not(.disabled):active, .btn-outline-success:not(:disabled):not(.disabled).active,\n.show > .btn-outline-success.dropdown-toggle {\n color: #fff;\n background-color: #28a745;\n border-color: #28a745;\n}\n\n.btn-outline-success:not(:disabled):not(.disabled):active:focus, .btn-outline-success:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-success.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);\n}\n\n.btn-outline-info {\n color: #17a2b8;\n background-color: transparent;\n background-image: none;\n border-color: #17a2b8;\n}\n\n.btn-outline-info:hover {\n color: #fff;\n background-color: #17a2b8;\n border-color: #17a2b8;\n}\n\n.btn-outline-info:focus, .btn-outline-info.focus {\n box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);\n}\n\n.btn-outline-info.disabled, .btn-outline-info:disabled {\n color: #17a2b8;\n background-color: transparent;\n}\n\n.btn-outline-info:not(:disabled):not(.disabled):active, .btn-outline-info:not(:disabled):not(.disabled).active,\n.show > .btn-outline-info.dropdown-toggle {\n color: #fff;\n background-color: #17a2b8;\n border-color: #17a2b8;\n}\n\n.btn-outline-info:not(:disabled):not(.disabled):active:focus, .btn-outline-info:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-info.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);\n}\n\n.btn-outline-warning {\n color: #ffc107;\n background-color: transparent;\n background-image: none;\n border-color: #ffc107;\n}\n\n.btn-outline-warning:hover {\n color: #212529;\n background-color: #ffc107;\n border-color: #ffc107;\n}\n\n.btn-outline-warning:focus, .btn-outline-warning.focus {\n box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);\n}\n\n.btn-outline-warning.disabled, .btn-outline-warning:disabled {\n color: #ffc107;\n background-color: transparent;\n}\n\n.btn-outline-warning:not(:disabled):not(.disabled):active, .btn-outline-warning:not(:disabled):not(.disabled).active,\n.show > .btn-outline-warning.dropdown-toggle {\n color: #212529;\n background-color: #ffc107;\n border-color: #ffc107;\n}\n\n.btn-outline-warning:not(:disabled):not(.disabled):active:focus, .btn-outline-warning:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-warning.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);\n}\n\n.btn-outline-danger {\n color: #dc3545;\n background-color: transparent;\n background-image: none;\n border-color: #dc3545;\n}\n\n.btn-outline-danger:hover {\n color: #fff;\n background-color: #dc3545;\n border-color: #dc3545;\n}\n\n.btn-outline-danger:focus, .btn-outline-danger.focus {\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);\n}\n\n.btn-outline-danger.disabled, .btn-outline-danger:disabled {\n color: #dc3545;\n background-color: transparent;\n}\n\n.btn-outline-danger:not(:disabled):not(.disabled):active, .btn-outline-danger:not(:disabled):not(.disabled).active,\n.show > .btn-outline-danger.dropdown-toggle {\n color: #fff;\n background-color: #dc3545;\n border-color: #dc3545;\n}\n\n.btn-outline-danger:not(:disabled):not(.disabled):active:focus, .btn-outline-danger:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-danger.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);\n}\n\n.btn-outline-light {\n color: #f8f9fa;\n background-color: transparent;\n background-image: none;\n border-color: #f8f9fa;\n}\n\n.btn-outline-light:hover {\n color: #212529;\n background-color: #f8f9fa;\n border-color: #f8f9fa;\n}\n\n.btn-outline-light:focus, .btn-outline-light.focus {\n box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);\n}\n\n.btn-outline-light.disabled, .btn-outline-light:disabled {\n color: #f8f9fa;\n background-color: transparent;\n}\n\n.btn-outline-light:not(:disabled):not(.disabled):active, .btn-outline-light:not(:disabled):not(.disabled).active,\n.show > .btn-outline-light.dropdown-toggle {\n color: #212529;\n background-color: #f8f9fa;\n border-color: #f8f9fa;\n}\n\n.btn-outline-light:not(:disabled):not(.disabled):active:focus, .btn-outline-light:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-light.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);\n}\n\n.btn-outline-dark {\n color: #343a40;\n background-color: transparent;\n background-image: none;\n border-color: #343a40;\n}\n\n.btn-outline-dark:hover {\n color: #fff;\n background-color: #343a40;\n border-color: #343a40;\n}\n\n.btn-outline-dark:focus, .btn-outline-dark.focus {\n box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);\n}\n\n.btn-outline-dark.disabled, .btn-outline-dark:disabled {\n color: #343a40;\n background-color: transparent;\n}\n\n.btn-outline-dark:not(:disabled):not(.disabled):active, .btn-outline-dark:not(:disabled):not(.disabled).active,\n.show > .btn-outline-dark.dropdown-toggle {\n color: #fff;\n background-color: #343a40;\n border-color: #343a40;\n}\n\n.btn-outline-dark:not(:disabled):not(.disabled):active:focus, .btn-outline-dark:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-dark.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);\n}\n\n.btn-link {\n font-weight: 400;\n color: #007bff;\n background-color: transparent;\n}\n\n.btn-link:hover {\n color: #0056b3;\n text-decoration: underline;\n background-color: transparent;\n border-color: transparent;\n}\n\n.btn-link:focus, .btn-link.focus {\n text-decoration: underline;\n border-color: transparent;\n box-shadow: none;\n}\n\n.btn-link:disabled, .btn-link.disabled {\n color: #6c757d;\n pointer-events: none;\n}\n\n.btn-lg, .btn-group-lg > .btn {\n padding: 0.5rem 1rem;\n font-size: 1.25rem;\n line-height: 1.5;\n border-radius: 0.3rem;\n}\n\n.btn-sm, .btn-group-sm > .btn {\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5;\n border-radius: 0.2rem;\n}\n\n.btn-block {\n display: block;\n width: 100%;\n}\n\n.btn-block + .btn-block {\n margin-top: 0.5rem;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n\n.fade {\n transition: opacity 0.15s linear;\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .fade {\n transition: none;\n }\n}\n\n.fade:not(.show) {\n opacity: 0;\n}\n\n.collapse:not(.show) {\n display: none;\n}\n\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n transition: height 0.35s ease;\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .collapsing {\n transition: none;\n }\n}\n\n.dropup,\n.dropright,\n.dropdown,\n.dropleft {\n position: relative;\n}\n\n.dropdown-toggle::after {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n border-top: 0.3em solid;\n border-right: 0.3em solid transparent;\n border-bottom: 0;\n border-left: 0.3em solid transparent;\n}\n\n.dropdown-toggle:empty::after {\n margin-left: 0;\n}\n\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 10rem;\n padding: 0.5rem 0;\n margin: 0.125rem 0 0;\n font-size: 1rem;\n color: #212529;\n text-align: left;\n list-style: none;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 0.25rem;\n}\n\n.dropdown-menu-right {\n right: 0;\n left: auto;\n}\n\n.dropup .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-top: 0;\n margin-bottom: 0.125rem;\n}\n\n.dropup .dropdown-toggle::after {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n border-top: 0;\n border-right: 0.3em solid transparent;\n border-bottom: 0.3em solid;\n border-left: 0.3em solid transparent;\n}\n\n.dropup .dropdown-toggle:empty::after {\n margin-left: 0;\n}\n\n.dropright .dropdown-menu {\n top: 0;\n right: auto;\n left: 100%;\n margin-top: 0;\n margin-left: 0.125rem;\n}\n\n.dropright .dropdown-toggle::after {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n border-top: 0.3em solid transparent;\n border-right: 0;\n border-bottom: 0.3em solid transparent;\n border-left: 0.3em solid;\n}\n\n.dropright .dropdown-toggle:empty::after {\n margin-left: 0;\n}\n\n.dropright .dropdown-toggle::after {\n vertical-align: 0;\n}\n\n.dropleft .dropdown-menu {\n top: 0;\n right: 100%;\n left: auto;\n margin-top: 0;\n margin-right: 0.125rem;\n}\n\n.dropleft .dropdown-toggle::after {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n}\n\n.dropleft .dropdown-toggle::after {\n display: none;\n}\n\n.dropleft .dropdown-toggle::before {\n display: inline-block;\n width: 0;\n height: 0;\n margin-right: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n border-top: 0.3em solid transparent;\n border-right: 0.3em solid;\n border-bottom: 0.3em solid transparent;\n}\n\n.dropleft .dropdown-toggle:empty::after {\n margin-left: 0;\n}\n\n.dropleft .dropdown-toggle::before {\n vertical-align: 0;\n}\n\n.dropdown-menu[x-placement^=\"top\"], .dropdown-menu[x-placement^=\"right\"], .dropdown-menu[x-placement^=\"bottom\"], .dropdown-menu[x-placement^=\"left\"] {\n right: auto;\n bottom: auto;\n}\n\n.dropdown-divider {\n height: 0;\n margin: 0.5rem 0;\n overflow: hidden;\n border-top: 1px solid #e9ecef;\n}\n\n.dropdown-item {\n display: block;\n width: 100%;\n padding: 0.25rem 1.5rem;\n clear: both;\n font-weight: 400;\n color: #212529;\n text-align: inherit;\n white-space: nowrap;\n background-color: transparent;\n border: 0;\n}\n\n.dropdown-item:hover, .dropdown-item:focus {\n color: #16181b;\n text-decoration: none;\n background-color: #f8f9fa;\n}\n\n.dropdown-item.active, .dropdown-item:active {\n color: #fff;\n text-decoration: none;\n background-color: #007bff;\n}\n\n.dropdown-item.disabled, .dropdown-item:disabled {\n color: #6c757d;\n background-color: transparent;\n}\n\n.dropdown-menu.show {\n display: block;\n}\n\n.dropdown-header {\n display: block;\n padding: 0.5rem 1.5rem;\n margin-bottom: 0;\n font-size: 0.875rem;\n color: #6c757d;\n white-space: nowrap;\n}\n\n.dropdown-item-text {\n display: block;\n padding: 0.25rem 1.5rem;\n color: #212529;\n}\n\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-flex;\n vertical-align: middle;\n}\n\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n flex: 0 1 auto;\n}\n\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover {\n z-index: 1;\n}\n\n.btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active,\n.btn-group-vertical > .btn:focus,\n.btn-group-vertical > .btn:active,\n.btn-group-vertical > .btn.active {\n z-index: 1;\n}\n\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group,\n.btn-group-vertical .btn + .btn,\n.btn-group-vertical .btn + .btn-group,\n.btn-group-vertical .btn-group + .btn,\n.btn-group-vertical .btn-group + .btn-group {\n margin-left: -1px;\n}\n\n.btn-toolbar {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-start;\n}\n\n.btn-toolbar .input-group {\n width: auto;\n}\n\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n\n.btn-group > .btn:not(:last-child):not(.dropdown-toggle),\n.btn-group > .btn-group:not(:last-child) > .btn {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n\n.btn-group > .btn:not(:first-child),\n.btn-group > .btn-group:not(:first-child) > .btn {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.dropdown-toggle-split {\n padding-right: 0.5625rem;\n padding-left: 0.5625rem;\n}\n\n.dropdown-toggle-split::after,\n.dropup .dropdown-toggle-split::after,\n.dropright .dropdown-toggle-split::after {\n margin-left: 0;\n}\n\n.dropleft .dropdown-toggle-split::before {\n margin-right: 0;\n}\n\n.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split {\n padding-right: 0.375rem;\n padding-left: 0.375rem;\n}\n\n.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split {\n padding-right: 0.75rem;\n padding-left: 0.75rem;\n}\n\n.btn-group-vertical {\n flex-direction: column;\n align-items: flex-start;\n justify-content: center;\n}\n\n.btn-group-vertical .btn,\n.btn-group-vertical .btn-group {\n width: 100%;\n}\n\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n\n.btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle),\n.btn-group-vertical > .btn-group:not(:last-child) > .btn {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.btn-group-vertical > .btn:not(:first-child),\n.btn-group-vertical > .btn-group:not(:first-child) > .btn {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n\n.btn-group-toggle > .btn,\n.btn-group-toggle > .btn-group > .btn {\n margin-bottom: 0;\n}\n\n.btn-group-toggle > .btn input[type=\"radio\"],\n.btn-group-toggle > .btn input[type=\"checkbox\"],\n.btn-group-toggle > .btn-group > .btn input[type=\"radio\"],\n.btn-group-toggle > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n\n.input-group {\n position: relative;\n display: flex;\n flex-wrap: wrap;\n align-items: stretch;\n width: 100%;\n}\n\n.input-group > .form-control,\n.input-group > .custom-select,\n.input-group > .custom-file {\n position: relative;\n flex: 1 1 auto;\n width: 1%;\n margin-bottom: 0;\n}\n\n.input-group > .form-control + .form-control,\n.input-group > .form-control + .custom-select,\n.input-group > .form-control + .custom-file,\n.input-group > .custom-select + .form-control,\n.input-group > .custom-select + .custom-select,\n.input-group > .custom-select + .custom-file,\n.input-group > .custom-file + .form-control,\n.input-group > .custom-file + .custom-select,\n.input-group > .custom-file + .custom-file {\n margin-left: -1px;\n}\n\n.input-group > .form-control:focus,\n.input-group > .custom-select:focus,\n.input-group > .custom-file .custom-file-input:focus ~ .custom-file-label {\n z-index: 3;\n}\n\n.input-group > .custom-file .custom-file-input:focus {\n z-index: 4;\n}\n\n.input-group > .form-control:not(:last-child),\n.input-group > .custom-select:not(:last-child) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n\n.input-group > .form-control:not(:first-child),\n.input-group > .custom-select:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.input-group > .custom-file {\n display: flex;\n align-items: center;\n}\n\n.input-group > .custom-file:not(:last-child) .custom-file-label,\n.input-group > .custom-file:not(:last-child) .custom-file-label::after {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n\n.input-group > .custom-file:not(:first-child) .custom-file-label {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.input-group-prepend,\n.input-group-append {\n display: flex;\n}\n\n.input-group-prepend .btn,\n.input-group-append .btn {\n position: relative;\n z-index: 2;\n}\n\n.input-group-prepend .btn + .btn,\n.input-group-prepend .btn + .input-group-text,\n.input-group-prepend .input-group-text + .input-group-text,\n.input-group-prepend .input-group-text + .btn,\n.input-group-append .btn + .btn,\n.input-group-append .btn + .input-group-text,\n.input-group-append .input-group-text + .input-group-text,\n.input-group-append .input-group-text + .btn {\n margin-left: -1px;\n}\n\n.input-group-prepend {\n margin-right: -1px;\n}\n\n.input-group-append {\n margin-left: -1px;\n}\n\n.input-group-text {\n display: flex;\n align-items: center;\n padding: 0.375rem 0.75rem;\n margin-bottom: 0;\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #495057;\n text-align: center;\n white-space: nowrap;\n background-color: #e9ecef;\n border: 1px solid #ced4da;\n border-radius: 0.25rem;\n}\n\n.input-group-text input[type=\"radio\"],\n.input-group-text input[type=\"checkbox\"] {\n margin-top: 0;\n}\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-prepend > .input-group-text,\n.input-group-lg > .input-group-append > .input-group-text,\n.input-group-lg > .input-group-prepend > .btn,\n.input-group-lg > .input-group-append > .btn {\n height: calc(2.875rem + 2px);\n padding: 0.5rem 1rem;\n font-size: 1.25rem;\n line-height: 1.5;\n border-radius: 0.3rem;\n}\n\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-prepend > .input-group-text,\n.input-group-sm > .input-group-append > .input-group-text,\n.input-group-sm > .input-group-prepend > .btn,\n.input-group-sm > .input-group-append > .btn {\n height: calc(1.8125rem + 2px);\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5;\n border-radius: 0.2rem;\n}\n\n.input-group > .input-group-prepend > .btn,\n.input-group > .input-group-prepend > .input-group-text,\n.input-group > .input-group-append:not(:last-child) > .btn,\n.input-group > .input-group-append:not(:last-child) > .input-group-text,\n.input-group > .input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group > .input-group-append:last-child > .input-group-text:not(:last-child) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n\n.input-group > .input-group-append > .btn,\n.input-group > .input-group-append > .input-group-text,\n.input-group > .input-group-prepend:not(:first-child) > .btn,\n.input-group > .input-group-prepend:not(:first-child) > .input-group-text,\n.input-group > .input-group-prepend:first-child > .btn:not(:first-child),\n.input-group > .input-group-prepend:first-child > .input-group-text:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.custom-control {\n position: relative;\n display: block;\n min-height: 1.5rem;\n padding-left: 1.5rem;\n}\n\n.custom-control-inline {\n display: inline-flex;\n margin-right: 1rem;\n}\n\n.custom-control-input {\n position: absolute;\n z-index: -1;\n opacity: 0;\n}\n\n.custom-control-input:checked ~ .custom-control-label::before {\n color: #fff;\n background-color: #007bff;\n}\n\n.custom-control-input:focus ~ .custom-control-label::before {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-control-input:active ~ .custom-control-label::before {\n color: #fff;\n background-color: #b3d7ff;\n}\n\n.custom-control-input:disabled ~ .custom-control-label {\n color: #6c757d;\n}\n\n.custom-control-input:disabled ~ .custom-control-label::before {\n background-color: #e9ecef;\n}\n\n.custom-control-label {\n position: relative;\n margin-bottom: 0;\n}\n\n.custom-control-label::before {\n position: absolute;\n top: 0.25rem;\n left: -1.5rem;\n display: block;\n width: 1rem;\n height: 1rem;\n pointer-events: none;\n content: \"\";\n user-select: none;\n background-color: #dee2e6;\n}\n\n.custom-control-label::after {\n position: absolute;\n top: 0.25rem;\n left: -1.5rem;\n display: block;\n width: 1rem;\n height: 1rem;\n content: \"\";\n background-repeat: no-repeat;\n background-position: center center;\n background-size: 50% 50%;\n}\n\n.custom-checkbox .custom-control-label::before {\n border-radius: 0.25rem;\n}\n\n.custom-checkbox .custom-control-input:checked ~ .custom-control-label::before {\n background-color: #007bff;\n}\n\n.custom-checkbox .custom-control-input:checked ~ .custom-control-label::after {\n background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E\");\n}\n\n.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before {\n background-color: #007bff;\n}\n\n.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after {\n background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E\");\n}\n\n.custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label::before {\n background-color: rgba(0, 123, 255, 0.5);\n}\n\n.custom-checkbox .custom-control-input:disabled:indeterminate ~ .custom-control-label::before {\n background-color: rgba(0, 123, 255, 0.5);\n}\n\n.custom-radio .custom-control-label::before {\n border-radius: 50%;\n}\n\n.custom-radio .custom-control-input:checked ~ .custom-control-label::before {\n background-color: #007bff;\n}\n\n.custom-radio .custom-control-input:checked ~ .custom-control-label::after {\n background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E\");\n}\n\n.custom-radio .custom-control-input:disabled:checked ~ .custom-control-label::before {\n background-color: rgba(0, 123, 255, 0.5);\n}\n\n.custom-select {\n display: inline-block;\n width: 100%;\n height: calc(2.25rem + 2px);\n padding: 0.375rem 1.75rem 0.375rem 0.75rem;\n line-height: 1.5;\n color: #495057;\n vertical-align: middle;\n background: #fff url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E\") no-repeat right 0.75rem center;\n background-size: 8px 10px;\n border: 1px solid #ced4da;\n border-radius: 0.25rem;\n appearance: none;\n}\n\n.custom-select:focus {\n border-color: #80bdff;\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(128, 189, 255, 0.5);\n}\n\n.custom-select:focus::-ms-value {\n color: #495057;\n background-color: #fff;\n}\n\n.custom-select[multiple], .custom-select[size]:not([size=\"1\"]) {\n height: auto;\n padding-right: 0.75rem;\n background-image: none;\n}\n\n.custom-select:disabled {\n color: #6c757d;\n background-color: #e9ecef;\n}\n\n.custom-select::-ms-expand {\n opacity: 0;\n}\n\n.custom-select-sm {\n height: calc(1.8125rem + 2px);\n padding-top: 0.375rem;\n padding-bottom: 0.375rem;\n font-size: 75%;\n}\n\n.custom-select-lg {\n height: calc(2.875rem + 2px);\n padding-top: 0.375rem;\n padding-bottom: 0.375rem;\n font-size: 125%;\n}\n\n.custom-file {\n position: relative;\n display: inline-block;\n width: 100%;\n height: calc(2.25rem + 2px);\n margin-bottom: 0;\n}\n\n.custom-file-input {\n position: relative;\n z-index: 2;\n width: 100%;\n height: calc(2.25rem + 2px);\n margin: 0;\n opacity: 0;\n}\n\n.custom-file-input:focus ~ .custom-file-label {\n border-color: #80bdff;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-file-input:focus ~ .custom-file-label::after {\n border-color: #80bdff;\n}\n\n.custom-file-input:disabled ~ .custom-file-label {\n background-color: #e9ecef;\n}\n\n.custom-file-input:lang(en) ~ .custom-file-label::after {\n content: \"Browse\";\n}\n\n.custom-file-label {\n position: absolute;\n top: 0;\n right: 0;\n left: 0;\n z-index: 1;\n height: calc(2.25rem + 2px);\n padding: 0.375rem 0.75rem;\n line-height: 1.5;\n color: #495057;\n background-color: #fff;\n border: 1px solid #ced4da;\n border-radius: 0.25rem;\n}\n\n.custom-file-label::after {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n z-index: 3;\n display: block;\n height: 2.25rem;\n padding: 0.375rem 0.75rem;\n line-height: 1.5;\n color: #495057;\n content: \"Browse\";\n background-color: #e9ecef;\n border-left: 1px solid #ced4da;\n border-radius: 0 0.25rem 0.25rem 0;\n}\n\n.custom-range {\n width: 100%;\n padding-left: 0;\n background-color: transparent;\n appearance: none;\n}\n\n.custom-range:focus {\n outline: none;\n}\n\n.custom-range:focus::-webkit-slider-thumb {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-range:focus::-moz-range-thumb {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-range:focus::-ms-thumb {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-range::-moz-focus-outer {\n border: 0;\n}\n\n.custom-range::-webkit-slider-thumb {\n width: 1rem;\n height: 1rem;\n margin-top: -0.25rem;\n background-color: #007bff;\n border: 0;\n border-radius: 1rem;\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n appearance: none;\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .custom-range::-webkit-slider-thumb {\n transition: none;\n }\n}\n\n.custom-range::-webkit-slider-thumb:active {\n background-color: #b3d7ff;\n}\n\n.custom-range::-webkit-slider-runnable-track {\n width: 100%;\n height: 0.5rem;\n color: transparent;\n cursor: pointer;\n background-color: #dee2e6;\n border-color: transparent;\n border-radius: 1rem;\n}\n\n.custom-range::-moz-range-thumb {\n width: 1rem;\n height: 1rem;\n background-color: #007bff;\n border: 0;\n border-radius: 1rem;\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n appearance: none;\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .custom-range::-moz-range-thumb {\n transition: none;\n }\n}\n\n.custom-range::-moz-range-thumb:active {\n background-color: #b3d7ff;\n}\n\n.custom-range::-moz-range-track {\n width: 100%;\n height: 0.5rem;\n color: transparent;\n cursor: pointer;\n background-color: #dee2e6;\n border-color: transparent;\n border-radius: 1rem;\n}\n\n.custom-range::-ms-thumb {\n width: 1rem;\n height: 1rem;\n margin-top: 0;\n margin-right: 0.2rem;\n margin-left: 0.2rem;\n background-color: #007bff;\n border: 0;\n border-radius: 1rem;\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n appearance: none;\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .custom-range::-ms-thumb {\n transition: none;\n }\n}\n\n.custom-range::-ms-thumb:active {\n background-color: #b3d7ff;\n}\n\n.custom-range::-ms-track {\n width: 100%;\n height: 0.5rem;\n color: transparent;\n cursor: pointer;\n background-color: transparent;\n border-color: transparent;\n border-width: 0.5rem;\n}\n\n.custom-range::-ms-fill-lower {\n background-color: #dee2e6;\n border-radius: 1rem;\n}\n\n.custom-range::-ms-fill-upper {\n margin-right: 15px;\n background-color: #dee2e6;\n border-radius: 1rem;\n}\n\n.custom-control-label::before,\n.custom-file-label,\n.custom-select {\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .custom-control-label::before,\n .custom-file-label,\n .custom-select {\n transition: none;\n }\n}\n\n.nav {\n display: flex;\n flex-wrap: wrap;\n padding-left: 0;\n margin-bottom: 0;\n list-style: none;\n}\n\n.nav-link {\n display: block;\n padding: 0.5rem 1rem;\n}\n\n.nav-link:hover, .nav-link:focus {\n text-decoration: none;\n}\n\n.nav-link.disabled {\n color: #6c757d;\n}\n\n.nav-tabs {\n border-bottom: 1px solid #dee2e6;\n}\n\n.nav-tabs .nav-item {\n margin-bottom: -1px;\n}\n\n.nav-tabs .nav-link {\n border: 1px solid transparent;\n border-top-left-radius: 0.25rem;\n border-top-right-radius: 0.25rem;\n}\n\n.nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus {\n border-color: #e9ecef #e9ecef #dee2e6;\n}\n\n.nav-tabs .nav-link.disabled {\n color: #6c757d;\n background-color: transparent;\n border-color: transparent;\n}\n\n.nav-tabs .nav-link.active,\n.nav-tabs .nav-item.show .nav-link {\n color: #495057;\n background-color: #fff;\n border-color: #dee2e6 #dee2e6 #fff;\n}\n\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n\n.nav-pills .nav-link {\n border-radius: 0.25rem;\n}\n\n.nav-pills .nav-link.active,\n.nav-pills .show > .nav-link {\n color: #fff;\n background-color: #007bff;\n}\n\n.nav-fill .nav-item {\n flex: 1 1 auto;\n text-align: center;\n}\n\n.nav-justified .nav-item {\n flex-basis: 0;\n flex-grow: 1;\n text-align: center;\n}\n\n.tab-content > .tab-pane {\n display: none;\n}\n\n.tab-content > .active {\n display: block;\n}\n\n.navbar {\n position: relative;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n padding: 0.5rem 1rem;\n}\n\n.navbar > .container,\n.navbar > .container-fluid {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n}\n\n.navbar-brand {\n display: inline-block;\n padding-top: 0.3125rem;\n padding-bottom: 0.3125rem;\n margin-right: 1rem;\n font-size: 1.25rem;\n line-height: inherit;\n white-space: nowrap;\n}\n\n.navbar-brand:hover, .navbar-brand:focus {\n text-decoration: none;\n}\n\n.navbar-nav {\n display: flex;\n flex-direction: column;\n padding-left: 0;\n margin-bottom: 0;\n list-style: none;\n}\n\n.navbar-nav .nav-link {\n padding-right: 0;\n padding-left: 0;\n}\n\n.navbar-nav .dropdown-menu {\n position: static;\n float: none;\n}\n\n.navbar-text {\n display: inline-block;\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n}\n\n.navbar-collapse {\n flex-basis: 100%;\n flex-grow: 1;\n align-items: center;\n}\n\n.navbar-toggler {\n padding: 0.25rem 0.75rem;\n font-size: 1.25rem;\n line-height: 1;\n background-color: transparent;\n border: 1px solid transparent;\n border-radius: 0.25rem;\n}\n\n.navbar-toggler:hover, .navbar-toggler:focus {\n text-decoration: none;\n}\n\n.navbar-toggler:not(:disabled):not(.disabled) {\n cursor: pointer;\n}\n\n.navbar-toggler-icon {\n display: inline-block;\n width: 1.5em;\n height: 1.5em;\n vertical-align: middle;\n content: \"\";\n background: no-repeat center center;\n background-size: 100% 100%;\n}\n\n@media (max-width: 575.98px) {\n .navbar-expand-sm > .container,\n .navbar-expand-sm > .container-fluid {\n padding-right: 0;\n padding-left: 0;\n }\n}\n\n@media (min-width: 576px) {\n .navbar-expand-sm {\n flex-flow: row nowrap;\n justify-content: flex-start;\n }\n .navbar-expand-sm .navbar-nav {\n flex-direction: row;\n }\n .navbar-expand-sm .navbar-nav .dropdown-menu {\n position: absolute;\n }\n .navbar-expand-sm .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem;\n }\n .navbar-expand-sm > .container,\n .navbar-expand-sm > .container-fluid {\n flex-wrap: nowrap;\n }\n .navbar-expand-sm .navbar-collapse {\n display: flex !important;\n flex-basis: auto;\n }\n .navbar-expand-sm .navbar-toggler {\n display: none;\n }\n}\n\n@media (max-width: 767.98px) {\n .navbar-expand-md > .container,\n .navbar-expand-md > .container-fluid {\n padding-right: 0;\n padding-left: 0;\n }\n}\n\n@media (min-width: 768px) {\n .navbar-expand-md {\n flex-flow: row nowrap;\n justify-content: flex-start;\n }\n .navbar-expand-md .navbar-nav {\n flex-direction: row;\n }\n .navbar-expand-md .navbar-nav .dropdown-menu {\n position: absolute;\n }\n .navbar-expand-md .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem;\n }\n .navbar-expand-md > .container,\n .navbar-expand-md > .container-fluid {\n flex-wrap: nowrap;\n }\n .navbar-expand-md .navbar-collapse {\n display: flex !important;\n flex-basis: auto;\n }\n .navbar-expand-md .navbar-toggler {\n display: none;\n }\n}\n\n@media (max-width: 991.98px) {\n .navbar-expand-lg > .container,\n .navbar-expand-lg > .container-fluid {\n padding-right: 0;\n padding-left: 0;\n }\n}\n\n@media (min-width: 992px) {\n .navbar-expand-lg {\n flex-flow: row nowrap;\n justify-content: flex-start;\n }\n .navbar-expand-lg .navbar-nav {\n flex-direction: row;\n }\n .navbar-expand-lg .navbar-nav .dropdown-menu {\n position: absolute;\n }\n .navbar-expand-lg .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem;\n }\n .navbar-expand-lg > .container,\n .navbar-expand-lg > .container-fluid {\n flex-wrap: nowrap;\n }\n .navbar-expand-lg .navbar-collapse {\n display: flex !important;\n flex-basis: auto;\n }\n .navbar-expand-lg .navbar-toggler {\n display: none;\n }\n}\n\n@media (max-width: 1199.98px) {\n .navbar-expand-xl > .container,\n .navbar-expand-xl > .container-fluid {\n padding-right: 0;\n padding-left: 0;\n }\n}\n\n@media (min-width: 1200px) {\n .navbar-expand-xl {\n flex-flow: row nowrap;\n justify-content: flex-start;\n }\n .navbar-expand-xl .navbar-nav {\n flex-direction: row;\n }\n .navbar-expand-xl .navbar-nav .dropdown-menu {\n position: absolute;\n }\n .navbar-expand-xl .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem;\n }\n .navbar-expand-xl > .container,\n .navbar-expand-xl > .container-fluid {\n flex-wrap: nowrap;\n }\n .navbar-expand-xl .navbar-collapse {\n display: flex !important;\n flex-basis: auto;\n }\n .navbar-expand-xl .navbar-toggler {\n display: none;\n }\n}\n\n.navbar-expand {\n flex-flow: row nowrap;\n justify-content: flex-start;\n}\n\n.navbar-expand > .container,\n.navbar-expand > .container-fluid {\n padding-right: 0;\n padding-left: 0;\n}\n\n.navbar-expand .navbar-nav {\n flex-direction: row;\n}\n\n.navbar-expand .navbar-nav .dropdown-menu {\n position: absolute;\n}\n\n.navbar-expand .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem;\n}\n\n.navbar-expand > .container,\n.navbar-expand > .container-fluid {\n flex-wrap: nowrap;\n}\n\n.navbar-expand .navbar-collapse {\n display: flex !important;\n flex-basis: auto;\n}\n\n.navbar-expand .navbar-toggler {\n display: none;\n}\n\n.navbar-light .navbar-brand {\n color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-brand:hover, .navbar-light .navbar-brand:focus {\n color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-nav .nav-link {\n color: rgba(0, 0, 0, 0.5);\n}\n\n.navbar-light .navbar-nav .nav-link:hover, .navbar-light .navbar-nav .nav-link:focus {\n color: rgba(0, 0, 0, 0.7);\n}\n\n.navbar-light .navbar-nav .nav-link.disabled {\n color: rgba(0, 0, 0, 0.3);\n}\n\n.navbar-light .navbar-nav .show > .nav-link,\n.navbar-light .navbar-nav .active > .nav-link,\n.navbar-light .navbar-nav .nav-link.show,\n.navbar-light .navbar-nav .nav-link.active {\n color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-toggler {\n color: rgba(0, 0, 0, 0.5);\n border-color: rgba(0, 0, 0, 0.1);\n}\n\n.navbar-light .navbar-toggler-icon {\n background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\");\n}\n\n.navbar-light .navbar-text {\n color: rgba(0, 0, 0, 0.5);\n}\n\n.navbar-light .navbar-text a {\n color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-text a:hover, .navbar-light .navbar-text a:focus {\n color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-dark .navbar-brand {\n color: #fff;\n}\n\n.navbar-dark .navbar-brand:hover, .navbar-dark .navbar-brand:focus {\n color: #fff;\n}\n\n.navbar-dark .navbar-nav .nav-link {\n color: rgba(255, 255, 255, 0.5);\n}\n\n.navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .nav-link:focus {\n color: rgba(255, 255, 255, 0.75);\n}\n\n.navbar-dark .navbar-nav .nav-link.disabled {\n color: rgba(255, 255, 255, 0.25);\n}\n\n.navbar-dark .navbar-nav .show > .nav-link,\n.navbar-dark .navbar-nav .active > .nav-link,\n.navbar-dark .navbar-nav .nav-link.show,\n.navbar-dark .navbar-nav .nav-link.active {\n color: #fff;\n}\n\n.navbar-dark .navbar-toggler {\n color: rgba(255, 255, 255, 0.5);\n border-color: rgba(255, 255, 255, 0.1);\n}\n\n.navbar-dark .navbar-toggler-icon {\n background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\");\n}\n\n.navbar-dark .navbar-text {\n color: rgba(255, 255, 255, 0.5);\n}\n\n.navbar-dark .navbar-text a {\n color: #fff;\n}\n\n.navbar-dark .navbar-text a:hover, .navbar-dark .navbar-text a:focus {\n color: #fff;\n}\n\n.card {\n position: relative;\n display: flex;\n flex-direction: column;\n min-width: 0;\n word-wrap: break-word;\n background-color: #fff;\n background-clip: border-box;\n border: 1px solid rgba(0, 0, 0, 0.125);\n border-radius: 0.25rem;\n}\n\n.card > hr {\n margin-right: 0;\n margin-left: 0;\n}\n\n.card > .list-group:first-child .list-group-item:first-child {\n border-top-left-radius: 0.25rem;\n border-top-right-radius: 0.25rem;\n}\n\n.card > .list-group:last-child .list-group-item:last-child {\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n}\n\n.card-body {\n flex: 1 1 auto;\n padding: 1.25rem;\n}\n\n.card-title {\n margin-bottom: 0.75rem;\n}\n\n.card-subtitle {\n margin-top: -0.375rem;\n margin-bottom: 0;\n}\n\n.card-text:last-child {\n margin-bottom: 0;\n}\n\n.card-link:hover {\n text-decoration: none;\n}\n\n.card-link + .card-link {\n margin-left: 1.25rem;\n}\n\n.card-header {\n padding: 0.75rem 1.25rem;\n margin-bottom: 0;\n background-color: rgba(0, 0, 0, 0.03);\n border-bottom: 1px solid rgba(0, 0, 0, 0.125);\n}\n\n.card-header:first-child {\n border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0;\n}\n\n.card-header + .list-group .list-group-item:first-child {\n border-top: 0;\n}\n\n.card-footer {\n padding: 0.75rem 1.25rem;\n background-color: rgba(0, 0, 0, 0.03);\n border-top: 1px solid rgba(0, 0, 0, 0.125);\n}\n\n.card-footer:last-child {\n border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px);\n}\n\n.card-header-tabs {\n margin-right: -0.625rem;\n margin-bottom: -0.75rem;\n margin-left: -0.625rem;\n border-bottom: 0;\n}\n\n.card-header-pills {\n margin-right: -0.625rem;\n margin-left: -0.625rem;\n}\n\n.card-img-overlay {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n padding: 1.25rem;\n}\n\n.card-img {\n width: 100%;\n border-radius: calc(0.25rem - 1px);\n}\n\n.card-img-top {\n width: 100%;\n border-top-left-radius: calc(0.25rem - 1px);\n border-top-right-radius: calc(0.25rem - 1px);\n}\n\n.card-img-bottom {\n width: 100%;\n border-bottom-right-radius: calc(0.25rem - 1px);\n border-bottom-left-radius: calc(0.25rem - 1px);\n}\n\n.card-deck {\n display: flex;\n flex-direction: column;\n}\n\n.card-deck .card {\n margin-bottom: 15px;\n}\n\n@media (min-width: 576px) {\n .card-deck {\n flex-flow: row wrap;\n margin-right: -15px;\n margin-left: -15px;\n }\n .card-deck .card {\n display: flex;\n flex: 1 0 0%;\n flex-direction: column;\n margin-right: 15px;\n margin-bottom: 0;\n margin-left: 15px;\n }\n}\n\n.card-group {\n display: flex;\n flex-direction: column;\n}\n\n.card-group > .card {\n margin-bottom: 15px;\n}\n\n@media (min-width: 576px) {\n .card-group {\n flex-flow: row wrap;\n }\n .card-group > .card {\n flex: 1 0 0%;\n margin-bottom: 0;\n }\n .card-group > .card + .card {\n margin-left: 0;\n border-left: 0;\n }\n .card-group > .card:first-child {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n }\n .card-group > .card:first-child .card-img-top,\n .card-group > .card:first-child .card-header {\n border-top-right-radius: 0;\n }\n .card-group > .card:first-child .card-img-bottom,\n .card-group > .card:first-child .card-footer {\n border-bottom-right-radius: 0;\n }\n .card-group > .card:last-child {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n }\n .card-group > .card:last-child .card-img-top,\n .card-group > .card:last-child .card-header {\n border-top-left-radius: 0;\n }\n .card-group > .card:last-child .card-img-bottom,\n .card-group > .card:last-child .card-footer {\n border-bottom-left-radius: 0;\n }\n .card-group > .card:only-child {\n border-radius: 0.25rem;\n }\n .card-group > .card:only-child .card-img-top,\n .card-group > .card:only-child .card-header {\n border-top-left-radius: 0.25rem;\n border-top-right-radius: 0.25rem;\n }\n .card-group > .card:only-child .card-img-bottom,\n .card-group > .card:only-child .card-footer {\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n }\n .card-group > .card:not(:first-child):not(:last-child):not(:only-child) {\n border-radius: 0;\n }\n .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-img-top,\n .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom,\n .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-header,\n .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-footer {\n border-radius: 0;\n }\n}\n\n.card-columns .card {\n margin-bottom: 0.75rem;\n}\n\n@media (min-width: 576px) {\n .card-columns {\n column-count: 3;\n column-gap: 1.25rem;\n orphans: 1;\n widows: 1;\n }\n .card-columns .card {\n display: inline-block;\n width: 100%;\n }\n}\n\n.accordion .card:not(:first-of-type):not(:last-of-type) {\n border-bottom: 0;\n border-radius: 0;\n}\n\n.accordion .card:not(:first-of-type) .card-header:first-child {\n border-radius: 0;\n}\n\n.accordion .card:first-of-type {\n border-bottom: 0;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.accordion .card:last-of-type {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n\n.breadcrumb {\n display: flex;\n flex-wrap: wrap;\n padding: 0.75rem 1rem;\n margin-bottom: 1rem;\n list-style: none;\n background-color: #e9ecef;\n border-radius: 0.25rem;\n}\n\n.breadcrumb-item + .breadcrumb-item {\n padding-left: 0.5rem;\n}\n\n.breadcrumb-item + .breadcrumb-item::before {\n display: inline-block;\n padding-right: 0.5rem;\n color: #6c757d;\n content: \"/\";\n}\n\n.breadcrumb-item + .breadcrumb-item:hover::before {\n text-decoration: underline;\n}\n\n.breadcrumb-item + .breadcrumb-item:hover::before {\n text-decoration: none;\n}\n\n.breadcrumb-item.active {\n color: #6c757d;\n}\n\n.pagination {\n display: flex;\n padding-left: 0;\n list-style: none;\n border-radius: 0.25rem;\n}\n\n.page-link {\n position: relative;\n display: block;\n padding: 0.5rem 0.75rem;\n margin-left: -1px;\n line-height: 1.25;\n color: #007bff;\n background-color: #fff;\n border: 1px solid #dee2e6;\n}\n\n.page-link:hover {\n z-index: 2;\n color: #0056b3;\n text-decoration: none;\n background-color: #e9ecef;\n border-color: #dee2e6;\n}\n\n.page-link:focus {\n z-index: 2;\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.page-link:not(:disabled):not(.disabled) {\n cursor: pointer;\n}\n\n.page-item:first-child .page-link {\n margin-left: 0;\n border-top-left-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n}\n\n.page-item:last-child .page-link {\n border-top-right-radius: 0.25rem;\n border-bottom-right-radius: 0.25rem;\n}\n\n.page-item.active .page-link {\n z-index: 1;\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.page-item.disabled .page-link {\n color: #6c757d;\n pointer-events: none;\n cursor: auto;\n background-color: #fff;\n border-color: #dee2e6;\n}\n\n.pagination-lg .page-link {\n padding: 0.75rem 1.5rem;\n font-size: 1.25rem;\n line-height: 1.5;\n}\n\n.pagination-lg .page-item:first-child .page-link {\n border-top-left-radius: 0.3rem;\n border-bottom-left-radius: 0.3rem;\n}\n\n.pagination-lg .page-item:last-child .page-link {\n border-top-right-radius: 0.3rem;\n border-bottom-right-radius: 0.3rem;\n}\n\n.pagination-sm .page-link {\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5;\n}\n\n.pagination-sm .page-item:first-child .page-link {\n border-top-left-radius: 0.2rem;\n border-bottom-left-radius: 0.2rem;\n}\n\n.pagination-sm .page-item:last-child .page-link {\n border-top-right-radius: 0.2rem;\n border-bottom-right-radius: 0.2rem;\n}\n\n.badge {\n display: inline-block;\n padding: 0.25em 0.4em;\n font-size: 75%;\n font-weight: 700;\n line-height: 1;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: 0.25rem;\n}\n\n.badge:empty {\n display: none;\n}\n\n.btn .badge {\n position: relative;\n top: -1px;\n}\n\n.badge-pill {\n padding-right: 0.6em;\n padding-left: 0.6em;\n border-radius: 10rem;\n}\n\n.badge-primary {\n color: #fff;\n background-color: #007bff;\n}\n\n.badge-primary[href]:hover, .badge-primary[href]:focus {\n color: #fff;\n text-decoration: none;\n background-color: #0062cc;\n}\n\n.badge-secondary {\n color: #fff;\n background-color: #6c757d;\n}\n\n.badge-secondary[href]:hover, .badge-secondary[href]:focus {\n color: #fff;\n text-decoration: none;\n background-color: #545b62;\n}\n\n.badge-success {\n color: #fff;\n background-color: #28a745;\n}\n\n.badge-success[href]:hover, .badge-success[href]:focus {\n color: #fff;\n text-decoration: none;\n background-color: #1e7e34;\n}\n\n.badge-info {\n color: #fff;\n background-color: #17a2b8;\n}\n\n.badge-info[href]:hover, .badge-info[href]:focus {\n color: #fff;\n text-decoration: none;\n background-color: #117a8b;\n}\n\n.badge-warning {\n color: #212529;\n background-color: #ffc107;\n}\n\n.badge-warning[href]:hover, .badge-warning[href]:focus {\n color: #212529;\n text-decoration: none;\n background-color: #d39e00;\n}\n\n.badge-danger {\n color: #fff;\n background-color: #dc3545;\n}\n\n.badge-danger[href]:hover, .badge-danger[href]:focus {\n color: #fff;\n text-decoration: none;\n background-color: #bd2130;\n}\n\n.badge-light {\n color: #212529;\n background-color: #f8f9fa;\n}\n\n.badge-light[href]:hover, .badge-light[href]:focus {\n color: #212529;\n text-decoration: none;\n background-color: #dae0e5;\n}\n\n.badge-dark {\n color: #fff;\n background-color: #343a40;\n}\n\n.badge-dark[href]:hover, .badge-dark[href]:focus {\n color: #fff;\n text-decoration: none;\n background-color: #1d2124;\n}\n\n.jumbotron {\n padding: 2rem 1rem;\n margin-bottom: 2rem;\n background-color: #e9ecef;\n border-radius: 0.3rem;\n}\n\n@media (min-width: 576px) {\n .jumbotron {\n padding: 4rem 2rem;\n }\n}\n\n.jumbotron-fluid {\n padding-right: 0;\n padding-left: 0;\n border-radius: 0;\n}\n\n.alert {\n position: relative;\n padding: 0.75rem 1.25rem;\n margin-bottom: 1rem;\n border: 1px solid transparent;\n border-radius: 0.25rem;\n}\n\n.alert-heading {\n color: inherit;\n}\n\n.alert-link {\n font-weight: 700;\n}\n\n.alert-dismissible {\n padding-right: 4rem;\n}\n\n.alert-dismissible .close {\n position: absolute;\n top: 0;\n right: 0;\n padding: 0.75rem 1.25rem;\n color: inherit;\n}\n\n.alert-primary {\n color: #004085;\n background-color: #cce5ff;\n border-color: #b8daff;\n}\n\n.alert-primary hr {\n border-top-color: #9fcdff;\n}\n\n.alert-primary .alert-link {\n color: #002752;\n}\n\n.alert-secondary {\n color: #383d41;\n background-color: #e2e3e5;\n border-color: #d6d8db;\n}\n\n.alert-secondary hr {\n border-top-color: #c8cbcf;\n}\n\n.alert-secondary .alert-link {\n color: #202326;\n}\n\n.alert-success {\n color: #155724;\n background-color: #d4edda;\n border-color: #c3e6cb;\n}\n\n.alert-success hr {\n border-top-color: #b1dfbb;\n}\n\n.alert-success .alert-link {\n color: #0b2e13;\n}\n\n.alert-info {\n color: #0c5460;\n background-color: #d1ecf1;\n border-color: #bee5eb;\n}\n\n.alert-info hr {\n border-top-color: #abdde5;\n}\n\n.alert-info .alert-link {\n color: #062c33;\n}\n\n.alert-warning {\n color: #856404;\n background-color: #fff3cd;\n border-color: #ffeeba;\n}\n\n.alert-warning hr {\n border-top-color: #ffe8a1;\n}\n\n.alert-warning .alert-link {\n color: #533f03;\n}\n\n.alert-danger {\n color: #721c24;\n background-color: #f8d7da;\n border-color: #f5c6cb;\n}\n\n.alert-danger hr {\n border-top-color: #f1b0b7;\n}\n\n.alert-danger .alert-link {\n color: #491217;\n}\n\n.alert-light {\n color: #818182;\n background-color: #fefefe;\n border-color: #fdfdfe;\n}\n\n.alert-light hr {\n border-top-color: #ececf6;\n}\n\n.alert-light .alert-link {\n color: #686868;\n}\n\n.alert-dark {\n color: #1b1e21;\n background-color: #d6d8d9;\n border-color: #c6c8ca;\n}\n\n.alert-dark hr {\n border-top-color: #b9bbbe;\n}\n\n.alert-dark .alert-link {\n color: #040505;\n}\n\n@keyframes progress-bar-stripes {\n from {\n background-position: 1rem 0;\n }\n to {\n background-position: 0 0;\n }\n}\n\n.progress {\n display: flex;\n height: 1rem;\n overflow: hidden;\n font-size: 0.75rem;\n background-color: #e9ecef;\n border-radius: 0.25rem;\n}\n\n.progress-bar {\n display: flex;\n flex-direction: column;\n justify-content: center;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n background-color: #007bff;\n transition: width 0.6s ease;\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .progress-bar {\n transition: none;\n }\n}\n\n.progress-bar-striped {\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-size: 1rem 1rem;\n}\n\n.progress-bar-animated {\n animation: progress-bar-stripes 1s linear infinite;\n}\n\n.media {\n display: flex;\n align-items: flex-start;\n}\n\n.media-body {\n flex: 1;\n}\n\n.list-group {\n display: flex;\n flex-direction: column;\n padding-left: 0;\n margin-bottom: 0;\n}\n\n.list-group-item-action {\n width: 100%;\n color: #495057;\n text-align: inherit;\n}\n\n.list-group-item-action:hover, .list-group-item-action:focus {\n color: #495057;\n text-decoration: none;\n background-color: #f8f9fa;\n}\n\n.list-group-item-action:active {\n color: #212529;\n background-color: #e9ecef;\n}\n\n.list-group-item {\n position: relative;\n display: block;\n padding: 0.75rem 1.25rem;\n margin-bottom: -1px;\n background-color: #fff;\n border: 1px solid rgba(0, 0, 0, 0.125);\n}\n\n.list-group-item:first-child {\n border-top-left-radius: 0.25rem;\n border-top-right-radius: 0.25rem;\n}\n\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n}\n\n.list-group-item:hover, .list-group-item:focus {\n z-index: 1;\n text-decoration: none;\n}\n\n.list-group-item.disabled, .list-group-item:disabled {\n color: #6c757d;\n background-color: #fff;\n}\n\n.list-group-item.active {\n z-index: 2;\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.list-group-flush .list-group-item {\n border-right: 0;\n border-left: 0;\n border-radius: 0;\n}\n\n.list-group-flush:first-child .list-group-item:first-child {\n border-top: 0;\n}\n\n.list-group-flush:last-child .list-group-item:last-child {\n border-bottom: 0;\n}\n\n.list-group-item-primary {\n color: #004085;\n background-color: #b8daff;\n}\n\n.list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus {\n color: #004085;\n background-color: #9fcdff;\n}\n\n.list-group-item-primary.list-group-item-action.active {\n color: #fff;\n background-color: #004085;\n border-color: #004085;\n}\n\n.list-group-item-secondary {\n color: #383d41;\n background-color: #d6d8db;\n}\n\n.list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus {\n color: #383d41;\n background-color: #c8cbcf;\n}\n\n.list-group-item-secondary.list-group-item-action.active {\n color: #fff;\n background-color: #383d41;\n border-color: #383d41;\n}\n\n.list-group-item-success {\n color: #155724;\n background-color: #c3e6cb;\n}\n\n.list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus {\n color: #155724;\n background-color: #b1dfbb;\n}\n\n.list-group-item-success.list-group-item-action.active {\n color: #fff;\n background-color: #155724;\n border-color: #155724;\n}\n\n.list-group-item-info {\n color: #0c5460;\n background-color: #bee5eb;\n}\n\n.list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus {\n color: #0c5460;\n background-color: #abdde5;\n}\n\n.list-group-item-info.list-group-item-action.active {\n color: #fff;\n background-color: #0c5460;\n border-color: #0c5460;\n}\n\n.list-group-item-warning {\n color: #856404;\n background-color: #ffeeba;\n}\n\n.list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus {\n color: #856404;\n background-color: #ffe8a1;\n}\n\n.list-group-item-warning.list-group-item-action.active {\n color: #fff;\n background-color: #856404;\n border-color: #856404;\n}\n\n.list-group-item-danger {\n color: #721c24;\n background-color: #f5c6cb;\n}\n\n.list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus {\n color: #721c24;\n background-color: #f1b0b7;\n}\n\n.list-group-item-danger.list-group-item-action.active {\n color: #fff;\n background-color: #721c24;\n border-color: #721c24;\n}\n\n.list-group-item-light {\n color: #818182;\n background-color: #fdfdfe;\n}\n\n.list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus {\n color: #818182;\n background-color: #ececf6;\n}\n\n.list-group-item-light.list-group-item-action.active {\n color: #fff;\n background-color: #818182;\n border-color: #818182;\n}\n\n.list-group-item-dark {\n color: #1b1e21;\n background-color: #c6c8ca;\n}\n\n.list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus {\n color: #1b1e21;\n background-color: #b9bbbe;\n}\n\n.list-group-item-dark.list-group-item-action.active {\n color: #fff;\n background-color: #1b1e21;\n border-color: #1b1e21;\n}\n\n.close {\n float: right;\n font-size: 1.5rem;\n font-weight: 700;\n line-height: 1;\n color: #000;\n text-shadow: 0 1px 0 #fff;\n opacity: .5;\n}\n\n.close:not(:disabled):not(.disabled) {\n cursor: pointer;\n}\n\n.close:not(:disabled):not(.disabled):hover, .close:not(:disabled):not(.disabled):focus {\n color: #000;\n text-decoration: none;\n opacity: .75;\n}\n\nbutton.close {\n padding: 0;\n background-color: transparent;\n border: 0;\n -webkit-appearance: none;\n}\n\n.modal-open {\n overflow: hidden;\n}\n\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n\n.modal {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n display: none;\n overflow: hidden;\n outline: 0;\n}\n\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 0.5rem;\n pointer-events: none;\n}\n\n.modal.fade .modal-dialog {\n transition: transform 0.3s ease-out;\n transform: translate(0, -25%);\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .modal.fade .modal-dialog {\n transition: none;\n }\n}\n\n.modal.show .modal-dialog {\n transform: translate(0, 0);\n}\n\n.modal-dialog-centered {\n display: flex;\n align-items: center;\n min-height: calc(100% - (0.5rem * 2));\n}\n\n.modal-dialog-centered::before {\n display: block;\n height: calc(100vh - (0.5rem * 2));\n content: \"\";\n}\n\n.modal-content {\n position: relative;\n display: flex;\n flex-direction: column;\n width: 100%;\n pointer-events: auto;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 0.3rem;\n outline: 0;\n}\n\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000;\n}\n\n.modal-backdrop.fade {\n opacity: 0;\n}\n\n.modal-backdrop.show {\n opacity: 0.5;\n}\n\n.modal-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n padding: 1rem;\n border-bottom: 1px solid #e9ecef;\n border-top-left-radius: 0.3rem;\n border-top-right-radius: 0.3rem;\n}\n\n.modal-header .close {\n padding: 1rem;\n margin: -1rem -1rem -1rem auto;\n}\n\n.modal-title {\n margin-bottom: 0;\n line-height: 1.5;\n}\n\n.modal-body {\n position: relative;\n flex: 1 1 auto;\n padding: 1rem;\n}\n\n.modal-footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n padding: 1rem;\n border-top: 1px solid #e9ecef;\n}\n\n.modal-footer > :not(:first-child) {\n margin-left: .25rem;\n}\n\n.modal-footer > :not(:last-child) {\n margin-right: .25rem;\n}\n\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n\n@media (min-width: 576px) {\n .modal-dialog {\n max-width: 500px;\n margin: 1.75rem auto;\n }\n .modal-dialog-centered {\n min-height: calc(100% - (1.75rem * 2));\n }\n .modal-dialog-centered::before {\n height: calc(100vh - (1.75rem * 2));\n }\n .modal-sm {\n max-width: 300px;\n }\n}\n\n@media (min-width: 992px) {\n .modal-lg {\n max-width: 800px;\n }\n}\n\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-style: normal;\n font-weight: 400;\n line-height: 1.5;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n white-space: normal;\n line-break: auto;\n font-size: 0.875rem;\n word-wrap: break-word;\n opacity: 0;\n}\n\n.tooltip.show {\n opacity: 0.9;\n}\n\n.tooltip .arrow {\n position: absolute;\n display: block;\n width: 0.8rem;\n height: 0.4rem;\n}\n\n.tooltip .arrow::before {\n position: absolute;\n content: \"\";\n border-color: transparent;\n border-style: solid;\n}\n\n.bs-tooltip-top, .bs-tooltip-auto[x-placement^=\"top\"] {\n padding: 0.4rem 0;\n}\n\n.bs-tooltip-top .arrow, .bs-tooltip-auto[x-placement^=\"top\"] .arrow {\n bottom: 0;\n}\n\n.bs-tooltip-top .arrow::before, .bs-tooltip-auto[x-placement^=\"top\"] .arrow::before {\n top: 0;\n border-width: 0.4rem 0.4rem 0;\n border-top-color: #000;\n}\n\n.bs-tooltip-right, .bs-tooltip-auto[x-placement^=\"right\"] {\n padding: 0 0.4rem;\n}\n\n.bs-tooltip-right .arrow, .bs-tooltip-auto[x-placement^=\"right\"] .arrow {\n left: 0;\n width: 0.4rem;\n height: 0.8rem;\n}\n\n.bs-tooltip-right .arrow::before, .bs-tooltip-auto[x-placement^=\"right\"] .arrow::before {\n right: 0;\n border-width: 0.4rem 0.4rem 0.4rem 0;\n border-right-color: #000;\n}\n\n.bs-tooltip-bottom, .bs-tooltip-auto[x-placement^=\"bottom\"] {\n padding: 0.4rem 0;\n}\n\n.bs-tooltip-bottom .arrow, .bs-tooltip-auto[x-placement^=\"bottom\"] .arrow {\n top: 0;\n}\n\n.bs-tooltip-bottom .arrow::before, .bs-tooltip-auto[x-placement^=\"bottom\"] .arrow::before {\n bottom: 0;\n border-width: 0 0.4rem 0.4rem;\n border-bottom-color: #000;\n}\n\n.bs-tooltip-left, .bs-tooltip-auto[x-placement^=\"left\"] {\n padding: 0 0.4rem;\n}\n\n.bs-tooltip-left .arrow, .bs-tooltip-auto[x-placement^=\"left\"] .arrow {\n right: 0;\n width: 0.4rem;\n height: 0.8rem;\n}\n\n.bs-tooltip-left .arrow::before, .bs-tooltip-auto[x-placement^=\"left\"] .arrow::before {\n left: 0;\n border-width: 0.4rem 0 0.4rem 0.4rem;\n border-left-color: #000;\n}\n\n.tooltip-inner {\n max-width: 200px;\n padding: 0.25rem 0.5rem;\n color: #fff;\n text-align: center;\n background-color: #000;\n border-radius: 0.25rem;\n}\n\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: block;\n max-width: 276px;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-style: normal;\n font-weight: 400;\n line-height: 1.5;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n white-space: normal;\n line-break: auto;\n font-size: 0.875rem;\n word-wrap: break-word;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 0.3rem;\n}\n\n.popover .arrow {\n position: absolute;\n display: block;\n width: 1rem;\n height: 0.5rem;\n margin: 0 0.3rem;\n}\n\n.popover .arrow::before, .popover .arrow::after {\n position: absolute;\n display: block;\n content: \"\";\n border-color: transparent;\n border-style: solid;\n}\n\n.bs-popover-top, .bs-popover-auto[x-placement^=\"top\"] {\n margin-bottom: 0.5rem;\n}\n\n.bs-popover-top .arrow, .bs-popover-auto[x-placement^=\"top\"] .arrow {\n bottom: calc((0.5rem + 1px) * -1);\n}\n\n.bs-popover-top .arrow::before, .bs-popover-auto[x-placement^=\"top\"] .arrow::before,\n.bs-popover-top .arrow::after,\n.bs-popover-auto[x-placement^=\"top\"] .arrow::after {\n border-width: 0.5rem 0.5rem 0;\n}\n\n.bs-popover-top .arrow::before, .bs-popover-auto[x-placement^=\"top\"] .arrow::before {\n bottom: 0;\n border-top-color: rgba(0, 0, 0, 0.25);\n}\n\n\n.bs-popover-top .arrow::after,\n.bs-popover-auto[x-placement^=\"top\"] .arrow::after {\n bottom: 1px;\n border-top-color: #fff;\n}\n\n.bs-popover-right, .bs-popover-auto[x-placement^=\"right\"] {\n margin-left: 0.5rem;\n}\n\n.bs-popover-right .arrow, .bs-popover-auto[x-placement^=\"right\"] .arrow {\n left: calc((0.5rem + 1px) * -1);\n width: 0.5rem;\n height: 1rem;\n margin: 0.3rem 0;\n}\n\n.bs-popover-right .arrow::before, .bs-popover-auto[x-placement^=\"right\"] .arrow::before,\n.bs-popover-right .arrow::after,\n.bs-popover-auto[x-placement^=\"right\"] .arrow::after {\n border-width: 0.5rem 0.5rem 0.5rem 0;\n}\n\n.bs-popover-right .arrow::before, .bs-popover-auto[x-placement^=\"right\"] .arrow::before {\n left: 0;\n border-right-color: rgba(0, 0, 0, 0.25);\n}\n\n\n.bs-popover-right .arrow::after,\n.bs-popover-auto[x-placement^=\"right\"] .arrow::after {\n left: 1px;\n border-right-color: #fff;\n}\n\n.bs-popover-bottom, .bs-popover-auto[x-placement^=\"bottom\"] {\n margin-top: 0.5rem;\n}\n\n.bs-popover-bottom .arrow, .bs-popover-auto[x-placement^=\"bottom\"] .arrow {\n top: calc((0.5rem + 1px) * -1);\n}\n\n.bs-popover-bottom .arrow::before, .bs-popover-auto[x-placement^=\"bottom\"] .arrow::before,\n.bs-popover-bottom .arrow::after,\n.bs-popover-auto[x-placement^=\"bottom\"] .arrow::after {\n border-width: 0 0.5rem 0.5rem 0.5rem;\n}\n\n.bs-popover-bottom .arrow::before, .bs-popover-auto[x-placement^=\"bottom\"] .arrow::before {\n top: 0;\n border-bottom-color: rgba(0, 0, 0, 0.25);\n}\n\n\n.bs-popover-bottom .arrow::after,\n.bs-popover-auto[x-placement^=\"bottom\"] .arrow::after {\n top: 1px;\n border-bottom-color: #fff;\n}\n\n.bs-popover-bottom .popover-header::before, .bs-popover-auto[x-placement^=\"bottom\"] .popover-header::before {\n position: absolute;\n top: 0;\n left: 50%;\n display: block;\n width: 1rem;\n margin-left: -0.5rem;\n content: \"\";\n border-bottom: 1px solid #f7f7f7;\n}\n\n.bs-popover-left, .bs-popover-auto[x-placement^=\"left\"] {\n margin-right: 0.5rem;\n}\n\n.bs-popover-left .arrow, .bs-popover-auto[x-placement^=\"left\"] .arrow {\n right: calc((0.5rem + 1px) * -1);\n width: 0.5rem;\n height: 1rem;\n margin: 0.3rem 0;\n}\n\n.bs-popover-left .arrow::before, .bs-popover-auto[x-placement^=\"left\"] .arrow::before,\n.bs-popover-left .arrow::after,\n.bs-popover-auto[x-placement^=\"left\"] .arrow::after {\n border-width: 0.5rem 0 0.5rem 0.5rem;\n}\n\n.bs-popover-left .arrow::before, .bs-popover-auto[x-placement^=\"left\"] .arrow::before {\n right: 0;\n border-left-color: rgba(0, 0, 0, 0.25);\n}\n\n\n.bs-popover-left .arrow::after,\n.bs-popover-auto[x-placement^=\"left\"] .arrow::after {\n right: 1px;\n border-left-color: #fff;\n}\n\n.popover-header {\n padding: 0.5rem 0.75rem;\n margin-bottom: 0;\n font-size: 1rem;\n color: inherit;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-top-left-radius: calc(0.3rem - 1px);\n border-top-right-radius: calc(0.3rem - 1px);\n}\n\n.popover-header:empty {\n display: none;\n}\n\n.popover-body {\n padding: 0.5rem 0.75rem;\n color: #212529;\n}\n\n.carousel {\n position: relative;\n}\n\n.carousel-inner {\n position: relative;\n width: 100%;\n overflow: hidden;\n}\n\n.carousel-item {\n position: relative;\n display: none;\n align-items: center;\n width: 100%;\n backface-visibility: hidden;\n perspective: 1000px;\n}\n\n.carousel-item.active,\n.carousel-item-next,\n.carousel-item-prev {\n display: block;\n transition: transform 0.6s ease;\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .carousel-item.active,\n .carousel-item-next,\n .carousel-item-prev {\n transition: none;\n }\n}\n\n.carousel-item-next,\n.carousel-item-prev {\n position: absolute;\n top: 0;\n}\n\n.carousel-item-next.carousel-item-left,\n.carousel-item-prev.carousel-item-right {\n transform: translateX(0);\n}\n\n@supports (transform-style: preserve-3d) {\n .carousel-item-next.carousel-item-left,\n .carousel-item-prev.carousel-item-right {\n transform: translate3d(0, 0, 0);\n }\n}\n\n.carousel-item-next,\n.active.carousel-item-right {\n transform: translateX(100%);\n}\n\n@supports (transform-style: preserve-3d) {\n .carousel-item-next,\n .active.carousel-item-right {\n transform: translate3d(100%, 0, 0);\n }\n}\n\n.carousel-item-prev,\n.active.carousel-item-left {\n transform: translateX(-100%);\n}\n\n@supports (transform-style: preserve-3d) {\n .carousel-item-prev,\n .active.carousel-item-left {\n transform: translate3d(-100%, 0, 0);\n }\n}\n\n.carousel-fade .carousel-item {\n opacity: 0;\n transition-duration: .6s;\n transition-property: opacity;\n}\n\n.carousel-fade .carousel-item.active,\n.carousel-fade .carousel-item-next.carousel-item-left,\n.carousel-fade .carousel-item-prev.carousel-item-right {\n opacity: 1;\n}\n\n.carousel-fade .active.carousel-item-left,\n.carousel-fade .active.carousel-item-right {\n opacity: 0;\n}\n\n.carousel-fade .carousel-item-next,\n.carousel-fade .carousel-item-prev,\n.carousel-fade .carousel-item.active,\n.carousel-fade .active.carousel-item-left,\n.carousel-fade .active.carousel-item-prev {\n transform: translateX(0);\n}\n\n@supports (transform-style: preserve-3d) {\n .carousel-fade .carousel-item-next,\n .carousel-fade .carousel-item-prev,\n .carousel-fade .carousel-item.active,\n .carousel-fade .active.carousel-item-left,\n .carousel-fade .active.carousel-item-prev {\n transform: translate3d(0, 0, 0);\n }\n}\n\n.carousel-control-prev,\n.carousel-control-next {\n position: absolute;\n top: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 15%;\n color: #fff;\n text-align: center;\n opacity: 0.5;\n}\n\n.carousel-control-prev:hover, .carousel-control-prev:focus,\n.carousel-control-next:hover,\n.carousel-control-next:focus {\n color: #fff;\n text-decoration: none;\n outline: 0;\n opacity: .9;\n}\n\n.carousel-control-prev {\n left: 0;\n}\n\n.carousel-control-next {\n right: 0;\n}\n\n.carousel-control-prev-icon,\n.carousel-control-next-icon {\n display: inline-block;\n width: 20px;\n height: 20px;\n background: transparent no-repeat center center;\n background-size: 100% 100%;\n}\n\n.carousel-control-prev-icon {\n background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E\");\n}\n\n.carousel-control-next-icon {\n background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E\");\n}\n\n.carousel-indicators {\n position: absolute;\n right: 0;\n bottom: 10px;\n left: 0;\n z-index: 15;\n display: flex;\n justify-content: center;\n padding-left: 0;\n margin-right: 15%;\n margin-left: 15%;\n list-style: none;\n}\n\n.carousel-indicators li {\n position: relative;\n flex: 0 1 auto;\n width: 30px;\n height: 3px;\n margin-right: 3px;\n margin-left: 3px;\n text-indent: -999px;\n cursor: pointer;\n background-color: rgba(255, 255, 255, 0.5);\n}\n\n.carousel-indicators li::before {\n position: absolute;\n top: -10px;\n left: 0;\n display: inline-block;\n width: 100%;\n height: 10px;\n content: \"\";\n}\n\n.carousel-indicators li::after {\n position: absolute;\n bottom: -10px;\n left: 0;\n display: inline-block;\n width: 100%;\n height: 10px;\n content: \"\";\n}\n\n.carousel-indicators .active {\n background-color: #fff;\n}\n\n.carousel-caption {\n position: absolute;\n right: 15%;\n bottom: 20px;\n left: 15%;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #fff;\n text-align: center;\n}\n\n.align-baseline {\n vertical-align: baseline !important;\n}\n\n.align-top {\n vertical-align: top !important;\n}\n\n.align-middle {\n vertical-align: middle !important;\n}\n\n.align-bottom {\n vertical-align: bottom !important;\n}\n\n.align-text-bottom {\n vertical-align: text-bottom !important;\n}\n\n.align-text-top {\n vertical-align: text-top !important;\n}\n\n.bg-primary {\n background-color: #007bff !important;\n}\n\na.bg-primary:hover, a.bg-primary:focus,\nbutton.bg-primary:hover,\nbutton.bg-primary:focus {\n background-color: #0062cc !important;\n}\n\n.bg-secondary {\n background-color: #6c757d !important;\n}\n\na.bg-secondary:hover, a.bg-secondary:focus,\nbutton.bg-secondary:hover,\nbutton.bg-secondary:focus {\n background-color: #545b62 !important;\n}\n\n.bg-success {\n background-color: #28a745 !important;\n}\n\na.bg-success:hover, a.bg-success:focus,\nbutton.bg-success:hover,\nbutton.bg-success:focus {\n background-color: #1e7e34 !important;\n}\n\n.bg-info {\n background-color: #17a2b8 !important;\n}\n\na.bg-info:hover, a.bg-info:focus,\nbutton.bg-info:hover,\nbutton.bg-info:focus {\n background-color: #117a8b !important;\n}\n\n.bg-warning {\n background-color: #ffc107 !important;\n}\n\na.bg-warning:hover, a.bg-warning:focus,\nbutton.bg-warning:hover,\nbutton.bg-warning:focus {\n background-color: #d39e00 !important;\n}\n\n.bg-danger {\n background-color: #dc3545 !important;\n}\n\na.bg-danger:hover, a.bg-danger:focus,\nbutton.bg-danger:hover,\nbutton.bg-danger:focus {\n background-color: #bd2130 !important;\n}\n\n.bg-light {\n background-color: #f8f9fa !important;\n}\n\na.bg-light:hover, a.bg-light:focus,\nbutton.bg-light:hover,\nbutton.bg-light:focus {\n background-color: #dae0e5 !important;\n}\n\n.bg-dark {\n background-color: #343a40 !important;\n}\n\na.bg-dark:hover, a.bg-dark:focus,\nbutton.bg-dark:hover,\nbutton.bg-dark:focus {\n background-color: #1d2124 !important;\n}\n\n.bg-white {\n background-color: #fff !important;\n}\n\n.bg-transparent {\n background-color: transparent !important;\n}\n\n.border {\n border: 1px solid #dee2e6 !important;\n}\n\n.border-top {\n border-top: 1px solid #dee2e6 !important;\n}\n\n.border-right {\n border-right: 1px solid #dee2e6 !important;\n}\n\n.border-bottom {\n border-bottom: 1px solid #dee2e6 !important;\n}\n\n.border-left {\n border-left: 1px solid #dee2e6 !important;\n}\n\n.border-0 {\n border: 0 !important;\n}\n\n.border-top-0 {\n border-top: 0 !important;\n}\n\n.border-right-0 {\n border-right: 0 !important;\n}\n\n.border-bottom-0 {\n border-bottom: 0 !important;\n}\n\n.border-left-0 {\n border-left: 0 !important;\n}\n\n.border-primary {\n border-color: #007bff !important;\n}\n\n.border-secondary {\n border-color: #6c757d !important;\n}\n\n.border-success {\n border-color: #28a745 !important;\n}\n\n.border-info {\n border-color: #17a2b8 !important;\n}\n\n.border-warning {\n border-color: #ffc107 !important;\n}\n\n.border-danger {\n border-color: #dc3545 !important;\n}\n\n.border-light {\n border-color: #f8f9fa !important;\n}\n\n.border-dark {\n border-color: #343a40 !important;\n}\n\n.border-white {\n border-color: #fff !important;\n}\n\n.rounded {\n border-radius: 0.25rem !important;\n}\n\n.rounded-top {\n border-top-left-radius: 0.25rem !important;\n border-top-right-radius: 0.25rem !important;\n}\n\n.rounded-right {\n border-top-right-radius: 0.25rem !important;\n border-bottom-right-radius: 0.25rem !important;\n}\n\n.rounded-bottom {\n border-bottom-right-radius: 0.25rem !important;\n border-bottom-left-radius: 0.25rem !important;\n}\n\n.rounded-left {\n border-top-left-radius: 0.25rem !important;\n border-bottom-left-radius: 0.25rem !important;\n}\n\n.rounded-circle {\n border-radius: 50% !important;\n}\n\n.rounded-0 {\n border-radius: 0 !important;\n}\n\n.clearfix::after {\n display: block;\n clear: both;\n content: \"\";\n}\n\n.d-none {\n display: none !important;\n}\n\n.d-inline {\n display: inline !important;\n}\n\n.d-inline-block {\n display: inline-block !important;\n}\n\n.d-block {\n display: block !important;\n}\n\n.d-table {\n display: table !important;\n}\n\n.d-table-row {\n display: table-row !important;\n}\n\n.d-table-cell {\n display: table-cell !important;\n}\n\n.d-flex {\n display: flex !important;\n}\n\n.d-inline-flex {\n display: inline-flex !important;\n}\n\n@media (min-width: 576px) {\n .d-sm-none {\n display: none !important;\n }\n .d-sm-inline {\n display: inline !important;\n }\n .d-sm-inline-block {\n display: inline-block !important;\n }\n .d-sm-block {\n display: block !important;\n }\n .d-sm-table {\n display: table !important;\n }\n .d-sm-table-row {\n display: table-row !important;\n }\n .d-sm-table-cell {\n display: table-cell !important;\n }\n .d-sm-flex {\n display: flex !important;\n }\n .d-sm-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 768px) {\n .d-md-none {\n display: none !important;\n }\n .d-md-inline {\n display: inline !important;\n }\n .d-md-inline-block {\n display: inline-block !important;\n }\n .d-md-block {\n display: block !important;\n }\n .d-md-table {\n display: table !important;\n }\n .d-md-table-row {\n display: table-row !important;\n }\n .d-md-table-cell {\n display: table-cell !important;\n }\n .d-md-flex {\n display: flex !important;\n }\n .d-md-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 992px) {\n .d-lg-none {\n display: none !important;\n }\n .d-lg-inline {\n display: inline !important;\n }\n .d-lg-inline-block {\n display: inline-block !important;\n }\n .d-lg-block {\n display: block !important;\n }\n .d-lg-table {\n display: table !important;\n }\n .d-lg-table-row {\n display: table-row !important;\n }\n .d-lg-table-cell {\n display: table-cell !important;\n }\n .d-lg-flex {\n display: flex !important;\n }\n .d-lg-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 1200px) {\n .d-xl-none {\n display: none !important;\n }\n .d-xl-inline {\n display: inline !important;\n }\n .d-xl-inline-block {\n display: inline-block !important;\n }\n .d-xl-block {\n display: block !important;\n }\n .d-xl-table {\n display: table !important;\n }\n .d-xl-table-row {\n display: table-row !important;\n }\n .d-xl-table-cell {\n display: table-cell !important;\n }\n .d-xl-flex {\n display: flex !important;\n }\n .d-xl-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media print {\n .d-print-none {\n display: none !important;\n }\n .d-print-inline {\n display: inline !important;\n }\n .d-print-inline-block {\n display: inline-block !important;\n }\n .d-print-block {\n display: block !important;\n }\n .d-print-table {\n display: table !important;\n }\n .d-print-table-row {\n display: table-row !important;\n }\n .d-print-table-cell {\n display: table-cell !important;\n }\n .d-print-flex {\n display: flex !important;\n }\n .d-print-inline-flex {\n display: inline-flex !important;\n }\n}\n\n.embed-responsive {\n position: relative;\n display: block;\n width: 100%;\n padding: 0;\n overflow: hidden;\n}\n\n.embed-responsive::before {\n display: block;\n content: \"\";\n}\n\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 100%;\n border: 0;\n}\n\n.embed-responsive-21by9::before {\n padding-top: 42.857143%;\n}\n\n.embed-responsive-16by9::before {\n padding-top: 56.25%;\n}\n\n.embed-responsive-4by3::before {\n padding-top: 75%;\n}\n\n.embed-responsive-1by1::before {\n padding-top: 100%;\n}\n\n.flex-row {\n flex-direction: row !important;\n}\n\n.flex-column {\n flex-direction: column !important;\n}\n\n.flex-row-reverse {\n flex-direction: row-reverse !important;\n}\n\n.flex-column-reverse {\n flex-direction: column-reverse !important;\n}\n\n.flex-wrap {\n flex-wrap: wrap !important;\n}\n\n.flex-nowrap {\n flex-wrap: nowrap !important;\n}\n\n.flex-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n}\n\n.flex-fill {\n flex: 1 1 auto !important;\n}\n\n.flex-grow-0 {\n flex-grow: 0 !important;\n}\n\n.flex-grow-1 {\n flex-grow: 1 !important;\n}\n\n.flex-shrink-0 {\n flex-shrink: 0 !important;\n}\n\n.flex-shrink-1 {\n flex-shrink: 1 !important;\n}\n\n.justify-content-start {\n justify-content: flex-start !important;\n}\n\n.justify-content-end {\n justify-content: flex-end !important;\n}\n\n.justify-content-center {\n justify-content: center !important;\n}\n\n.justify-content-between {\n justify-content: space-between !important;\n}\n\n.justify-content-around {\n justify-content: space-around !important;\n}\n\n.align-items-start {\n align-items: flex-start !important;\n}\n\n.align-items-end {\n align-items: flex-end !important;\n}\n\n.align-items-center {\n align-items: center !important;\n}\n\n.align-items-baseline {\n align-items: baseline !important;\n}\n\n.align-items-stretch {\n align-items: stretch !important;\n}\n\n.align-content-start {\n align-content: flex-start !important;\n}\n\n.align-content-end {\n align-content: flex-end !important;\n}\n\n.align-content-center {\n align-content: center !important;\n}\n\n.align-content-between {\n align-content: space-between !important;\n}\n\n.align-content-around {\n align-content: space-around !important;\n}\n\n.align-content-stretch {\n align-content: stretch !important;\n}\n\n.align-self-auto {\n align-self: auto !important;\n}\n\n.align-self-start {\n align-self: flex-start !important;\n}\n\n.align-self-end {\n align-self: flex-end !important;\n}\n\n.align-self-center {\n align-self: center !important;\n}\n\n.align-self-baseline {\n align-self: baseline !important;\n}\n\n.align-self-stretch {\n align-self: stretch !important;\n}\n\n@media (min-width: 576px) {\n .flex-sm-row {\n flex-direction: row !important;\n }\n .flex-sm-column {\n flex-direction: column !important;\n }\n .flex-sm-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-sm-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-sm-wrap {\n flex-wrap: wrap !important;\n }\n .flex-sm-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-sm-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-sm-fill {\n flex: 1 1 auto !important;\n }\n .flex-sm-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-sm-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-sm-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-sm-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-sm-start {\n justify-content: flex-start !important;\n }\n .justify-content-sm-end {\n justify-content: flex-end !important;\n }\n .justify-content-sm-center {\n justify-content: center !important;\n }\n .justify-content-sm-between {\n justify-content: space-between !important;\n }\n .justify-content-sm-around {\n justify-content: space-around !important;\n }\n .align-items-sm-start {\n align-items: flex-start !important;\n }\n .align-items-sm-end {\n align-items: flex-end !important;\n }\n .align-items-sm-center {\n align-items: center !important;\n }\n .align-items-sm-baseline {\n align-items: baseline !important;\n }\n .align-items-sm-stretch {\n align-items: stretch !important;\n }\n .align-content-sm-start {\n align-content: flex-start !important;\n }\n .align-content-sm-end {\n align-content: flex-end !important;\n }\n .align-content-sm-center {\n align-content: center !important;\n }\n .align-content-sm-between {\n align-content: space-between !important;\n }\n .align-content-sm-around {\n align-content: space-around !important;\n }\n .align-content-sm-stretch {\n align-content: stretch !important;\n }\n .align-self-sm-auto {\n align-self: auto !important;\n }\n .align-self-sm-start {\n align-self: flex-start !important;\n }\n .align-self-sm-end {\n align-self: flex-end !important;\n }\n .align-self-sm-center {\n align-self: center !important;\n }\n .align-self-sm-baseline {\n align-self: baseline !important;\n }\n .align-self-sm-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 768px) {\n .flex-md-row {\n flex-direction: row !important;\n }\n .flex-md-column {\n flex-direction: column !important;\n }\n .flex-md-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-md-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-md-wrap {\n flex-wrap: wrap !important;\n }\n .flex-md-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-md-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-md-fill {\n flex: 1 1 auto !important;\n }\n .flex-md-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-md-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-md-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-md-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-md-start {\n justify-content: flex-start !important;\n }\n .justify-content-md-end {\n justify-content: flex-end !important;\n }\n .justify-content-md-center {\n justify-content: center !important;\n }\n .justify-content-md-between {\n justify-content: space-between !important;\n }\n .justify-content-md-around {\n justify-content: space-around !important;\n }\n .align-items-md-start {\n align-items: flex-start !important;\n }\n .align-items-md-end {\n align-items: flex-end !important;\n }\n .align-items-md-center {\n align-items: center !important;\n }\n .align-items-md-baseline {\n align-items: baseline !important;\n }\n .align-items-md-stretch {\n align-items: stretch !important;\n }\n .align-content-md-start {\n align-content: flex-start !important;\n }\n .align-content-md-end {\n align-content: flex-end !important;\n }\n .align-content-md-center {\n align-content: center !important;\n }\n .align-content-md-between {\n align-content: space-between !important;\n }\n .align-content-md-around {\n align-content: space-around !important;\n }\n .align-content-md-stretch {\n align-content: stretch !important;\n }\n .align-self-md-auto {\n align-self: auto !important;\n }\n .align-self-md-start {\n align-self: flex-start !important;\n }\n .align-self-md-end {\n align-self: flex-end !important;\n }\n .align-self-md-center {\n align-self: center !important;\n }\n .align-self-md-baseline {\n align-self: baseline !important;\n }\n .align-self-md-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 992px) {\n .flex-lg-row {\n flex-direction: row !important;\n }\n .flex-lg-column {\n flex-direction: column !important;\n }\n .flex-lg-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-lg-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-lg-wrap {\n flex-wrap: wrap !important;\n }\n .flex-lg-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-lg-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-lg-fill {\n flex: 1 1 auto !important;\n }\n .flex-lg-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-lg-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-lg-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-lg-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-lg-start {\n justify-content: flex-start !important;\n }\n .justify-content-lg-end {\n justify-content: flex-end !important;\n }\n .justify-content-lg-center {\n justify-content: center !important;\n }\n .justify-content-lg-between {\n justify-content: space-between !important;\n }\n .justify-content-lg-around {\n justify-content: space-around !important;\n }\n .align-items-lg-start {\n align-items: flex-start !important;\n }\n .align-items-lg-end {\n align-items: flex-end !important;\n }\n .align-items-lg-center {\n align-items: center !important;\n }\n .align-items-lg-baseline {\n align-items: baseline !important;\n }\n .align-items-lg-stretch {\n align-items: stretch !important;\n }\n .align-content-lg-start {\n align-content: flex-start !important;\n }\n .align-content-lg-end {\n align-content: flex-end !important;\n }\n .align-content-lg-center {\n align-content: center !important;\n }\n .align-content-lg-between {\n align-content: space-between !important;\n }\n .align-content-lg-around {\n align-content: space-around !important;\n }\n .align-content-lg-stretch {\n align-content: stretch !important;\n }\n .align-self-lg-auto {\n align-self: auto !important;\n }\n .align-self-lg-start {\n align-self: flex-start !important;\n }\n .align-self-lg-end {\n align-self: flex-end !important;\n }\n .align-self-lg-center {\n align-self: center !important;\n }\n .align-self-lg-baseline {\n align-self: baseline !important;\n }\n .align-self-lg-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 1200px) {\n .flex-xl-row {\n flex-direction: row !important;\n }\n .flex-xl-column {\n flex-direction: column !important;\n }\n .flex-xl-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-xl-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-xl-wrap {\n flex-wrap: wrap !important;\n }\n .flex-xl-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-xl-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-xl-fill {\n flex: 1 1 auto !important;\n }\n .flex-xl-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-xl-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-xl-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-xl-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-xl-start {\n justify-content: flex-start !important;\n }\n .justify-content-xl-end {\n justify-content: flex-end !important;\n }\n .justify-content-xl-center {\n justify-content: center !important;\n }\n .justify-content-xl-between {\n justify-content: space-between !important;\n }\n .justify-content-xl-around {\n justify-content: space-around !important;\n }\n .align-items-xl-start {\n align-items: flex-start !important;\n }\n .align-items-xl-end {\n align-items: flex-end !important;\n }\n .align-items-xl-center {\n align-items: center !important;\n }\n .align-items-xl-baseline {\n align-items: baseline !important;\n }\n .align-items-xl-stretch {\n align-items: stretch !important;\n }\n .align-content-xl-start {\n align-content: flex-start !important;\n }\n .align-content-xl-end {\n align-content: flex-end !important;\n }\n .align-content-xl-center {\n align-content: center !important;\n }\n .align-content-xl-between {\n align-content: space-between !important;\n }\n .align-content-xl-around {\n align-content: space-around !important;\n }\n .align-content-xl-stretch {\n align-content: stretch !important;\n }\n .align-self-xl-auto {\n align-self: auto !important;\n }\n .align-self-xl-start {\n align-self: flex-start !important;\n }\n .align-self-xl-end {\n align-self: flex-end !important;\n }\n .align-self-xl-center {\n align-self: center !important;\n }\n .align-self-xl-baseline {\n align-self: baseline !important;\n }\n .align-self-xl-stretch {\n align-self: stretch !important;\n }\n}\n\n.float-left {\n float: left !important;\n}\n\n.float-right {\n float: right !important;\n}\n\n.float-none {\n float: none !important;\n}\n\n@media (min-width: 576px) {\n .float-sm-left {\n float: left !important;\n }\n .float-sm-right {\n float: right !important;\n }\n .float-sm-none {\n float: none !important;\n }\n}\n\n@media (min-width: 768px) {\n .float-md-left {\n float: left !important;\n }\n .float-md-right {\n float: right !important;\n }\n .float-md-none {\n float: none !important;\n }\n}\n\n@media (min-width: 992px) {\n .float-lg-left {\n float: left !important;\n }\n .float-lg-right {\n float: right !important;\n }\n .float-lg-none {\n float: none !important;\n }\n}\n\n@media (min-width: 1200px) {\n .float-xl-left {\n float: left !important;\n }\n .float-xl-right {\n float: right !important;\n }\n .float-xl-none {\n float: none !important;\n }\n}\n\n.position-static {\n position: static !important;\n}\n\n.position-relative {\n position: relative !important;\n}\n\n.position-absolute {\n position: absolute !important;\n}\n\n.position-fixed {\n position: fixed !important;\n}\n\n.position-sticky {\n position: sticky !important;\n}\n\n.fixed-top {\n position: fixed;\n top: 0;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n\n.fixed-bottom {\n position: fixed;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1030;\n}\n\n@supports (position: sticky) {\n .sticky-top {\n position: sticky;\n top: 0;\n z-index: 1020;\n }\n}\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n.sr-only-focusable:active, .sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n overflow: visible;\n clip: auto;\n white-space: normal;\n}\n\n.shadow-sm {\n box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important;\n}\n\n.shadow {\n box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important;\n}\n\n.shadow-lg {\n box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important;\n}\n\n.shadow-none {\n box-shadow: none !important;\n}\n\n.w-25 {\n width: 25% !important;\n}\n\n.w-50 {\n width: 50% !important;\n}\n\n.w-75 {\n width: 75% !important;\n}\n\n.w-100 {\n width: 100% !important;\n}\n\n.w-auto {\n width: auto !important;\n}\n\n.h-25 {\n height: 25% !important;\n}\n\n.h-50 {\n height: 50% !important;\n}\n\n.h-75 {\n height: 75% !important;\n}\n\n.h-100 {\n height: 100% !important;\n}\n\n.h-auto {\n height: auto !important;\n}\n\n.mw-100 {\n max-width: 100% !important;\n}\n\n.mh-100 {\n max-height: 100% !important;\n}\n\n.m-0 {\n margin: 0 !important;\n}\n\n.mt-0,\n.my-0 {\n margin-top: 0 !important;\n}\n\n.mr-0,\n.mx-0 {\n margin-right: 0 !important;\n}\n\n.mb-0,\n.my-0 {\n margin-bottom: 0 !important;\n}\n\n.ml-0,\n.mx-0 {\n margin-left: 0 !important;\n}\n\n.m-1 {\n margin: 0.25rem !important;\n}\n\n.mt-1,\n.my-1 {\n margin-top: 0.25rem !important;\n}\n\n.mr-1,\n.mx-1 {\n margin-right: 0.25rem !important;\n}\n\n.mb-1,\n.my-1 {\n margin-bottom: 0.25rem !important;\n}\n\n.ml-1,\n.mx-1 {\n margin-left: 0.25rem !important;\n}\n\n.m-2 {\n margin: 0.5rem !important;\n}\n\n.mt-2,\n.my-2 {\n margin-top: 0.5rem !important;\n}\n\n.mr-2,\n.mx-2 {\n margin-right: 0.5rem !important;\n}\n\n.mb-2,\n.my-2 {\n margin-bottom: 0.5rem !important;\n}\n\n.ml-2,\n.mx-2 {\n margin-left: 0.5rem !important;\n}\n\n.m-3 {\n margin: 1rem !important;\n}\n\n.mt-3,\n.my-3 {\n margin-top: 1rem !important;\n}\n\n.mr-3,\n.mx-3 {\n margin-right: 1rem !important;\n}\n\n.mb-3,\n.my-3 {\n margin-bottom: 1rem !important;\n}\n\n.ml-3,\n.mx-3 {\n margin-left: 1rem !important;\n}\n\n.m-4 {\n margin: 1.5rem !important;\n}\n\n.mt-4,\n.my-4 {\n margin-top: 1.5rem !important;\n}\n\n.mr-4,\n.mx-4 {\n margin-right: 1.5rem !important;\n}\n\n.mb-4,\n.my-4 {\n margin-bottom: 1.5rem !important;\n}\n\n.ml-4,\n.mx-4 {\n margin-left: 1.5rem !important;\n}\n\n.m-5 {\n margin: 3rem !important;\n}\n\n.mt-5,\n.my-5 {\n margin-top: 3rem !important;\n}\n\n.mr-5,\n.mx-5 {\n margin-right: 3rem !important;\n}\n\n.mb-5,\n.my-5 {\n margin-bottom: 3rem !important;\n}\n\n.ml-5,\n.mx-5 {\n margin-left: 3rem !important;\n}\n\n.p-0 {\n padding: 0 !important;\n}\n\n.pt-0,\n.py-0 {\n padding-top: 0 !important;\n}\n\n.pr-0,\n.px-0 {\n padding-right: 0 !important;\n}\n\n.pb-0,\n.py-0 {\n padding-bottom: 0 !important;\n}\n\n.pl-0,\n.px-0 {\n padding-left: 0 !important;\n}\n\n.p-1 {\n padding: 0.25rem !important;\n}\n\n.pt-1,\n.py-1 {\n padding-top: 0.25rem !important;\n}\n\n.pr-1,\n.px-1 {\n padding-right: 0.25rem !important;\n}\n\n.pb-1,\n.py-1 {\n padding-bottom: 0.25rem !important;\n}\n\n.pl-1,\n.px-1 {\n padding-left: 0.25rem !important;\n}\n\n.p-2 {\n padding: 0.5rem !important;\n}\n\n.pt-2,\n.py-2 {\n padding-top: 0.5rem !important;\n}\n\n.pr-2,\n.px-2 {\n padding-right: 0.5rem !important;\n}\n\n.pb-2,\n.py-2 {\n padding-bottom: 0.5rem !important;\n}\n\n.pl-2,\n.px-2 {\n padding-left: 0.5rem !important;\n}\n\n.p-3 {\n padding: 1rem !important;\n}\n\n.pt-3,\n.py-3 {\n padding-top: 1rem !important;\n}\n\n.pr-3,\n.px-3 {\n padding-right: 1rem !important;\n}\n\n.pb-3,\n.py-3 {\n padding-bottom: 1rem !important;\n}\n\n.pl-3,\n.px-3 {\n padding-left: 1rem !important;\n}\n\n.p-4 {\n padding: 1.5rem !important;\n}\n\n.pt-4,\n.py-4 {\n padding-top: 1.5rem !important;\n}\n\n.pr-4,\n.px-4 {\n padding-right: 1.5rem !important;\n}\n\n.pb-4,\n.py-4 {\n padding-bottom: 1.5rem !important;\n}\n\n.pl-4,\n.px-4 {\n padding-left: 1.5rem !important;\n}\n\n.p-5 {\n padding: 3rem !important;\n}\n\n.pt-5,\n.py-5 {\n padding-top: 3rem !important;\n}\n\n.pr-5,\n.px-5 {\n padding-right: 3rem !important;\n}\n\n.pb-5,\n.py-5 {\n padding-bottom: 3rem !important;\n}\n\n.pl-5,\n.px-5 {\n padding-left: 3rem !important;\n}\n\n.m-auto {\n margin: auto !important;\n}\n\n.mt-auto,\n.my-auto {\n margin-top: auto !important;\n}\n\n.mr-auto,\n.mx-auto {\n margin-right: auto !important;\n}\n\n.mb-auto,\n.my-auto {\n margin-bottom: auto !important;\n}\n\n.ml-auto,\n.mx-auto {\n margin-left: auto !important;\n}\n\n@media (min-width: 576px) {\n .m-sm-0 {\n margin: 0 !important;\n }\n .mt-sm-0,\n .my-sm-0 {\n margin-top: 0 !important;\n }\n .mr-sm-0,\n .mx-sm-0 {\n margin-right: 0 !important;\n }\n .mb-sm-0,\n .my-sm-0 {\n margin-bottom: 0 !important;\n }\n .ml-sm-0,\n .mx-sm-0 {\n margin-left: 0 !important;\n }\n .m-sm-1 {\n margin: 0.25rem !important;\n }\n .mt-sm-1,\n .my-sm-1 {\n margin-top: 0.25rem !important;\n }\n .mr-sm-1,\n .mx-sm-1 {\n margin-right: 0.25rem !important;\n }\n .mb-sm-1,\n .my-sm-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-sm-1,\n .mx-sm-1 {\n margin-left: 0.25rem !important;\n }\n .m-sm-2 {\n margin: 0.5rem !important;\n }\n .mt-sm-2,\n .my-sm-2 {\n margin-top: 0.5rem !important;\n }\n .mr-sm-2,\n .mx-sm-2 {\n margin-right: 0.5rem !important;\n }\n .mb-sm-2,\n .my-sm-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-sm-2,\n .mx-sm-2 {\n margin-left: 0.5rem !important;\n }\n .m-sm-3 {\n margin: 1rem !important;\n }\n .mt-sm-3,\n .my-sm-3 {\n margin-top: 1rem !important;\n }\n .mr-sm-3,\n .mx-sm-3 {\n margin-right: 1rem !important;\n }\n .mb-sm-3,\n .my-sm-3 {\n margin-bottom: 1rem !important;\n }\n .ml-sm-3,\n .mx-sm-3 {\n margin-left: 1rem !important;\n }\n .m-sm-4 {\n margin: 1.5rem !important;\n }\n .mt-sm-4,\n .my-sm-4 {\n margin-top: 1.5rem !important;\n }\n .mr-sm-4,\n .mx-sm-4 {\n margin-right: 1.5rem !important;\n }\n .mb-sm-4,\n .my-sm-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-sm-4,\n .mx-sm-4 {\n margin-left: 1.5rem !important;\n }\n .m-sm-5 {\n margin: 3rem !important;\n }\n .mt-sm-5,\n .my-sm-5 {\n margin-top: 3rem !important;\n }\n .mr-sm-5,\n .mx-sm-5 {\n margin-right: 3rem !important;\n }\n .mb-sm-5,\n .my-sm-5 {\n margin-bottom: 3rem !important;\n }\n .ml-sm-5,\n .mx-sm-5 {\n margin-left: 3rem !important;\n }\n .p-sm-0 {\n padding: 0 !important;\n }\n .pt-sm-0,\n .py-sm-0 {\n padding-top: 0 !important;\n }\n .pr-sm-0,\n .px-sm-0 {\n padding-right: 0 !important;\n }\n .pb-sm-0,\n .py-sm-0 {\n padding-bottom: 0 !important;\n }\n .pl-sm-0,\n .px-sm-0 {\n padding-left: 0 !important;\n }\n .p-sm-1 {\n padding: 0.25rem !important;\n }\n .pt-sm-1,\n .py-sm-1 {\n padding-top: 0.25rem !important;\n }\n .pr-sm-1,\n .px-sm-1 {\n padding-right: 0.25rem !important;\n }\n .pb-sm-1,\n .py-sm-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-sm-1,\n .px-sm-1 {\n padding-left: 0.25rem !important;\n }\n .p-sm-2 {\n padding: 0.5rem !important;\n }\n .pt-sm-2,\n .py-sm-2 {\n padding-top: 0.5rem !important;\n }\n .pr-sm-2,\n .px-sm-2 {\n padding-right: 0.5rem !important;\n }\n .pb-sm-2,\n .py-sm-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-sm-2,\n .px-sm-2 {\n padding-left: 0.5rem !important;\n }\n .p-sm-3 {\n padding: 1rem !important;\n }\n .pt-sm-3,\n .py-sm-3 {\n padding-top: 1rem !important;\n }\n .pr-sm-3,\n .px-sm-3 {\n padding-right: 1rem !important;\n }\n .pb-sm-3,\n .py-sm-3 {\n padding-bottom: 1rem !important;\n }\n .pl-sm-3,\n .px-sm-3 {\n padding-left: 1rem !important;\n }\n .p-sm-4 {\n padding: 1.5rem !important;\n }\n .pt-sm-4,\n .py-sm-4 {\n padding-top: 1.5rem !important;\n }\n .pr-sm-4,\n .px-sm-4 {\n padding-right: 1.5rem !important;\n }\n .pb-sm-4,\n .py-sm-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-sm-4,\n .px-sm-4 {\n padding-left: 1.5rem !important;\n }\n .p-sm-5 {\n padding: 3rem !important;\n }\n .pt-sm-5,\n .py-sm-5 {\n padding-top: 3rem !important;\n }\n .pr-sm-5,\n .px-sm-5 {\n padding-right: 3rem !important;\n }\n .pb-sm-5,\n .py-sm-5 {\n padding-bottom: 3rem !important;\n }\n .pl-sm-5,\n .px-sm-5 {\n padding-left: 3rem !important;\n }\n .m-sm-auto {\n margin: auto !important;\n }\n .mt-sm-auto,\n .my-sm-auto {\n margin-top: auto !important;\n }\n .mr-sm-auto,\n .mx-sm-auto {\n margin-right: auto !important;\n }\n .mb-sm-auto,\n .my-sm-auto {\n margin-bottom: auto !important;\n }\n .ml-sm-auto,\n .mx-sm-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 768px) {\n .m-md-0 {\n margin: 0 !important;\n }\n .mt-md-0,\n .my-md-0 {\n margin-top: 0 !important;\n }\n .mr-md-0,\n .mx-md-0 {\n margin-right: 0 !important;\n }\n .mb-md-0,\n .my-md-0 {\n margin-bottom: 0 !important;\n }\n .ml-md-0,\n .mx-md-0 {\n margin-left: 0 !important;\n }\n .m-md-1 {\n margin: 0.25rem !important;\n }\n .mt-md-1,\n .my-md-1 {\n margin-top: 0.25rem !important;\n }\n .mr-md-1,\n .mx-md-1 {\n margin-right: 0.25rem !important;\n }\n .mb-md-1,\n .my-md-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-md-1,\n .mx-md-1 {\n margin-left: 0.25rem !important;\n }\n .m-md-2 {\n margin: 0.5rem !important;\n }\n .mt-md-2,\n .my-md-2 {\n margin-top: 0.5rem !important;\n }\n .mr-md-2,\n .mx-md-2 {\n margin-right: 0.5rem !important;\n }\n .mb-md-2,\n .my-md-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-md-2,\n .mx-md-2 {\n margin-left: 0.5rem !important;\n }\n .m-md-3 {\n margin: 1rem !important;\n }\n .mt-md-3,\n .my-md-3 {\n margin-top: 1rem !important;\n }\n .mr-md-3,\n .mx-md-3 {\n margin-right: 1rem !important;\n }\n .mb-md-3,\n .my-md-3 {\n margin-bottom: 1rem !important;\n }\n .ml-md-3,\n .mx-md-3 {\n margin-left: 1rem !important;\n }\n .m-md-4 {\n margin: 1.5rem !important;\n }\n .mt-md-4,\n .my-md-4 {\n margin-top: 1.5rem !important;\n }\n .mr-md-4,\n .mx-md-4 {\n margin-right: 1.5rem !important;\n }\n .mb-md-4,\n .my-md-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-md-4,\n .mx-md-4 {\n margin-left: 1.5rem !important;\n }\n .m-md-5 {\n margin: 3rem !important;\n }\n .mt-md-5,\n .my-md-5 {\n margin-top: 3rem !important;\n }\n .mr-md-5,\n .mx-md-5 {\n margin-right: 3rem !important;\n }\n .mb-md-5,\n .my-md-5 {\n margin-bottom: 3rem !important;\n }\n .ml-md-5,\n .mx-md-5 {\n margin-left: 3rem !important;\n }\n .p-md-0 {\n padding: 0 !important;\n }\n .pt-md-0,\n .py-md-0 {\n padding-top: 0 !important;\n }\n .pr-md-0,\n .px-md-0 {\n padding-right: 0 !important;\n }\n .pb-md-0,\n .py-md-0 {\n padding-bottom: 0 !important;\n }\n .pl-md-0,\n .px-md-0 {\n padding-left: 0 !important;\n }\n .p-md-1 {\n padding: 0.25rem !important;\n }\n .pt-md-1,\n .py-md-1 {\n padding-top: 0.25rem !important;\n }\n .pr-md-1,\n .px-md-1 {\n padding-right: 0.25rem !important;\n }\n .pb-md-1,\n .py-md-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-md-1,\n .px-md-1 {\n padding-left: 0.25rem !important;\n }\n .p-md-2 {\n padding: 0.5rem !important;\n }\n .pt-md-2,\n .py-md-2 {\n padding-top: 0.5rem !important;\n }\n .pr-md-2,\n .px-md-2 {\n padding-right: 0.5rem !important;\n }\n .pb-md-2,\n .py-md-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-md-2,\n .px-md-2 {\n padding-left: 0.5rem !important;\n }\n .p-md-3 {\n padding: 1rem !important;\n }\n .pt-md-3,\n .py-md-3 {\n padding-top: 1rem !important;\n }\n .pr-md-3,\n .px-md-3 {\n padding-right: 1rem !important;\n }\n .pb-md-3,\n .py-md-3 {\n padding-bottom: 1rem !important;\n }\n .pl-md-3,\n .px-md-3 {\n padding-left: 1rem !important;\n }\n .p-md-4 {\n padding: 1.5rem !important;\n }\n .pt-md-4,\n .py-md-4 {\n padding-top: 1.5rem !important;\n }\n .pr-md-4,\n .px-md-4 {\n padding-right: 1.5rem !important;\n }\n .pb-md-4,\n .py-md-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-md-4,\n .px-md-4 {\n padding-left: 1.5rem !important;\n }\n .p-md-5 {\n padding: 3rem !important;\n }\n .pt-md-5,\n .py-md-5 {\n padding-top: 3rem !important;\n }\n .pr-md-5,\n .px-md-5 {\n padding-right: 3rem !important;\n }\n .pb-md-5,\n .py-md-5 {\n padding-bottom: 3rem !important;\n }\n .pl-md-5,\n .px-md-5 {\n padding-left: 3rem !important;\n }\n .m-md-auto {\n margin: auto !important;\n }\n .mt-md-auto,\n .my-md-auto {\n margin-top: auto !important;\n }\n .mr-md-auto,\n .mx-md-auto {\n margin-right: auto !important;\n }\n .mb-md-auto,\n .my-md-auto {\n margin-bottom: auto !important;\n }\n .ml-md-auto,\n .mx-md-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 992px) {\n .m-lg-0 {\n margin: 0 !important;\n }\n .mt-lg-0,\n .my-lg-0 {\n margin-top: 0 !important;\n }\n .mr-lg-0,\n .mx-lg-0 {\n margin-right: 0 !important;\n }\n .mb-lg-0,\n .my-lg-0 {\n margin-bottom: 0 !important;\n }\n .ml-lg-0,\n .mx-lg-0 {\n margin-left: 0 !important;\n }\n .m-lg-1 {\n margin: 0.25rem !important;\n }\n .mt-lg-1,\n .my-lg-1 {\n margin-top: 0.25rem !important;\n }\n .mr-lg-1,\n .mx-lg-1 {\n margin-right: 0.25rem !important;\n }\n .mb-lg-1,\n .my-lg-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-lg-1,\n .mx-lg-1 {\n margin-left: 0.25rem !important;\n }\n .m-lg-2 {\n margin: 0.5rem !important;\n }\n .mt-lg-2,\n .my-lg-2 {\n margin-top: 0.5rem !important;\n }\n .mr-lg-2,\n .mx-lg-2 {\n margin-right: 0.5rem !important;\n }\n .mb-lg-2,\n .my-lg-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-lg-2,\n .mx-lg-2 {\n margin-left: 0.5rem !important;\n }\n .m-lg-3 {\n margin: 1rem !important;\n }\n .mt-lg-3,\n .my-lg-3 {\n margin-top: 1rem !important;\n }\n .mr-lg-3,\n .mx-lg-3 {\n margin-right: 1rem !important;\n }\n .mb-lg-3,\n .my-lg-3 {\n margin-bottom: 1rem !important;\n }\n .ml-lg-3,\n .mx-lg-3 {\n margin-left: 1rem !important;\n }\n .m-lg-4 {\n margin: 1.5rem !important;\n }\n .mt-lg-4,\n .my-lg-4 {\n margin-top: 1.5rem !important;\n }\n .mr-lg-4,\n .mx-lg-4 {\n margin-right: 1.5rem !important;\n }\n .mb-lg-4,\n .my-lg-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-lg-4,\n .mx-lg-4 {\n margin-left: 1.5rem !important;\n }\n .m-lg-5 {\n margin: 3rem !important;\n }\n .mt-lg-5,\n .my-lg-5 {\n margin-top: 3rem !important;\n }\n .mr-lg-5,\n .mx-lg-5 {\n margin-right: 3rem !important;\n }\n .mb-lg-5,\n .my-lg-5 {\n margin-bottom: 3rem !important;\n }\n .ml-lg-5,\n .mx-lg-5 {\n margin-left: 3rem !important;\n }\n .p-lg-0 {\n padding: 0 !important;\n }\n .pt-lg-0,\n .py-lg-0 {\n padding-top: 0 !important;\n }\n .pr-lg-0,\n .px-lg-0 {\n padding-right: 0 !important;\n }\n .pb-lg-0,\n .py-lg-0 {\n padding-bottom: 0 !important;\n }\n .pl-lg-0,\n .px-lg-0 {\n padding-left: 0 !important;\n }\n .p-lg-1 {\n padding: 0.25rem !important;\n }\n .pt-lg-1,\n .py-lg-1 {\n padding-top: 0.25rem !important;\n }\n .pr-lg-1,\n .px-lg-1 {\n padding-right: 0.25rem !important;\n }\n .pb-lg-1,\n .py-lg-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-lg-1,\n .px-lg-1 {\n padding-left: 0.25rem !important;\n }\n .p-lg-2 {\n padding: 0.5rem !important;\n }\n .pt-lg-2,\n .py-lg-2 {\n padding-top: 0.5rem !important;\n }\n .pr-lg-2,\n .px-lg-2 {\n padding-right: 0.5rem !important;\n }\n .pb-lg-2,\n .py-lg-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-lg-2,\n .px-lg-2 {\n padding-left: 0.5rem !important;\n }\n .p-lg-3 {\n padding: 1rem !important;\n }\n .pt-lg-3,\n .py-lg-3 {\n padding-top: 1rem !important;\n }\n .pr-lg-3,\n .px-lg-3 {\n padding-right: 1rem !important;\n }\n .pb-lg-3,\n .py-lg-3 {\n padding-bottom: 1rem !important;\n }\n .pl-lg-3,\n .px-lg-3 {\n padding-left: 1rem !important;\n }\n .p-lg-4 {\n padding: 1.5rem !important;\n }\n .pt-lg-4,\n .py-lg-4 {\n padding-top: 1.5rem !important;\n }\n .pr-lg-4,\n .px-lg-4 {\n padding-right: 1.5rem !important;\n }\n .pb-lg-4,\n .py-lg-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-lg-4,\n .px-lg-4 {\n padding-left: 1.5rem !important;\n }\n .p-lg-5 {\n padding: 3rem !important;\n }\n .pt-lg-5,\n .py-lg-5 {\n padding-top: 3rem !important;\n }\n .pr-lg-5,\n .px-lg-5 {\n padding-right: 3rem !important;\n }\n .pb-lg-5,\n .py-lg-5 {\n padding-bottom: 3rem !important;\n }\n .pl-lg-5,\n .px-lg-5 {\n padding-left: 3rem !important;\n }\n .m-lg-auto {\n margin: auto !important;\n }\n .mt-lg-auto,\n .my-lg-auto {\n margin-top: auto !important;\n }\n .mr-lg-auto,\n .mx-lg-auto {\n margin-right: auto !important;\n }\n .mb-lg-auto,\n .my-lg-auto {\n margin-bottom: auto !important;\n }\n .ml-lg-auto,\n .mx-lg-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 1200px) {\n .m-xl-0 {\n margin: 0 !important;\n }\n .mt-xl-0,\n .my-xl-0 {\n margin-top: 0 !important;\n }\n .mr-xl-0,\n .mx-xl-0 {\n margin-right: 0 !important;\n }\n .mb-xl-0,\n .my-xl-0 {\n margin-bottom: 0 !important;\n }\n .ml-xl-0,\n .mx-xl-0 {\n margin-left: 0 !important;\n }\n .m-xl-1 {\n margin: 0.25rem !important;\n }\n .mt-xl-1,\n .my-xl-1 {\n margin-top: 0.25rem !important;\n }\n .mr-xl-1,\n .mx-xl-1 {\n margin-right: 0.25rem !important;\n }\n .mb-xl-1,\n .my-xl-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-xl-1,\n .mx-xl-1 {\n margin-left: 0.25rem !important;\n }\n .m-xl-2 {\n margin: 0.5rem !important;\n }\n .mt-xl-2,\n .my-xl-2 {\n margin-top: 0.5rem !important;\n }\n .mr-xl-2,\n .mx-xl-2 {\n margin-right: 0.5rem !important;\n }\n .mb-xl-2,\n .my-xl-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-xl-2,\n .mx-xl-2 {\n margin-left: 0.5rem !important;\n }\n .m-xl-3 {\n margin: 1rem !important;\n }\n .mt-xl-3,\n .my-xl-3 {\n margin-top: 1rem !important;\n }\n .mr-xl-3,\n .mx-xl-3 {\n margin-right: 1rem !important;\n }\n .mb-xl-3,\n .my-xl-3 {\n margin-bottom: 1rem !important;\n }\n .ml-xl-3,\n .mx-xl-3 {\n margin-left: 1rem !important;\n }\n .m-xl-4 {\n margin: 1.5rem !important;\n }\n .mt-xl-4,\n .my-xl-4 {\n margin-top: 1.5rem !important;\n }\n .mr-xl-4,\n .mx-xl-4 {\n margin-right: 1.5rem !important;\n }\n .mb-xl-4,\n .my-xl-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-xl-4,\n .mx-xl-4 {\n margin-left: 1.5rem !important;\n }\n .m-xl-5 {\n margin: 3rem !important;\n }\n .mt-xl-5,\n .my-xl-5 {\n margin-top: 3rem !important;\n }\n .mr-xl-5,\n .mx-xl-5 {\n margin-right: 3rem !important;\n }\n .mb-xl-5,\n .my-xl-5 {\n margin-bottom: 3rem !important;\n }\n .ml-xl-5,\n .mx-xl-5 {\n margin-left: 3rem !important;\n }\n .p-xl-0 {\n padding: 0 !important;\n }\n .pt-xl-0,\n .py-xl-0 {\n padding-top: 0 !important;\n }\n .pr-xl-0,\n .px-xl-0 {\n padding-right: 0 !important;\n }\n .pb-xl-0,\n .py-xl-0 {\n padding-bottom: 0 !important;\n }\n .pl-xl-0,\n .px-xl-0 {\n padding-left: 0 !important;\n }\n .p-xl-1 {\n padding: 0.25rem !important;\n }\n .pt-xl-1,\n .py-xl-1 {\n padding-top: 0.25rem !important;\n }\n .pr-xl-1,\n .px-xl-1 {\n padding-right: 0.25rem !important;\n }\n .pb-xl-1,\n .py-xl-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-xl-1,\n .px-xl-1 {\n padding-left: 0.25rem !important;\n }\n .p-xl-2 {\n padding: 0.5rem !important;\n }\n .pt-xl-2,\n .py-xl-2 {\n padding-top: 0.5rem !important;\n }\n .pr-xl-2,\n .px-xl-2 {\n padding-right: 0.5rem !important;\n }\n .pb-xl-2,\n .py-xl-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-xl-2,\n .px-xl-2 {\n padding-left: 0.5rem !important;\n }\n .p-xl-3 {\n padding: 1rem !important;\n }\n .pt-xl-3,\n .py-xl-3 {\n padding-top: 1rem !important;\n }\n .pr-xl-3,\n .px-xl-3 {\n padding-right: 1rem !important;\n }\n .pb-xl-3,\n .py-xl-3 {\n padding-bottom: 1rem !important;\n }\n .pl-xl-3,\n .px-xl-3 {\n padding-left: 1rem !important;\n }\n .p-xl-4 {\n padding: 1.5rem !important;\n }\n .pt-xl-4,\n .py-xl-4 {\n padding-top: 1.5rem !important;\n }\n .pr-xl-4,\n .px-xl-4 {\n padding-right: 1.5rem !important;\n }\n .pb-xl-4,\n .py-xl-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-xl-4,\n .px-xl-4 {\n padding-left: 1.5rem !important;\n }\n .p-xl-5 {\n padding: 3rem !important;\n }\n .pt-xl-5,\n .py-xl-5 {\n padding-top: 3rem !important;\n }\n .pr-xl-5,\n .px-xl-5 {\n padding-right: 3rem !important;\n }\n .pb-xl-5,\n .py-xl-5 {\n padding-bottom: 3rem !important;\n }\n .pl-xl-5,\n .px-xl-5 {\n padding-left: 3rem !important;\n }\n .m-xl-auto {\n margin: auto !important;\n }\n .mt-xl-auto,\n .my-xl-auto {\n margin-top: auto !important;\n }\n .mr-xl-auto,\n .mx-xl-auto {\n margin-right: auto !important;\n }\n .mb-xl-auto,\n .my-xl-auto {\n margin-bottom: auto !important;\n }\n .ml-xl-auto,\n .mx-xl-auto {\n margin-left: auto !important;\n }\n}\n\n.text-monospace {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n}\n\n.text-justify {\n text-align: justify !important;\n}\n\n.text-nowrap {\n white-space: nowrap !important;\n}\n\n.text-truncate {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.text-left {\n text-align: left !important;\n}\n\n.text-right {\n text-align: right !important;\n}\n\n.text-center {\n text-align: center !important;\n}\n\n@media (min-width: 576px) {\n .text-sm-left {\n text-align: left !important;\n }\n .text-sm-right {\n text-align: right !important;\n }\n .text-sm-center {\n text-align: center !important;\n }\n}\n\n@media (min-width: 768px) {\n .text-md-left {\n text-align: left !important;\n }\n .text-md-right {\n text-align: right !important;\n }\n .text-md-center {\n text-align: center !important;\n }\n}\n\n@media (min-width: 992px) {\n .text-lg-left {\n text-align: left !important;\n }\n .text-lg-right {\n text-align: right !important;\n }\n .text-lg-center {\n text-align: center !important;\n }\n}\n\n@media (min-width: 1200px) {\n .text-xl-left {\n text-align: left !important;\n }\n .text-xl-right {\n text-align: right !important;\n }\n .text-xl-center {\n text-align: center !important;\n }\n}\n\n.text-lowercase {\n text-transform: lowercase !important;\n}\n\n.text-uppercase {\n text-transform: uppercase !important;\n}\n\n.text-capitalize {\n text-transform: capitalize !important;\n}\n\n.font-weight-light {\n font-weight: 300 !important;\n}\n\n.font-weight-normal {\n font-weight: 400 !important;\n}\n\n.font-weight-bold {\n font-weight: 700 !important;\n}\n\n.font-italic {\n font-style: italic !important;\n}\n\n.text-white {\n color: #fff !important;\n}\n\n.text-primary {\n color: #007bff !important;\n}\n\na.text-primary:hover, a.text-primary:focus {\n color: #0062cc !important;\n}\n\n.text-secondary {\n color: #6c757d !important;\n}\n\na.text-secondary:hover, a.text-secondary:focus {\n color: #545b62 !important;\n}\n\n.text-success {\n color: #28a745 !important;\n}\n\na.text-success:hover, a.text-success:focus {\n color: #1e7e34 !important;\n}\n\n.text-info {\n color: #17a2b8 !important;\n}\n\na.text-info:hover, a.text-info:focus {\n color: #117a8b !important;\n}\n\n.text-warning {\n color: #ffc107 !important;\n}\n\na.text-warning:hover, a.text-warning:focus {\n color: #d39e00 !important;\n}\n\n.text-danger {\n color: #dc3545 !important;\n}\n\na.text-danger:hover, a.text-danger:focus {\n color: #bd2130 !important;\n}\n\n.text-light {\n color: #f8f9fa !important;\n}\n\na.text-light:hover, a.text-light:focus {\n color: #dae0e5 !important;\n}\n\n.text-dark {\n color: #343a40 !important;\n}\n\na.text-dark:hover, a.text-dark:focus {\n color: #1d2124 !important;\n}\n\n.text-body {\n color: #212529 !important;\n}\n\n.text-muted {\n color: #6c757d !important;\n}\n\n.text-black-50 {\n color: rgba(0, 0, 0, 0.5) !important;\n}\n\n.text-white-50 {\n color: rgba(255, 255, 255, 0.5) !important;\n}\n\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n\n.visible {\n visibility: visible !important;\n}\n\n.invisible {\n visibility: hidden !important;\n}\n\n@media print {\n *,\n *::before,\n *::after {\n text-shadow: none !important;\n box-shadow: none !important;\n }\n a:not(.btn) {\n text-decoration: underline;\n }\n abbr[title]::after {\n content: \" (\" attr(title) \")\";\n }\n pre {\n white-space: pre-wrap !important;\n }\n pre,\n blockquote {\n border: 1px solid #adb5bd;\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n @page {\n size: a3;\n }\n body {\n min-width: 992px !important;\n }\n .container {\n min-width: 992px !important;\n }\n .navbar {\n display: none;\n }\n .badge {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #dee2e6 !important;\n }\n .table-dark {\n color: inherit;\n }\n .table-dark th,\n .table-dark td,\n .table-dark thead th,\n .table-dark tbody + tbody {\n border-color: #dee2e6;\n }\n .table .thead-dark th {\n color: inherit;\n border-color: #dee2e6;\n }\n}\n\n/*# sourceMappingURL=bootstrap.css.map */","// Hover mixin and `$enable-hover-media-query` are deprecated.\n//\n// Originally added during our alphas and maintained during betas, this mixin was\n// designed to prevent `:hover` stickiness on iOS-an issue where hover styles\n// would persist after initial touch.\n//\n// For backward compatibility, we've kept these mixins and updated them to\n// always return their regular pseudo-classes instead of a shimmed media query.\n//\n// Issue: https://github.com/twbs/bootstrap/issues/25195\n\n@mixin hover {\n &:hover { @content; }\n}\n\n@mixin hover-focus {\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin plain-hover-focus {\n &,\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin hover-focus-active {\n &:hover,\n &:focus,\n &:active {\n @content;\n }\n}\n","// stylelint-disable declaration-no-important, selector-list-comma-newline-after\n\n//\n// Headings\n//\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n margin-bottom: $headings-margin-bottom;\n font-family: $headings-font-family;\n font-weight: $headings-font-weight;\n line-height: $headings-line-height;\n color: $headings-color;\n}\n\nh1, .h1 { font-size: $h1-font-size; }\nh2, .h2 { font-size: $h2-font-size; }\nh3, .h3 { font-size: $h3-font-size; }\nh4, .h4 { font-size: $h4-font-size; }\nh5, .h5 { font-size: $h5-font-size; }\nh6, .h6 { font-size: $h6-font-size; }\n\n.lead {\n font-size: $lead-font-size;\n font-weight: $lead-font-weight;\n}\n\n// Type display classes\n.display-1 {\n font-size: $display1-size;\n font-weight: $display1-weight;\n line-height: $display-line-height;\n}\n.display-2 {\n font-size: $display2-size;\n font-weight: $display2-weight;\n line-height: $display-line-height;\n}\n.display-3 {\n font-size: $display3-size;\n font-weight: $display3-weight;\n line-height: $display-line-height;\n}\n.display-4 {\n font-size: $display4-size;\n font-weight: $display4-weight;\n line-height: $display-line-height;\n}\n\n\n//\n// Horizontal rules\n//\n\nhr {\n margin-top: $hr-margin-y;\n margin-bottom: $hr-margin-y;\n border: 0;\n border-top: $hr-border-width solid $hr-border-color;\n}\n\n\n//\n// Emphasis\n//\n\nsmall,\n.small {\n font-size: $small-font-size;\n font-weight: $font-weight-normal;\n}\n\nmark,\n.mark {\n padding: $mark-padding;\n background-color: $mark-bg;\n}\n\n\n//\n// Lists\n//\n\n.list-unstyled {\n @include list-unstyled;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n @include list-unstyled;\n}\n.list-inline-item {\n display: inline-block;\n\n &:not(:last-child) {\n margin-right: $list-inline-padding;\n }\n}\n\n\n//\n// Misc\n//\n\n// Builds on `abbr`\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\n\n// Blockquotes\n.blockquote {\n margin-bottom: $spacer;\n font-size: $blockquote-font-size;\n}\n\n.blockquote-footer {\n display: block;\n font-size: 80%; // back to default font-size\n color: $blockquote-small-color;\n\n &::before {\n content: \"\\2014 \\00A0\"; // em dash, nbsp\n }\n}\n","// Lists\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n@mixin list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n","// Responsive images (ensure images don't scale beyond their parents)\n//\n// This is purposefully opt-in via an explicit class rather than being the default for all ``s.\n// We previously tried the \"images are responsive by default\" approach in Bootstrap v2,\n// and abandoned it in Bootstrap v3 because it breaks lots of third-party widgets (including Google Maps)\n// which weren't expecting the images within themselves to be involuntarily resized.\n// See also https://github.com/twbs/bootstrap/issues/18178\n.img-fluid {\n @include img-fluid;\n}\n\n\n// Image thumbnails\n.img-thumbnail {\n padding: $thumbnail-padding;\n background-color: $thumbnail-bg;\n border: $thumbnail-border-width solid $thumbnail-border-color;\n @include border-radius($thumbnail-border-radius);\n @include box-shadow($thumbnail-box-shadow);\n\n // Keep them at most 100% wide\n @include img-fluid;\n}\n\n//\n// Figures\n//\n\n.figure {\n // Ensures the caption's text aligns with the image.\n display: inline-block;\n}\n\n.figure-img {\n margin-bottom: ($spacer / 2);\n line-height: 1;\n}\n\n.figure-caption {\n font-size: $figure-caption-font-size;\n color: $figure-caption-color;\n}\n","// Image Mixins\n// - Responsive image\n// - Retina image\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n\n@mixin img-fluid {\n // Part 1: Set a maximum relative to the parent\n max-width: 100%;\n // Part 2: Override the height to auto, otherwise images will be stretched\n // when setting a width and height attribute on the img element.\n height: auto;\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size.\n\n// stylelint-disable indentation, media-query-list-comma-newline-after\n@mixin img-retina($file-1x, $file-2x, $width-1x, $height-1x) {\n background-image: url($file-1x);\n\n // Autoprefixer takes care of adding -webkit-min-device-pixel-ratio and -o-min-device-pixel-ratio,\n // but doesn't convert dppx=>dpi.\n // There's no such thing as unprefixed min-device-pixel-ratio since it's nonstandard.\n // Compatibility info: https://caniuse.com/#feat=css-media-resolution\n @media only screen and (min-resolution: 192dpi), // IE9-11 don't support dppx\n only screen and (min-resolution: 2dppx) { // Standardized\n background-image: url($file-2x);\n background-size: $width-1x $height-1x;\n }\n}\n","// Single side border-radius\n\n@mixin border-radius($radius: $border-radius) {\n @if $enable-rounded {\n border-radius: $radius;\n }\n}\n\n@mixin border-top-radius($radius) {\n @if $enable-rounded {\n border-top-left-radius: $radius;\n border-top-right-radius: $radius;\n }\n}\n\n@mixin border-right-radius($radius) {\n @if $enable-rounded {\n border-top-right-radius: $radius;\n border-bottom-right-radius: $radius;\n }\n}\n\n@mixin border-bottom-radius($radius) {\n @if $enable-rounded {\n border-bottom-right-radius: $radius;\n border-bottom-left-radius: $radius;\n }\n}\n\n@mixin border-left-radius($radius) {\n @if $enable-rounded {\n border-top-left-radius: $radius;\n border-bottom-left-radius: $radius;\n }\n}\n","// Inline code\ncode {\n font-size: $code-font-size;\n color: $code-color;\n word-break: break-word;\n\n // Streamline the style when inside anchors to avoid broken underline and more\n a > & {\n color: inherit;\n }\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: $kbd-padding-y $kbd-padding-x;\n font-size: $kbd-font-size;\n color: $kbd-color;\n background-color: $kbd-bg;\n @include border-radius($border-radius-sm);\n @include box-shadow($kbd-box-shadow);\n\n kbd {\n padding: 0;\n font-size: 100%;\n font-weight: $nested-kbd-font-weight;\n @include box-shadow(none);\n }\n}\n\n// Blocks of code\npre {\n display: block;\n font-size: $code-font-size;\n color: $pre-color;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n font-size: inherit;\n color: inherit;\n word-break: normal;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: $pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n@if $enable-grid-classes {\n .container {\n @include make-container();\n @include make-container-max-widths();\n }\n}\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but with 100% width for\n// fluid, full width layouts.\n\n@if $enable-grid-classes {\n .container-fluid {\n @include make-container();\n }\n}\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n@if $enable-grid-classes {\n .row {\n @include make-row();\n }\n\n // Remove the negative margin from default .row, then the horizontal padding\n // from all immediate children columns (to prevent runaway style inheritance).\n .no-gutters {\n margin-right: 0;\n margin-left: 0;\n\n > .col,\n > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n }\n }\n}\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n@if $enable-grid-classes {\n @include make-grid-columns();\n}\n","/// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n@mixin make-container() {\n width: 100%;\n padding-right: ($grid-gutter-width / 2);\n padding-left: ($grid-gutter-width / 2);\n margin-right: auto;\n margin-left: auto;\n}\n\n\n// For each breakpoint, define the maximum width of the container in a media query\n@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) {\n @each $breakpoint, $container-max-width in $max-widths {\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n max-width: $container-max-width;\n }\n }\n}\n\n@mixin make-row() {\n display: flex;\n flex-wrap: wrap;\n margin-right: ($grid-gutter-width / -2);\n margin-left: ($grid-gutter-width / -2);\n}\n\n@mixin make-col-ready() {\n position: relative;\n // Prevent columns from becoming too narrow when at smaller grid tiers by\n // always setting `width: 100%;`. This works because we use `flex` values\n // later on to override this initial width.\n width: 100%;\n min-height: 1px; // Prevent collapsing\n padding-right: ($grid-gutter-width / 2);\n padding-left: ($grid-gutter-width / 2);\n}\n\n@mixin make-col($size, $columns: $grid-columns) {\n flex: 0 0 percentage($size / $columns);\n // Add a `max-width` to ensure content within each column does not blow out\n // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari\n // do not appear to require this.\n max-width: percentage($size / $columns);\n}\n\n@mixin make-col-offset($size, $columns: $grid-columns) {\n $num: $size / $columns;\n margin-left: if($num == 0, 0, percentage($num));\n}\n","// Breakpoint viewport sizes and media queries.\n//\n// Breakpoints are defined as a map of (name: minimum width), order from small to large:\n//\n// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)\n//\n// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.\n\n// Name of the next breakpoint, or null for the last breakpoint.\n//\n// >> breakpoint-next(sm)\n// md\n// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// md\n// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))\n// md\n@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {\n $n: index($breakpoint-names, $name);\n @return if($n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);\n}\n\n// Minimum breakpoint width. Null for the smallest (first) breakpoint.\n//\n// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 576px\n@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {\n $min: map-get($breakpoints, $name);\n @return if($min != 0, $min, null);\n}\n\n// Maximum breakpoint width. Null for the largest (last) breakpoint.\n// The maximum value is calculated as the minimum of the next one less 0.02px\n// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths.\n// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max\n// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.\n// See https://bugs.webkit.org/show_bug.cgi?id=178261\n//\n// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 767.98px\n@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {\n $next: breakpoint-next($name, $breakpoints);\n @return if($next, breakpoint-min($next, $breakpoints) - .02px, null);\n}\n\n// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.\n// Useful for making responsive utilities.\n//\n// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"\" (Returns a blank string)\n// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"-sm\"\n@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {\n @return if(breakpoint-min($name, $breakpoints) == null, \"\", \"-#{$name}\");\n}\n\n// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.\n// Makes the @content apply to the given breakpoint and wider.\n@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n @if $min {\n @media (min-width: $min) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media of at most the maximum breakpoint width. No query for the largest breakpoint.\n// Makes the @content apply to the given breakpoint and narrower.\n@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {\n $max: breakpoint-max($name, $breakpoints);\n @if $max {\n @media (max-width: $max) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media that spans multiple breakpoint widths.\n// Makes the @content apply between the min and max breakpoints\n@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($lower, $breakpoints);\n $max: breakpoint-max($upper, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($lower, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($upper, $breakpoints) {\n @content;\n }\n }\n}\n\n// Media between the breakpoint's minimum and maximum widths.\n// No minimum for the smallest breakpoint, and no maximum for the largest one.\n// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.\n@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n $max: breakpoint-max($name, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($name, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($name, $breakpoints) {\n @content;\n }\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `$grid-columns`.\n\n@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {\n // Common properties for all breakpoints\n %grid-column {\n position: relative;\n width: 100%;\n min-height: 1px; // Prevent columns from collapsing when empty\n padding-right: ($gutter / 2);\n padding-left: ($gutter / 2);\n }\n\n @each $breakpoint in map-keys($breakpoints) {\n $infix: breakpoint-infix($breakpoint, $breakpoints);\n\n // Allow columns to stretch full width below their breakpoints\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @extend %grid-column;\n }\n }\n .col#{$infix},\n .col#{$infix}-auto {\n @extend %grid-column;\n }\n\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n // Provide basic `.col-{bp}` classes for equal-width flexbox columns\n .col#{$infix} {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col#{$infix}-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none; // Reset earlier grid tiers\n }\n\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @include make-col($i, $columns);\n }\n }\n\n .order#{$infix}-first { order: -1; }\n\n .order#{$infix}-last { order: $columns + 1; }\n\n @for $i from 0 through $columns {\n .order#{$infix}-#{$i} { order: $i; }\n }\n\n // `$columns - 1` because offsetting by the width of an entire row isn't possible\n @for $i from 0 through ($columns - 1) {\n @if not ($infix == \"\" and $i == 0) { // Avoid emitting useless .offset-0\n .offset#{$infix}-#{$i} {\n @include make-col-offset($i, $columns);\n }\n }\n }\n }\n }\n}\n","//\n// Basic Bootstrap table\n//\n\n.table {\n width: 100%;\n margin-bottom: $spacer;\n background-color: $table-bg; // Reset for nesting within parents with `background-color`.\n\n th,\n td {\n padding: $table-cell-padding;\n vertical-align: top;\n border-top: $table-border-width solid $table-border-color;\n }\n\n thead th {\n vertical-align: bottom;\n border-bottom: (2 * $table-border-width) solid $table-border-color;\n }\n\n tbody + tbody {\n border-top: (2 * $table-border-width) solid $table-border-color;\n }\n\n .table {\n background-color: $body-bg;\n }\n}\n\n\n//\n// Condensed table w/ half padding\n//\n\n.table-sm {\n th,\n td {\n padding: $table-cell-padding-sm;\n }\n}\n\n\n// Border versions\n//\n// Add or remove borders all around the table and between all the columns.\n\n.table-bordered {\n border: $table-border-width solid $table-border-color;\n\n th,\n td {\n border: $table-border-width solid $table-border-color;\n }\n\n thead {\n th,\n td {\n border-bottom-width: (2 * $table-border-width);\n }\n }\n}\n\n.table-borderless {\n th,\n td,\n thead th,\n tbody + tbody {\n border: 0;\n }\n}\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n tbody tr:nth-of-type(#{$table-striped-order}) {\n background-color: $table-accent-bg;\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n tbody tr {\n @include hover {\n background-color: $table-hover-bg;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n@each $color, $value in $theme-colors {\n @include table-row-variant($color, theme-color-level($color, -9));\n}\n\n@include table-row-variant(active, $table-active-bg);\n\n\n// Dark styles\n//\n// Same table markup, but inverted color scheme: dark background and light text.\n\n// stylelint-disable-next-line no-duplicate-selectors\n.table {\n .thead-dark {\n th {\n color: $table-dark-color;\n background-color: $table-dark-bg;\n border-color: $table-dark-border-color;\n }\n }\n\n .thead-light {\n th {\n color: $table-head-color;\n background-color: $table-head-bg;\n border-color: $table-border-color;\n }\n }\n}\n\n.table-dark {\n color: $table-dark-color;\n background-color: $table-dark-bg;\n\n th,\n td,\n thead th {\n border-color: $table-dark-border-color;\n }\n\n &.table-bordered {\n border: 0;\n }\n\n &.table-striped {\n tbody tr:nth-of-type(odd) {\n background-color: $table-dark-accent-bg;\n }\n }\n\n &.table-hover {\n tbody tr {\n @include hover {\n background-color: $table-dark-hover-bg;\n }\n }\n }\n}\n\n\n// Responsive tables\n//\n// Generate series of `.table-responsive-*` classes for configuring the screen\n// size of where your table will overflow.\n\n.table-responsive {\n @each $breakpoint in map-keys($grid-breakpoints) {\n $next: breakpoint-next($breakpoint, $grid-breakpoints);\n $infix: breakpoint-infix($next, $grid-breakpoints);\n\n &#{$infix} {\n @include media-breakpoint-down($breakpoint) {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n -ms-overflow-style: -ms-autohiding-scrollbar; // See https://github.com/twbs/bootstrap/pull/10057\n\n // Prevent double border on horizontal scroll due to use of `display: block;`\n > .table-bordered {\n border: 0;\n }\n }\n }\n }\n}\n","// Tables\n\n@mixin table-row-variant($state, $background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table-#{$state} {\n &,\n > th,\n > td {\n background-color: $background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover {\n $hover-background: darken($background, 5%);\n\n .table-#{$state} {\n @include hover {\n background-color: $hover-background;\n\n > td,\n > th {\n background-color: $hover-background;\n }\n }\n }\n }\n}\n","// Bootstrap functions\n//\n// Utility mixins and functions for evaluating source code across our variables, maps, and mixins.\n\n// Ascending\n// Used to evaluate Sass maps like our grid breakpoints.\n@mixin _assert-ascending($map, $map-name) {\n $prev-key: null;\n $prev-num: null;\n @each $key, $num in $map {\n @if $prev-num == null {\n // Do nothing\n } @else if not comparable($prev-num, $num) {\n @warn \"Potentially invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} whose unit makes it incomparable to #{$prev-num}, the value of the previous key '#{$prev-key}' !\";\n } @else if $prev-num >= $num {\n @warn \"Invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} which isn't greater than #{$prev-num}, the value of the previous key '#{$prev-key}' !\";\n }\n $prev-key: $key;\n $prev-num: $num;\n }\n}\n\n// Starts at zero\n// Another grid mixin that ensures the min-width of the lowest breakpoint starts at 0.\n@mixin _assert-starts-at-zero($map) {\n $values: map-values($map);\n $first-value: nth($values, 1);\n @if $first-value != 0 {\n @warn \"First breakpoint in `$grid-breakpoints` must start at 0, but starts at #{$first-value}.\";\n }\n}\n\n// Replace `$search` with `$replace` in `$string`\n// Used on our SVG icon backgrounds for custom forms.\n//\n// @author Hugo Giraudel\n// @param {String} $string - Initial string\n// @param {String} $search - Substring to replace\n// @param {String} $replace ('') - New value\n// @return {String} - Updated string\n@function str-replace($string, $search, $replace: \"\") {\n $index: str-index($string, $search);\n\n @if $index {\n @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);\n }\n\n @return $string;\n}\n\n// Color contrast\n@function color-yiq($color) {\n $r: red($color);\n $g: green($color);\n $b: blue($color);\n\n $yiq: (($r * 299) + ($g * 587) + ($b * 114)) / 1000;\n\n @if ($yiq >= $yiq-contrasted-threshold) {\n @return $yiq-text-dark;\n } @else {\n @return $yiq-text-light;\n }\n}\n\n// Retrieve color Sass maps\n@function color($key: \"blue\") {\n @return map-get($colors, $key);\n}\n\n@function theme-color($key: \"primary\") {\n @return map-get($theme-colors, $key);\n}\n\n@function gray($key: \"100\") {\n @return map-get($grays, $key);\n}\n\n// Request a theme color level\n@function theme-color-level($color-name: \"primary\", $level: 0) {\n $color: theme-color($color-name);\n $color-base: if($level > 0, $black, $white);\n $level: abs($level);\n\n @return mix($color-base, $color, $level * $theme-color-interval);\n}\n","// stylelint-disable selector-no-qualifying-type\n\n//\n// Textual form controls\n//\n\n.form-control {\n display: block;\n width: 100%;\n height: $input-height;\n padding: $input-padding-y $input-padding-x;\n font-size: $font-size-base;\n line-height: $input-line-height;\n color: $input-color;\n background-color: $input-bg;\n background-clip: padding-box;\n border: $input-border-width solid $input-border-color;\n\n // Note: This has no effect on `s in CSS.\n @if $enable-rounded {\n // Manually use the if/else instead of the mixin to account for iOS override\n border-radius: $input-border-radius;\n } @else {\n // Otherwise undo the iOS default\n border-radius: 0;\n }\n\n @include box-shadow($input-box-shadow);\n @include transition($input-transition);\n\n // Unstyle the caret on ` receives focus\n // in IE and (under certain conditions) Edge, as it looks bad and cannot be made to\n // match the appearance of the native widget.\n // See https://github.com/twbs/bootstrap/issues/19398.\n color: $input-color;\n background-color: $input-bg;\n }\n}\n\n// Make file inputs better match text inputs by forcing them to new lines.\n.form-control-file,\n.form-control-range {\n display: block;\n width: 100%;\n}\n\n\n//\n// Labels\n//\n\n// For use with horizontal and inline forms, when you need the label (or legend)\n// text to align with the form controls.\n.col-form-label {\n padding-top: calc(#{$input-padding-y} + #{$input-border-width});\n padding-bottom: calc(#{$input-padding-y} + #{$input-border-width});\n margin-bottom: 0; // Override the `
    ',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:vn},Ln="show",xn="out",Pn={HIDE:"hide"+Tn,HIDDEN:"hidden"+Tn,SHOW:"show"+Tn,SHOWN:"shown"+Tn,INSERTED:"inserted"+Tn,CLICK:"click"+Tn,FOCUSIN:"focusin"+Tn,FOCUSOUT:"focusout"+Tn,MOUSEENTER:"mouseenter"+Tn,MOUSELEAVE:"mouseleave"+Tn},Hn="fade",jn="show",Rn=".tooltip-inner",Fn=".arrow",Mn="hover",Wn="focus",Un="click",Bn="manual",qn=function(){function i(t,e){if("undefined"==typeof be)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var t=i.prototype;return t.enable=function(){this._isEnabled=!0},t.disable=function(){this._isEnabled=!1},t.toggleEnabled=function(){this._isEnabled=!this._isEnabled},t.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=p(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),p(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(p(this.getTipElement()).hasClass(jn))return void this._leave(null,this);this._enter(null,this)}},t.dispose=function(){clearTimeout(this._timeout),p.removeData(this.element,this.constructor.DATA_KEY),p(this.element).off(this.constructor.EVENT_KEY),p(this.element).closest(".modal").off("hide.bs.modal"),this.tip&&p(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,(this._activeTrigger=null)!==this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},t.show=function(){var e=this;if("none"===p(this.element).css("display"))throw new Error("Please use show on visible elements");var t=p.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){p(this.element).trigger(t);var n=m.findShadowRoot(this.element),i=p.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(t.isDefaultPrevented()||!i)return;var o=this.getTipElement(),r=m.getUID(this.constructor.NAME);o.setAttribute("id",r),this.element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&p(o).addClass(Hn);var s="function"==typeof this.config.placement?this.config.placement.call(this,o,this.element):this.config.placement,a=this._getAttachment(s);this.addAttachmentClass(a);var l=this._getContainer();p(o).data(this.constructor.DATA_KEY,this),p.contains(this.element.ownerDocument.documentElement,this.tip)||p(o).appendTo(l),p(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new be(this.element,o,{placement:a,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:Fn},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}}),p(o).addClass(jn),"ontouchstart"in document.documentElement&&p(document.body).children().on("mouseover",null,p.noop);var c=function(){e.config.animation&&e._fixTransition();var t=e._hoverState;e._hoverState=null,p(e.element).trigger(e.constructor.Event.SHOWN),t===xn&&e._leave(null,e)};if(p(this.tip).hasClass(Hn)){var h=m.getTransitionDurationFromElement(this.tip);p(this.tip).one(m.TRANSITION_END,c).emulateTransitionEnd(h)}else c()}},t.hide=function(t){var e=this,n=this.getTipElement(),i=p.Event(this.constructor.Event.HIDE),o=function(){e._hoverState!==Ln&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),p(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(p(this.element).trigger(i),!i.isDefaultPrevented()){if(p(n).removeClass(jn),"ontouchstart"in document.documentElement&&p(document.body).children().off("mouseover",null,p.noop),this._activeTrigger[Un]=!1,this._activeTrigger[Wn]=!1,this._activeTrigger[Mn]=!1,p(this.tip).hasClass(Hn)){var r=m.getTransitionDurationFromElement(n);p(n).one(m.TRANSITION_END,o).emulateTransitionEnd(r)}else o();this._hoverState=""}},t.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},t.isWithContent=function(){return Boolean(this.getTitle())},t.addAttachmentClass=function(t){p(this.getTipElement()).addClass(Dn+"-"+t)},t.getTipElement=function(){return this.tip=this.tip||p(this.config.template)[0],this.tip},t.setContent=function(){var t=this.getTipElement();this.setElementContent(p(t.querySelectorAll(Rn)),this.getTitle()),p(t).removeClass(Hn+" "+jn)},t.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=bn(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?p(e).parent().is(t)||t.empty().append(e):t.text(p(e).text())},t.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},t._getOffset=function(){var e=this,t={};return"function"==typeof this.config.offset?t.fn=function(t){return t.offsets=l({},t.offsets,e.config.offset(t.offsets,e.element)||{}),t}:t.offset=this.config.offset,t},t._getContainer=function(){return!1===this.config.container?document.body:m.isElement(this.config.container)?p(this.config.container):p(document).find(this.config.container)},t._getAttachment=function(t){return Nn[t.toUpperCase()]},t._setListeners=function(){var i=this;this.config.trigger.split(" ").forEach(function(t){if("click"===t)p(i.element).on(i.constructor.Event.CLICK,i.config.selector,function(t){return i.toggle(t)});else if(t!==Bn){var e=t===Mn?i.constructor.Event.MOUSEENTER:i.constructor.Event.FOCUSIN,n=t===Mn?i.constructor.Event.MOUSELEAVE:i.constructor.Event.FOCUSOUT;p(i.element).on(e,i.config.selector,function(t){return i._enter(t)}).on(n,i.config.selector,function(t){return i._leave(t)})}}),p(this.element).closest(".modal").on("hide.bs.modal",function(){i.element&&i.hide()}),this.config.selector?this.config=l({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},t._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},t._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||p(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),p(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Wn:Mn]=!0),p(e.getTipElement()).hasClass(jn)||e._hoverState===Ln?e._hoverState=Ln:(clearTimeout(e._timeout),e._hoverState=Ln,e.config.delay&&e.config.delay.show?e._timeout=setTimeout(function(){e._hoverState===Ln&&e.show()},e.config.delay.show):e.show())},t._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||p(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),p(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Wn:Mn]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=xn,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout(function(){e._hoverState===xn&&e.hide()},e.config.delay.hide):e.hide())},t._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},t._getConfig=function(t){var e=p(this.element).data();return Object.keys(e).forEach(function(t){-1!==An.indexOf(t)&&delete e[t]}),"number"==typeof(t=l({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),m.typeCheckConfig(wn,t,this.constructor.DefaultType),t.sanitize&&(t.template=bn(t.template,t.whiteList,t.sanitizeFn)),t},t._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},t._cleanTipClass=function(){var t=p(this.getTipElement()),e=t.attr("class").match(In);null!==e&&e.length&&t.removeClass(e.join(""))},t._handlePopperPlacementChange=function(t){var e=t.instance;this.tip=e.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},t._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(p(t).removeClass(Hn),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},i._jQueryInterface=function(n){return this.each(function(){var t=p(this).data(Cn),e="object"==typeof n&&n;if((t||!/dispose|hide/.test(n))&&(t||(t=new i(this,e),p(this).data(Cn,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return kn}},{key:"NAME",get:function(){return wn}},{key:"DATA_KEY",get:function(){return Cn}},{key:"Event",get:function(){return Pn}},{key:"EVENT_KEY",get:function(){return Tn}},{key:"DefaultType",get:function(){return On}}]),i}();p.fn[wn]=qn._jQueryInterface,p.fn[wn].Constructor=qn,p.fn[wn].noConflict=function(){return p.fn[wn]=Sn,qn._jQueryInterface};var Kn="popover",Qn="bs.popover",Vn="."+Qn,Yn=p.fn[Kn],zn="bs-popover",Xn=new RegExp("(^|\\s)"+zn+"\\S+","g"),Gn=l({},qn.Default,{placement:"right",trigger:"click",content:"",template:''}),$n=l({},qn.DefaultType,{content:"(string|element|function)"}),Jn="fade",Zn="show",ti=".popover-header",ei=".popover-body",ni={HIDE:"hide"+Vn,HIDDEN:"hidden"+Vn,SHOW:"show"+Vn,SHOWN:"shown"+Vn,INSERTED:"inserted"+Vn,CLICK:"click"+Vn,FOCUSIN:"focusin"+Vn,FOCUSOUT:"focusout"+Vn,MOUSEENTER:"mouseenter"+Vn,MOUSELEAVE:"mouseleave"+Vn},ii=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),(e.prototype.constructor=e).__proto__=n;var o=i.prototype;return o.isWithContent=function(){return this.getTitle()||this._getContent()},o.addAttachmentClass=function(t){p(this.getTipElement()).addClass(zn+"-"+t)},o.getTipElement=function(){return this.tip=this.tip||p(this.config.template)[0],this.tip},o.setContent=function(){var t=p(this.getTipElement());this.setElementContent(t.find(ti),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(ei),e),t.removeClass(Jn+" "+Zn)},o._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},o._cleanTipClass=function(){var t=p(this.getTipElement()),e=t.attr("class").match(Xn);null!==e&&0=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t= 0) {\n timeoutDuration = 1;\n break;\n }\n}\n\nfunction microtaskDebounce(fn) {\n var called = false;\n return function () {\n if (called) {\n return;\n }\n called = true;\n window.Promise.resolve().then(function () {\n called = false;\n fn();\n });\n };\n}\n\nfunction taskDebounce(fn) {\n var scheduled = false;\n return function () {\n if (!scheduled) {\n scheduled = true;\n setTimeout(function () {\n scheduled = false;\n fn();\n }, timeoutDuration);\n }\n };\n}\n\nvar supportsMicroTasks = isBrowser && window.Promise;\n\n/**\n* Create a debounced version of a method, that's asynchronously deferred\n* but called in the minimum time possible.\n*\n* @method\n* @memberof Popper.Utils\n* @argument {Function} fn\n* @returns {Function}\n*/\nvar debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce;\n\n/**\n * Check if the given variable is a function\n * @method\n * @memberof Popper.Utils\n * @argument {Any} functionToCheck - variable to check\n * @returns {Boolean} answer to: is a function?\n */\nfunction isFunction(functionToCheck) {\n var getType = {};\n return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';\n}\n\n/**\n * Get CSS computed property of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Eement} element\n * @argument {String} property\n */\nfunction getStyleComputedProperty(element, property) {\n if (element.nodeType !== 1) {\n return [];\n }\n // NOTE: 1 DOM access here\n var css = getComputedStyle(element, null);\n return property ? css[property] : css;\n}\n\n/**\n * Returns the parentNode or the host of the element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} parent\n */\nfunction getParentNode(element) {\n if (element.nodeName === 'HTML') {\n return element;\n }\n return element.parentNode || element.host;\n}\n\n/**\n * Returns the scrolling parent of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} scroll parent\n */\nfunction getScrollParent(element) {\n // Return body, `getScroll` will take care to get the correct `scrollTop` from it\n if (!element) {\n return document.body;\n }\n\n switch (element.nodeName) {\n case 'HTML':\n case 'BODY':\n return element.ownerDocument.body;\n case '#document':\n return element.body;\n }\n\n // Firefox want us to check `-x` and `-y` variations as well\n\n var _getStyleComputedProp = getStyleComputedProperty(element),\n overflow = _getStyleComputedProp.overflow,\n overflowX = _getStyleComputedProp.overflowX,\n overflowY = _getStyleComputedProp.overflowY;\n\n if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) {\n return element;\n }\n\n return getScrollParent(getParentNode(element));\n}\n\nvar isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode);\nvar isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent);\n\n/**\n * Determines if the browser is Internet Explorer\n * @method\n * @memberof Popper.Utils\n * @param {Number} version to check\n * @returns {Boolean} isIE\n */\nfunction isIE(version) {\n if (version === 11) {\n return isIE11;\n }\n if (version === 10) {\n return isIE10;\n }\n return isIE11 || isIE10;\n}\n\n/**\n * Returns the offset parent of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} offset parent\n */\nfunction getOffsetParent(element) {\n if (!element) {\n return document.documentElement;\n }\n\n var noOffsetParent = isIE(10) ? document.body : null;\n\n // NOTE: 1 DOM access here\n var offsetParent = element.offsetParent;\n // Skip hidden elements which don't have an offsetParent\n while (offsetParent === noOffsetParent && element.nextElementSibling) {\n offsetParent = (element = element.nextElementSibling).offsetParent;\n }\n\n var nodeName = offsetParent && offsetParent.nodeName;\n\n if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {\n return element ? element.ownerDocument.documentElement : document.documentElement;\n }\n\n // .offsetParent will return the closest TD or TABLE in case\n // no offsetParent is present, I hate this job...\n if (['TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {\n return getOffsetParent(offsetParent);\n }\n\n return offsetParent;\n}\n\nfunction isOffsetContainer(element) {\n var nodeName = element.nodeName;\n\n if (nodeName === 'BODY') {\n return false;\n }\n return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;\n}\n\n/**\n * Finds the root node (document, shadowDOM root) of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} node\n * @returns {Element} root node\n */\nfunction getRoot(node) {\n if (node.parentNode !== null) {\n return getRoot(node.parentNode);\n }\n\n return node;\n}\n\n/**\n * Finds the offset parent common to the two provided nodes\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element1\n * @argument {Element} element2\n * @returns {Element} common offset parent\n */\nfunction findCommonOffsetParent(element1, element2) {\n // This check is needed to avoid errors in case one of the elements isn't defined for any reason\n if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {\n return document.documentElement;\n }\n\n // Here we make sure to give as \"start\" the element that comes first in the DOM\n var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;\n var start = order ? element1 : element2;\n var end = order ? element2 : element1;\n\n // Get common ancestor container\n var range = document.createRange();\n range.setStart(start, 0);\n range.setEnd(end, 0);\n var commonAncestorContainer = range.commonAncestorContainer;\n\n // Both nodes are inside #document\n\n if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {\n if (isOffsetContainer(commonAncestorContainer)) {\n return commonAncestorContainer;\n }\n\n return getOffsetParent(commonAncestorContainer);\n }\n\n // one of the nodes is inside shadowDOM, find which one\n var element1root = getRoot(element1);\n if (element1root.host) {\n return findCommonOffsetParent(element1root.host, element2);\n } else {\n return findCommonOffsetParent(element1, getRoot(element2).host);\n }\n}\n\n/**\n * Gets the scroll value of the given element in the given side (top and left)\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @argument {String} side `top` or `left`\n * @returns {number} amount of scrolled pixels\n */\nfunction getScroll(element) {\n var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';\n\n var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';\n var nodeName = element.nodeName;\n\n if (nodeName === 'BODY' || nodeName === 'HTML') {\n var html = element.ownerDocument.documentElement;\n var scrollingElement = element.ownerDocument.scrollingElement || html;\n return scrollingElement[upperSide];\n }\n\n return element[upperSide];\n}\n\n/*\n * Sum or subtract the element scroll values (left and top) from a given rect object\n * @method\n * @memberof Popper.Utils\n * @param {Object} rect - Rect object you want to change\n * @param {HTMLElement} element - The element from the function reads the scroll values\n * @param {Boolean} subtract - set to true if you want to subtract the scroll values\n * @return {Object} rect - The modifier rect object\n */\nfunction includeScroll(rect, element) {\n var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n\n var scrollTop = getScroll(element, 'top');\n var scrollLeft = getScroll(element, 'left');\n var modifier = subtract ? -1 : 1;\n rect.top += scrollTop * modifier;\n rect.bottom += scrollTop * modifier;\n rect.left += scrollLeft * modifier;\n rect.right += scrollLeft * modifier;\n return rect;\n}\n\n/*\n * Helper to detect borders of a given element\n * @method\n * @memberof Popper.Utils\n * @param {CSSStyleDeclaration} styles\n * Result of `getStyleComputedProperty` on the given element\n * @param {String} axis - `x` or `y`\n * @return {number} borders - The borders size of the given axis\n */\n\nfunction getBordersSize(styles, axis) {\n var sideA = axis === 'x' ? 'Left' : 'Top';\n var sideB = sideA === 'Left' ? 'Right' : 'Bottom';\n\n return parseFloat(styles['border' + sideA + 'Width'], 10) + parseFloat(styles['border' + sideB + 'Width'], 10);\n}\n\nfunction getSize(axis, body, html, computedStyle) {\n return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE(10) ? html['offset' + axis] + computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')] + computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')] : 0);\n}\n\nfunction getWindowSizes() {\n var body = document.body;\n var html = document.documentElement;\n var computedStyle = isIE(10) && getComputedStyle(html);\n\n return {\n height: getSize('Height', body, html, computedStyle),\n width: getSize('Width', body, html, computedStyle)\n };\n}\n\nvar classCallCheck = function (instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n};\n\nvar createClass = function () {\n function defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n }\n\n return function (Constructor, protoProps, staticProps) {\n if (protoProps) defineProperties(Constructor.prototype, protoProps);\n if (staticProps) defineProperties(Constructor, staticProps);\n return Constructor;\n };\n}();\n\n\n\n\n\nvar defineProperty = function (obj, key, value) {\n if (key in obj) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n } else {\n obj[key] = value;\n }\n\n return obj;\n};\n\nvar _extends = Object.assign || function (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n\n return target;\n};\n\n/**\n * Given element offsets, generate an output similar to getBoundingClientRect\n * @method\n * @memberof Popper.Utils\n * @argument {Object} offsets\n * @returns {Object} ClientRect like output\n */\nfunction getClientRect(offsets) {\n return _extends({}, offsets, {\n right: offsets.left + offsets.width,\n bottom: offsets.top + offsets.height\n });\n}\n\n/**\n * Get bounding client rect of given element\n * @method\n * @memberof Popper.Utils\n * @param {HTMLElement} element\n * @return {Object} client rect\n */\nfunction getBoundingClientRect(element) {\n var rect = {};\n\n // IE10 10 FIX: Please, don't ask, the element isn't\n // considered in DOM in some circumstances...\n // This isn't reproducible in IE10 compatibility mode of IE11\n try {\n if (isIE(10)) {\n rect = element.getBoundingClientRect();\n var scrollTop = getScroll(element, 'top');\n var scrollLeft = getScroll(element, 'left');\n rect.top += scrollTop;\n rect.left += scrollLeft;\n rect.bottom += scrollTop;\n rect.right += scrollLeft;\n } else {\n rect = element.getBoundingClientRect();\n }\n } catch (e) {}\n\n var result = {\n left: rect.left,\n top: rect.top,\n width: rect.right - rect.left,\n height: rect.bottom - rect.top\n };\n\n // subtract scrollbar size from sizes\n var sizes = element.nodeName === 'HTML' ? getWindowSizes() : {};\n var width = sizes.width || element.clientWidth || result.right - result.left;\n var height = sizes.height || element.clientHeight || result.bottom - result.top;\n\n var horizScrollbar = element.offsetWidth - width;\n var vertScrollbar = element.offsetHeight - height;\n\n // if an hypothetical scrollbar is detected, we must be sure it's not a `border`\n // we make this check conditional for performance reasons\n if (horizScrollbar || vertScrollbar) {\n var styles = getStyleComputedProperty(element);\n horizScrollbar -= getBordersSize(styles, 'x');\n vertScrollbar -= getBordersSize(styles, 'y');\n\n result.width -= horizScrollbar;\n result.height -= vertScrollbar;\n }\n\n return getClientRect(result);\n}\n\nfunction getOffsetRectRelativeToArbitraryNode(children, parent) {\n var fixedPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n\n var isIE10 = isIE(10);\n var isHTML = parent.nodeName === 'HTML';\n var childrenRect = getBoundingClientRect(children);\n var parentRect = getBoundingClientRect(parent);\n var scrollParent = getScrollParent(children);\n\n var styles = getStyleComputedProperty(parent);\n var borderTopWidth = parseFloat(styles.borderTopWidth, 10);\n var borderLeftWidth = parseFloat(styles.borderLeftWidth, 10);\n\n // In cases where the parent is fixed, we must ignore negative scroll in offset calc\n if (fixedPosition && parent.nodeName === 'HTML') {\n parentRect.top = Math.max(parentRect.top, 0);\n parentRect.left = Math.max(parentRect.left, 0);\n }\n var offsets = getClientRect({\n top: childrenRect.top - parentRect.top - borderTopWidth,\n left: childrenRect.left - parentRect.left - borderLeftWidth,\n width: childrenRect.width,\n height: childrenRect.height\n });\n offsets.marginTop = 0;\n offsets.marginLeft = 0;\n\n // Subtract margins of documentElement in case it's being used as parent\n // we do this only on HTML because it's the only element that behaves\n // differently when margins are applied to it. The margins are included in\n // the box of the documentElement, in the other cases not.\n if (!isIE10 && isHTML) {\n var marginTop = parseFloat(styles.marginTop, 10);\n var marginLeft = parseFloat(styles.marginLeft, 10);\n\n offsets.top -= borderTopWidth - marginTop;\n offsets.bottom -= borderTopWidth - marginTop;\n offsets.left -= borderLeftWidth - marginLeft;\n offsets.right -= borderLeftWidth - marginLeft;\n\n // Attach marginTop and marginLeft because in some circumstances we may need them\n offsets.marginTop = marginTop;\n offsets.marginLeft = marginLeft;\n }\n\n if (isIE10 && !fixedPosition ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {\n offsets = includeScroll(offsets, parent);\n }\n\n return offsets;\n}\n\nfunction getViewportOffsetRectRelativeToArtbitraryNode(element) {\n var excludeScroll = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n\n var html = element.ownerDocument.documentElement;\n var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);\n var width = Math.max(html.clientWidth, window.innerWidth || 0);\n var height = Math.max(html.clientHeight, window.innerHeight || 0);\n\n var scrollTop = !excludeScroll ? getScroll(html) : 0;\n var scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0;\n\n var offset = {\n top: scrollTop - relativeOffset.top + relativeOffset.marginTop,\n left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,\n width: width,\n height: height\n };\n\n return getClientRect(offset);\n}\n\n/**\n * Check if the given element is fixed or is inside a fixed parent\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @argument {Element} customContainer\n * @returns {Boolean} answer to \"isFixed?\"\n */\nfunction isFixed(element) {\n var nodeName = element.nodeName;\n if (nodeName === 'BODY' || nodeName === 'HTML') {\n return false;\n }\n if (getStyleComputedProperty(element, 'position') === 'fixed') {\n return true;\n }\n return isFixed(getParentNode(element));\n}\n\n/**\n * Finds the first parent of an element that has a transformed property defined\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} first transformed parent or documentElement\n */\n\nfunction getFixedPositionOffsetParent(element) {\n // This check is needed to avoid errors in case one of the elements isn't defined for any reason\n if (!element || !element.parentElement || isIE()) {\n return document.documentElement;\n }\n var el = element.parentElement;\n while (el && getStyleComputedProperty(el, 'transform') === 'none') {\n el = el.parentElement;\n }\n return el || document.documentElement;\n}\n\n/**\n * Computed the boundaries limits and return them\n * @method\n * @memberof Popper.Utils\n * @param {HTMLElement} popper\n * @param {HTMLElement} reference\n * @param {number} padding\n * @param {HTMLElement} boundariesElement - Element used to define the boundaries\n * @param {Boolean} fixedPosition - Is in fixed position mode\n * @returns {Object} Coordinates of the boundaries\n */\nfunction getBoundaries(popper, reference, padding, boundariesElement) {\n var fixedPosition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;\n\n // NOTE: 1 DOM access here\n\n var boundaries = { top: 0, left: 0 };\n var offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);\n\n // Handle viewport case\n if (boundariesElement === 'viewport') {\n boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition);\n } else {\n // Handle other cases based on DOM element used as boundaries\n var boundariesNode = void 0;\n if (boundariesElement === 'scrollParent') {\n boundariesNode = getScrollParent(getParentNode(reference));\n if (boundariesNode.nodeName === 'BODY') {\n boundariesNode = popper.ownerDocument.documentElement;\n }\n } else if (boundariesElement === 'window') {\n boundariesNode = popper.ownerDocument.documentElement;\n } else {\n boundariesNode = boundariesElement;\n }\n\n var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent, fixedPosition);\n\n // In case of HTML, we need a different computation\n if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {\n var _getWindowSizes = getWindowSizes(),\n height = _getWindowSizes.height,\n width = _getWindowSizes.width;\n\n boundaries.top += offsets.top - offsets.marginTop;\n boundaries.bottom = height + offsets.top;\n boundaries.left += offsets.left - offsets.marginLeft;\n boundaries.right = width + offsets.left;\n } else {\n // for all the other DOM elements, this one is good\n boundaries = offsets;\n }\n }\n\n // Add paddings\n boundaries.left += padding;\n boundaries.top += padding;\n boundaries.right -= padding;\n boundaries.bottom -= padding;\n\n return boundaries;\n}\n\nfunction getArea(_ref) {\n var width = _ref.width,\n height = _ref.height;\n\n return width * height;\n}\n\n/**\n * Utility used to transform the `auto` placement to the placement with more\n * available space.\n * @method\n * @memberof Popper.Utils\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) {\n var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;\n\n if (placement.indexOf('auto') === -1) {\n return placement;\n }\n\n var boundaries = getBoundaries(popper, reference, padding, boundariesElement);\n\n var rects = {\n top: {\n width: boundaries.width,\n height: refRect.top - boundaries.top\n },\n right: {\n width: boundaries.right - refRect.right,\n height: boundaries.height\n },\n bottom: {\n width: boundaries.width,\n height: boundaries.bottom - refRect.bottom\n },\n left: {\n width: refRect.left - boundaries.left,\n height: boundaries.height\n }\n };\n\n var sortedAreas = Object.keys(rects).map(function (key) {\n return _extends({\n key: key\n }, rects[key], {\n area: getArea(rects[key])\n });\n }).sort(function (a, b) {\n return b.area - a.area;\n });\n\n var filteredAreas = sortedAreas.filter(function (_ref2) {\n var width = _ref2.width,\n height = _ref2.height;\n return width >= popper.clientWidth && height >= popper.clientHeight;\n });\n\n var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;\n\n var variation = placement.split('-')[1];\n\n return computedPlacement + (variation ? '-' + variation : '');\n}\n\n/**\n * Get offsets to the reference element\n * @method\n * @memberof Popper.Utils\n * @param {Object} state\n * @param {Element} popper - the popper element\n * @param {Element} reference - the reference element (the popper will be relative to this)\n * @param {Element} fixedPosition - is in fixed position mode\n * @returns {Object} An object containing the offsets which will be applied to the popper\n */\nfunction getReferenceOffsets(state, popper, reference) {\n var fixedPosition = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;\n\n var commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);\n return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition);\n}\n\n/**\n * Get the outer sizes of the given element (offset size + margins)\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Object} object containing width and height properties\n */\nfunction getOuterSizes(element) {\n var styles = getComputedStyle(element);\n var x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom);\n var y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight);\n var result = {\n width: element.offsetWidth + y,\n height: element.offsetHeight + x\n };\n return result;\n}\n\n/**\n * Get the opposite placement of the given one\n * @method\n * @memberof Popper.Utils\n * @argument {String} placement\n * @returns {String} flipped placement\n */\nfunction getOppositePlacement(placement) {\n var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };\n return placement.replace(/left|right|bottom|top/g, function (matched) {\n return hash[matched];\n });\n}\n\n/**\n * Get offsets to the popper\n * @method\n * @memberof Popper.Utils\n * @param {Object} position - CSS position the Popper will get applied\n * @param {HTMLElement} popper - the popper element\n * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)\n * @param {String} placement - one of the valid placement options\n * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper\n */\nfunction getPopperOffsets(popper, referenceOffsets, placement) {\n placement = placement.split('-')[0];\n\n // Get popper node sizes\n var popperRect = getOuterSizes(popper);\n\n // Add position, width and height to our offsets object\n var popperOffsets = {\n width: popperRect.width,\n height: popperRect.height\n };\n\n // depending by the popper placement we have to compute its offsets slightly differently\n var isHoriz = ['right', 'left'].indexOf(placement) !== -1;\n var mainSide = isHoriz ? 'top' : 'left';\n var secondarySide = isHoriz ? 'left' : 'top';\n var measurement = isHoriz ? 'height' : 'width';\n var secondaryMeasurement = !isHoriz ? 'height' : 'width';\n\n popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;\n if (placement === secondarySide) {\n popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];\n } else {\n popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];\n }\n\n return popperOffsets;\n}\n\n/**\n * Mimics the `find` method of Array\n * @method\n * @memberof Popper.Utils\n * @argument {Array} arr\n * @argument prop\n * @argument value\n * @returns index or -1\n */\nfunction find(arr, check) {\n // use native find if supported\n if (Array.prototype.find) {\n return arr.find(check);\n }\n\n // use `filter` to obtain the same behavior of `find`\n return arr.filter(check)[0];\n}\n\n/**\n * Return the index of the matching object\n * @method\n * @memberof Popper.Utils\n * @argument {Array} arr\n * @argument prop\n * @argument value\n * @returns index or -1\n */\nfunction findIndex(arr, prop, value) {\n // use native findIndex if supported\n if (Array.prototype.findIndex) {\n return arr.findIndex(function (cur) {\n return cur[prop] === value;\n });\n }\n\n // use `find` + `indexOf` if `findIndex` isn't supported\n var match = find(arr, function (obj) {\n return obj[prop] === value;\n });\n return arr.indexOf(match);\n}\n\n/**\n * Loop trough the list of modifiers and run them in order,\n * each of them will then edit the data object.\n * @method\n * @memberof Popper.Utils\n * @param {dataObject} data\n * @param {Array} modifiers\n * @param {String} ends - Optional modifier name used as stopper\n * @returns {dataObject}\n */\nfunction runModifiers(modifiers, data, ends) {\n var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));\n\n modifiersToRun.forEach(function (modifier) {\n if (modifier['function']) {\n // eslint-disable-line dot-notation\n console.warn('`modifier.function` is deprecated, use `modifier.fn`!');\n }\n var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation\n if (modifier.enabled && isFunction(fn)) {\n // Add properties to offsets to make them a complete clientRect object\n // we do this before each modifier to make sure the previous one doesn't\n // mess with these values\n data.offsets.popper = getClientRect(data.offsets.popper);\n data.offsets.reference = getClientRect(data.offsets.reference);\n\n data = fn(data, modifier);\n }\n });\n\n return data;\n}\n\n/**\n * Updates the position of the popper, computing the new offsets and applying\n * the new style.
    \n * Prefer `scheduleUpdate` over `update` because of performance reasons.\n * @method\n * @memberof Popper\n */\nfunction update() {\n // if popper is destroyed, don't perform any further update\n if (this.state.isDestroyed) {\n return;\n }\n\n var data = {\n instance: this,\n styles: {},\n arrowStyles: {},\n attributes: {},\n flipped: false,\n offsets: {}\n };\n\n // compute reference element offsets\n data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference, this.options.positionFixed);\n\n // compute auto placement, store placement inside the data object,\n // modifiers will be able to edit `placement` if needed\n // and refer to originalPlacement to know the original value\n data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding);\n\n // store the computed placement inside `originalPlacement`\n data.originalPlacement = data.placement;\n\n data.positionFixed = this.options.positionFixed;\n\n // compute the popper offsets\n data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement);\n\n data.offsets.popper.position = this.options.positionFixed ? 'fixed' : 'absolute';\n\n // run the modifiers\n data = runModifiers(this.modifiers, data);\n\n // the first `update` will call `onCreate` callback\n // the other ones will call `onUpdate` callback\n if (!this.state.isCreated) {\n this.state.isCreated = true;\n this.options.onCreate(data);\n } else {\n this.options.onUpdate(data);\n }\n}\n\n/**\n * Helper used to know if the given modifier is enabled.\n * @method\n * @memberof Popper.Utils\n * @returns {Boolean}\n */\nfunction isModifierEnabled(modifiers, modifierName) {\n return modifiers.some(function (_ref) {\n var name = _ref.name,\n enabled = _ref.enabled;\n return enabled && name === modifierName;\n });\n}\n\n/**\n * Get the prefixed supported property name\n * @method\n * @memberof Popper.Utils\n * @argument {String} property (camelCase)\n * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)\n */\nfunction getSupportedPropertyName(property) {\n var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];\n var upperProp = property.charAt(0).toUpperCase() + property.slice(1);\n\n for (var i = 0; i < prefixes.length; i++) {\n var prefix = prefixes[i];\n var toCheck = prefix ? '' + prefix + upperProp : property;\n if (typeof document.body.style[toCheck] !== 'undefined') {\n return toCheck;\n }\n }\n return null;\n}\n\n/**\n * Destroy the popper\n * @method\n * @memberof Popper\n */\nfunction destroy() {\n this.state.isDestroyed = true;\n\n // touch DOM only if `applyStyle` modifier is enabled\n if (isModifierEnabled(this.modifiers, 'applyStyle')) {\n this.popper.removeAttribute('x-placement');\n this.popper.style.position = '';\n this.popper.style.top = '';\n this.popper.style.left = '';\n this.popper.style.right = '';\n this.popper.style.bottom = '';\n this.popper.style.willChange = '';\n this.popper.style[getSupportedPropertyName('transform')] = '';\n }\n\n this.disableEventListeners();\n\n // remove the popper if user explicity asked for the deletion on destroy\n // do not use `remove` because IE11 doesn't support it\n if (this.options.removeOnDestroy) {\n this.popper.parentNode.removeChild(this.popper);\n }\n return this;\n}\n\n/**\n * Get the window associated with the element\n * @argument {Element} element\n * @returns {Window}\n */\nfunction getWindow(element) {\n var ownerDocument = element.ownerDocument;\n return ownerDocument ? ownerDocument.defaultView : window;\n}\n\nfunction attachToScrollParents(scrollParent, event, callback, scrollParents) {\n var isBody = scrollParent.nodeName === 'BODY';\n var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent;\n target.addEventListener(event, callback, { passive: true });\n\n if (!isBody) {\n attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);\n }\n scrollParents.push(target);\n}\n\n/**\n * Setup needed event listeners used to update the popper position\n * @method\n * @memberof Popper.Utils\n * @private\n */\nfunction setupEventListeners(reference, options, state, updateBound) {\n // Resize event listener on window\n state.updateBound = updateBound;\n getWindow(reference).addEventListener('resize', state.updateBound, { passive: true });\n\n // Scroll event listener on scroll parents\n var scrollElement = getScrollParent(reference);\n attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);\n state.scrollElement = scrollElement;\n state.eventsEnabled = true;\n\n return state;\n}\n\n/**\n * It will add resize/scroll events and start recalculating\n * position of the popper element when they are triggered.\n * @method\n * @memberof Popper\n */\nfunction enableEventListeners() {\n if (!this.state.eventsEnabled) {\n this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);\n }\n}\n\n/**\n * Remove event listeners used to update the popper position\n * @method\n * @memberof Popper.Utils\n * @private\n */\nfunction removeEventListeners(reference, state) {\n // Remove resize event listener on window\n getWindow(reference).removeEventListener('resize', state.updateBound);\n\n // Remove scroll event listener on scroll parents\n state.scrollParents.forEach(function (target) {\n target.removeEventListener('scroll', state.updateBound);\n });\n\n // Reset state\n state.updateBound = null;\n state.scrollParents = [];\n state.scrollElement = null;\n state.eventsEnabled = false;\n return state;\n}\n\n/**\n * It will remove resize/scroll events and won't recalculate popper position\n * when they are triggered. It also won't trigger onUpdate callback anymore,\n * unless you call `update` method manually.\n * @method\n * @memberof Popper\n */\nfunction disableEventListeners() {\n if (this.state.eventsEnabled) {\n cancelAnimationFrame(this.scheduleUpdate);\n this.state = removeEventListeners(this.reference, this.state);\n }\n}\n\n/**\n * Tells if a given input is a number\n * @method\n * @memberof Popper.Utils\n * @param {*} input to check\n * @return {Boolean}\n */\nfunction isNumeric(n) {\n return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);\n}\n\n/**\n * Set the style to the given popper\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element - Element to apply the style to\n * @argument {Object} styles\n * Object with a list of properties and values which will be applied to the element\n */\nfunction setStyles(element, styles) {\n Object.keys(styles).forEach(function (prop) {\n var unit = '';\n // add unit if the value is numeric and is one of the following\n if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {\n unit = 'px';\n }\n element.style[prop] = styles[prop] + unit;\n });\n}\n\n/**\n * Set the attributes to the given popper\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element - Element to apply the attributes to\n * @argument {Object} styles\n * Object with a list of properties and values which will be applied to the element\n */\nfunction setAttributes(element, attributes) {\n Object.keys(attributes).forEach(function (prop) {\n var value = attributes[prop];\n if (value !== false) {\n element.setAttribute(prop, attributes[prop]);\n } else {\n element.removeAttribute(prop);\n }\n });\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} data.styles - List of style properties - values to apply to popper element\n * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The same data object\n */\nfunction applyStyle(data) {\n // any property present in `data.styles` will be applied to the popper,\n // in this way we can make the 3rd party modifiers add custom styles to it\n // Be aware, modifiers could override the properties defined in the previous\n // lines of this modifier!\n setStyles(data.instance.popper, data.styles);\n\n // any property present in `data.attributes` will be applied to the popper,\n // they will be set as HTML attributes of the element\n setAttributes(data.instance.popper, data.attributes);\n\n // if arrowElement is defined and arrowStyles has some properties\n if (data.arrowElement && Object.keys(data.arrowStyles).length) {\n setStyles(data.arrowElement, data.arrowStyles);\n }\n\n return data;\n}\n\n/**\n * Set the x-placement attribute before everything else because it could be used\n * to add margins to the popper margins needs to be calculated to get the\n * correct popper offsets.\n * @method\n * @memberof Popper.modifiers\n * @param {HTMLElement} reference - The reference element used to position the popper\n * @param {HTMLElement} popper - The HTML element used as popper\n * @param {Object} options - Popper.js options\n */\nfunction applyStyleOnLoad(reference, popper, options, modifierOptions, state) {\n // compute reference element offsets\n var referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed);\n\n // compute auto placement, store placement inside the data object,\n // modifiers will be able to edit `placement` if needed\n // and refer to originalPlacement to know the original value\n var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding);\n\n popper.setAttribute('x-placement', placement);\n\n // Apply `position` to popper before anything else because\n // without the position applied we can't guarantee correct computations\n setStyles(popper, { position: options.positionFixed ? 'fixed' : 'absolute' });\n\n return options;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction computeStyle(data, options) {\n var x = options.x,\n y = options.y;\n var popper = data.offsets.popper;\n\n // Remove this legacy support in Popper.js v2\n\n var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) {\n return modifier.name === 'applyStyle';\n }).gpuAcceleration;\n if (legacyGpuAccelerationOption !== undefined) {\n console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');\n }\n var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration;\n\n var offsetParent = getOffsetParent(data.instance.popper);\n var offsetParentRect = getBoundingClientRect(offsetParent);\n\n // Styles\n var styles = {\n position: popper.position\n };\n\n // Avoid blurry text by using full pixel integers.\n // For pixel-perfect positioning, top/bottom prefers rounded\n // values, while left/right prefers floored values.\n var offsets = {\n left: Math.floor(popper.left),\n top: Math.round(popper.top),\n bottom: Math.round(popper.bottom),\n right: Math.floor(popper.right)\n };\n\n var sideA = x === 'bottom' ? 'top' : 'bottom';\n var sideB = y === 'right' ? 'left' : 'right';\n\n // if gpuAcceleration is set to `true` and transform is supported,\n // we use `translate3d` to apply the position to the popper we\n // automatically use the supported prefixed version if needed\n var prefixedProperty = getSupportedPropertyName('transform');\n\n // now, let's make a step back and look at this code closely (wtf?)\n // If the content of the popper grows once it's been positioned, it\n // may happen that the popper gets misplaced because of the new content\n // overflowing its reference element\n // To avoid this problem, we provide two options (x and y), which allow\n // the consumer to define the offset origin.\n // If we position a popper on top of a reference element, we can set\n // `x` to `top` to make the popper grow towards its top instead of\n // its bottom.\n var left = void 0,\n top = void 0;\n if (sideA === 'bottom') {\n top = -offsetParentRect.height + offsets.bottom;\n } else {\n top = offsets.top;\n }\n if (sideB === 'right') {\n left = -offsetParentRect.width + offsets.right;\n } else {\n left = offsets.left;\n }\n if (gpuAcceleration && prefixedProperty) {\n styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';\n styles[sideA] = 0;\n styles[sideB] = 0;\n styles.willChange = 'transform';\n } else {\n // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties\n var invertTop = sideA === 'bottom' ? -1 : 1;\n var invertLeft = sideB === 'right' ? -1 : 1;\n styles[sideA] = top * invertTop;\n styles[sideB] = left * invertLeft;\n styles.willChange = sideA + ', ' + sideB;\n }\n\n // Attributes\n var attributes = {\n 'x-placement': data.placement\n };\n\n // Update `data` attributes, styles and arrowStyles\n data.attributes = _extends({}, attributes, data.attributes);\n data.styles = _extends({}, styles, data.styles);\n data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles);\n\n return data;\n}\n\n/**\n * Helper used to know if the given modifier depends from another one.
    \n * It checks if the needed modifier is listed and enabled.\n * @method\n * @memberof Popper.Utils\n * @param {Array} modifiers - list of modifiers\n * @param {String} requestingName - name of requesting modifier\n * @param {String} requestedName - name of requested modifier\n * @returns {Boolean}\n */\nfunction isModifierRequired(modifiers, requestingName, requestedName) {\n var requesting = find(modifiers, function (_ref) {\n var name = _ref.name;\n return name === requestingName;\n });\n\n var isRequired = !!requesting && modifiers.some(function (modifier) {\n return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;\n });\n\n if (!isRequired) {\n var _requesting = '`' + requestingName + '`';\n var requested = '`' + requestedName + '`';\n console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!');\n }\n return isRequired;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction arrow(data, options) {\n var _data$offsets$arrow;\n\n // arrow depends on keepTogether in order to work\n if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {\n return data;\n }\n\n var arrowElement = options.element;\n\n // if arrowElement is a string, suppose it's a CSS selector\n if (typeof arrowElement === 'string') {\n arrowElement = data.instance.popper.querySelector(arrowElement);\n\n // if arrowElement is not found, don't run the modifier\n if (!arrowElement) {\n return data;\n }\n } else {\n // if the arrowElement isn't a query selector we must check that the\n // provided DOM node is child of its popper node\n if (!data.instance.popper.contains(arrowElement)) {\n console.warn('WARNING: `arrow.element` must be child of its popper element!');\n return data;\n }\n }\n\n var placement = data.placement.split('-')[0];\n var _data$offsets = data.offsets,\n popper = _data$offsets.popper,\n reference = _data$offsets.reference;\n\n var isVertical = ['left', 'right'].indexOf(placement) !== -1;\n\n var len = isVertical ? 'height' : 'width';\n var sideCapitalized = isVertical ? 'Top' : 'Left';\n var side = sideCapitalized.toLowerCase();\n var altSide = isVertical ? 'left' : 'top';\n var opSide = isVertical ? 'bottom' : 'right';\n var arrowElementSize = getOuterSizes(arrowElement)[len];\n\n //\n // extends keepTogether behavior making sure the popper and its\n // reference have enough pixels in conjuction\n //\n\n // top/left side\n if (reference[opSide] - arrowElementSize < popper[side]) {\n data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);\n }\n // bottom/right side\n if (reference[side] + arrowElementSize > popper[opSide]) {\n data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];\n }\n data.offsets.popper = getClientRect(data.offsets.popper);\n\n // compute center of the popper\n var center = reference[side] + reference[len] / 2 - arrowElementSize / 2;\n\n // Compute the sideValue using the updated popper offsets\n // take popper margin in account because we don't have this info available\n var css = getStyleComputedProperty(data.instance.popper);\n var popperMarginSide = parseFloat(css['margin' + sideCapitalized], 10);\n var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width'], 10);\n var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;\n\n // prevent arrowElement from being placed not contiguously to its popper\n sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);\n\n data.arrowElement = arrowElement;\n data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow);\n\n return data;\n}\n\n/**\n * Get the opposite placement variation of the given one\n * @method\n * @memberof Popper.Utils\n * @argument {String} placement variation\n * @returns {String} flipped placement variation\n */\nfunction getOppositeVariation(variation) {\n if (variation === 'end') {\n return 'start';\n } else if (variation === 'start') {\n return 'end';\n }\n return variation;\n}\n\n/**\n * List of accepted placements to use as values of the `placement` option.
    \n * Valid placements are:\n * - `auto`\n * - `top`\n * - `right`\n * - `bottom`\n * - `left`\n *\n * Each placement can have a variation from this list:\n * - `-start`\n * - `-end`\n *\n * Variations are interpreted easily if you think of them as the left to right\n * written languages. Horizontally (`top` and `bottom`), `start` is left and `end`\n * is right.
    \n * Vertically (`left` and `right`), `start` is top and `end` is bottom.\n *\n * Some valid examples are:\n * - `top-end` (on top of reference, right aligned)\n * - `right-start` (on right of reference, top aligned)\n * - `bottom` (on bottom, centered)\n * - `auto-right` (on the side with more space available, alignment depends by placement)\n *\n * @static\n * @type {Array}\n * @enum {String}\n * @readonly\n * @method placements\n * @memberof Popper\n */\nvar placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start'];\n\n// Get rid of `auto` `auto-start` and `auto-end`\nvar validPlacements = placements.slice(3);\n\n/**\n * Given an initial placement, returns all the subsequent placements\n * clockwise (or counter-clockwise).\n *\n * @method\n * @memberof Popper.Utils\n * @argument {String} placement - A valid placement (it accepts variations)\n * @argument {Boolean} counter - Set to true to walk the placements counterclockwise\n * @returns {Array} placements including their variations\n */\nfunction clockwise(placement) {\n var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n\n var index = validPlacements.indexOf(placement);\n var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index));\n return counter ? arr.reverse() : arr;\n}\n\nvar BEHAVIORS = {\n FLIP: 'flip',\n CLOCKWISE: 'clockwise',\n COUNTERCLOCKWISE: 'counterclockwise'\n};\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction flip(data, options) {\n // if `inner` modifier is enabled, we can't use the `flip` modifier\n if (isModifierEnabled(data.instance.modifiers, 'inner')) {\n return data;\n }\n\n if (data.flipped && data.placement === data.originalPlacement) {\n // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides\n return data;\n }\n\n var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement, data.positionFixed);\n\n var placement = data.placement.split('-')[0];\n var placementOpposite = getOppositePlacement(placement);\n var variation = data.placement.split('-')[1] || '';\n\n var flipOrder = [];\n\n switch (options.behavior) {\n case BEHAVIORS.FLIP:\n flipOrder = [placement, placementOpposite];\n break;\n case BEHAVIORS.CLOCKWISE:\n flipOrder = clockwise(placement);\n break;\n case BEHAVIORS.COUNTERCLOCKWISE:\n flipOrder = clockwise(placement, true);\n break;\n default:\n flipOrder = options.behavior;\n }\n\n flipOrder.forEach(function (step, index) {\n if (placement !== step || flipOrder.length === index + 1) {\n return data;\n }\n\n placement = data.placement.split('-')[0];\n placementOpposite = getOppositePlacement(placement);\n\n var popperOffsets = data.offsets.popper;\n var refOffsets = data.offsets.reference;\n\n // using floor because the reference offsets may contain decimals we are not going to consider here\n var floor = Math.floor;\n var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom);\n\n var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);\n var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);\n var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);\n var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);\n\n var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom;\n\n // flip the variation if required\n var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;\n var flippedVariation = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom);\n\n if (overlapsRef || overflowsBoundaries || flippedVariation) {\n // this boolean to detect any flip loop\n data.flipped = true;\n\n if (overlapsRef || overflowsBoundaries) {\n placement = flipOrder[index + 1];\n }\n\n if (flippedVariation) {\n variation = getOppositeVariation(variation);\n }\n\n data.placement = placement + (variation ? '-' + variation : '');\n\n // this object contains `position`, we want to preserve it along with\n // any additional property we may add in the future\n data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));\n\n data = runModifiers(data.instance.modifiers, data, 'flip');\n }\n });\n return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction keepTogether(data) {\n var _data$offsets = data.offsets,\n popper = _data$offsets.popper,\n reference = _data$offsets.reference;\n\n var placement = data.placement.split('-')[0];\n var floor = Math.floor;\n var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;\n var side = isVertical ? 'right' : 'bottom';\n var opSide = isVertical ? 'left' : 'top';\n var measurement = isVertical ? 'width' : 'height';\n\n if (popper[side] < floor(reference[opSide])) {\n data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];\n }\n if (popper[opSide] > floor(reference[side])) {\n data.offsets.popper[opSide] = floor(reference[side]);\n }\n\n return data;\n}\n\n/**\n * Converts a string containing value + unit into a px value number\n * @function\n * @memberof {modifiers~offset}\n * @private\n * @argument {String} str - Value + unit string\n * @argument {String} measurement - `height` or `width`\n * @argument {Object} popperOffsets\n * @argument {Object} referenceOffsets\n * @returns {Number|String}\n * Value in pixels, or original string if no values were extracted\n */\nfunction toValue(str, measurement, popperOffsets, referenceOffsets) {\n // separate value from unit\n var split = str.match(/((?:\\-|\\+)?\\d*\\.?\\d*)(.*)/);\n var value = +split[1];\n var unit = split[2];\n\n // If it's not a number it's an operator, I guess\n if (!value) {\n return str;\n }\n\n if (unit.indexOf('%') === 0) {\n var element = void 0;\n switch (unit) {\n case '%p':\n element = popperOffsets;\n break;\n case '%':\n case '%r':\n default:\n element = referenceOffsets;\n }\n\n var rect = getClientRect(element);\n return rect[measurement] / 100 * value;\n } else if (unit === 'vh' || unit === 'vw') {\n // if is a vh or vw, we calculate the size based on the viewport\n var size = void 0;\n if (unit === 'vh') {\n size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);\n } else {\n size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);\n }\n return size / 100 * value;\n } else {\n // if is an explicit pixel unit, we get rid of the unit and keep the value\n // if is an implicit unit, it's px, and we return just the value\n return value;\n }\n}\n\n/**\n * Parse an `offset` string to extrapolate `x` and `y` numeric offsets.\n * @function\n * @memberof {modifiers~offset}\n * @private\n * @argument {String} offset\n * @argument {Object} popperOffsets\n * @argument {Object} referenceOffsets\n * @argument {String} basePlacement\n * @returns {Array} a two cells array with x and y offsets in numbers\n */\nfunction parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {\n var offsets = [0, 0];\n\n // Use height if placement is left or right and index is 0 otherwise use width\n // in this way the first offset will use an axis and the second one\n // will use the other one\n var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1;\n\n // Split the offset string to obtain a list of values and operands\n // The regex addresses values with the plus or minus sign in front (+10, -20, etc)\n var fragments = offset.split(/(\\+|\\-)/).map(function (frag) {\n return frag.trim();\n });\n\n // Detect if the offset string contains a pair of values or a single one\n // they could be separated by comma or space\n var divider = fragments.indexOf(find(fragments, function (frag) {\n return frag.search(/,|\\s/) !== -1;\n }));\n\n if (fragments[divider] && fragments[divider].indexOf(',') === -1) {\n console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');\n }\n\n // If divider is found, we divide the list of values and operands to divide\n // them by ofset X and Y.\n var splitRegex = /\\s*,\\s*|\\s+/;\n var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments];\n\n // Convert the values with units to absolute pixels to allow our computations\n ops = ops.map(function (op, index) {\n // Most of the units rely on the orientation of the popper\n var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';\n var mergeWithPrevious = false;\n return op\n // This aggregates any `+` or `-` sign that aren't considered operators\n // e.g.: 10 + +5 => [10, +, +5]\n .reduce(function (a, b) {\n if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {\n a[a.length - 1] = b;\n mergeWithPrevious = true;\n return a;\n } else if (mergeWithPrevious) {\n a[a.length - 1] += b;\n mergeWithPrevious = false;\n return a;\n } else {\n return a.concat(b);\n }\n }, [])\n // Here we convert the string values into number values (in px)\n .map(function (str) {\n return toValue(str, measurement, popperOffsets, referenceOffsets);\n });\n });\n\n // Loop trough the offsets arrays and execute the operations\n ops.forEach(function (op, index) {\n op.forEach(function (frag, index2) {\n if (isNumeric(frag)) {\n offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);\n }\n });\n });\n return offsets;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @argument {Number|String} options.offset=0\n * The offset value as described in the modifier description\n * @returns {Object} The data object, properly modified\n */\nfunction offset(data, _ref) {\n var offset = _ref.offset;\n var placement = data.placement,\n _data$offsets = data.offsets,\n popper = _data$offsets.popper,\n reference = _data$offsets.reference;\n\n var basePlacement = placement.split('-')[0];\n\n var offsets = void 0;\n if (isNumeric(+offset)) {\n offsets = [+offset, 0];\n } else {\n offsets = parseOffset(offset, popper, reference, basePlacement);\n }\n\n if (basePlacement === 'left') {\n popper.top += offsets[0];\n popper.left -= offsets[1];\n } else if (basePlacement === 'right') {\n popper.top += offsets[0];\n popper.left += offsets[1];\n } else if (basePlacement === 'top') {\n popper.left += offsets[0];\n popper.top -= offsets[1];\n } else if (basePlacement === 'bottom') {\n popper.left += offsets[0];\n popper.top += offsets[1];\n }\n\n data.popper = popper;\n return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction preventOverflow(data, options) {\n var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper);\n\n // If offsetParent is the reference element, we really want to\n // go one step up and use the next offsetParent as reference to\n // avoid to make this modifier completely useless and look like broken\n if (data.instance.reference === boundariesElement) {\n boundariesElement = getOffsetParent(boundariesElement);\n }\n\n // NOTE: DOM access here\n // resets the popper's position so that the document size can be calculated excluding\n // the size of the popper element itself\n var transformProp = getSupportedPropertyName('transform');\n var popperStyles = data.instance.popper.style; // assignment to help minification\n var top = popperStyles.top,\n left = popperStyles.left,\n transform = popperStyles[transformProp];\n\n popperStyles.top = '';\n popperStyles.left = '';\n popperStyles[transformProp] = '';\n\n var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement, data.positionFixed);\n\n // NOTE: DOM access here\n // restores the original style properties after the offsets have been computed\n popperStyles.top = top;\n popperStyles.left = left;\n popperStyles[transformProp] = transform;\n\n options.boundaries = boundaries;\n\n var order = options.priority;\n var popper = data.offsets.popper;\n\n var check = {\n primary: function primary(placement) {\n var value = popper[placement];\n if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {\n value = Math.max(popper[placement], boundaries[placement]);\n }\n return defineProperty({}, placement, value);\n },\n secondary: function secondary(placement) {\n var mainSide = placement === 'right' ? 'left' : 'top';\n var value = popper[mainSide];\n if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {\n value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));\n }\n return defineProperty({}, mainSide, value);\n }\n };\n\n order.forEach(function (placement) {\n var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';\n popper = _extends({}, popper, check[side](placement));\n });\n\n data.offsets.popper = popper;\n\n return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction shift(data) {\n var placement = data.placement;\n var basePlacement = placement.split('-')[0];\n var shiftvariation = placement.split('-')[1];\n\n // if shift shiftvariation is specified, run the modifier\n if (shiftvariation) {\n var _data$offsets = data.offsets,\n reference = _data$offsets.reference,\n popper = _data$offsets.popper;\n\n var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;\n var side = isVertical ? 'left' : 'top';\n var measurement = isVertical ? 'width' : 'height';\n\n var shiftOffsets = {\n start: defineProperty({}, side, reference[side]),\n end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])\n };\n\n data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]);\n }\n\n return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction hide(data) {\n if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {\n return data;\n }\n\n var refRect = data.offsets.reference;\n var bound = find(data.instance.modifiers, function (modifier) {\n return modifier.name === 'preventOverflow';\n }).boundaries;\n\n if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {\n // Avoid unnecessary DOM access if visibility hasn't changed\n if (data.hide === true) {\n return data;\n }\n\n data.hide = true;\n data.attributes['x-out-of-boundaries'] = '';\n } else {\n // Avoid unnecessary DOM access if visibility hasn't changed\n if (data.hide === false) {\n return data;\n }\n\n data.hide = false;\n data.attributes['x-out-of-boundaries'] = false;\n }\n\n return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction inner(data) {\n var placement = data.placement;\n var basePlacement = placement.split('-')[0];\n var _data$offsets = data.offsets,\n popper = _data$offsets.popper,\n reference = _data$offsets.reference;\n\n var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;\n\n var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;\n\n popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);\n\n data.placement = getOppositePlacement(placement);\n data.offsets.popper = getClientRect(popper);\n\n return data;\n}\n\n/**\n * Modifier function, each modifier can have a function of this type assigned\n * to its `fn` property.
    \n * These functions will be called on each update, this means that you must\n * make sure they are performant enough to avoid performance bottlenecks.\n *\n * @function ModifierFn\n * @argument {dataObject} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {dataObject} The data object, properly modified\n */\n\n/**\n * Modifiers are plugins used to alter the behavior of your poppers.
    \n * Popper.js uses a set of 9 modifiers to provide all the basic functionalities\n * needed by the library.\n *\n * Usually you don't want to override the `order`, `fn` and `onLoad` props.\n * All the other properties are configurations that could be tweaked.\n * @namespace modifiers\n */\nvar modifiers = {\n /**\n * Modifier used to shift the popper on the start or end of its reference\n * element.
    \n * It will read the variation of the `placement` property.
    \n * It can be one either `-end` or `-start`.\n * @memberof modifiers\n * @inner\n */\n shift: {\n /** @prop {number} order=100 - Index used to define the order of execution */\n order: 100,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: shift\n },\n\n /**\n * The `offset` modifier can shift your popper on both its axis.\n *\n * It accepts the following units:\n * - `px` or unitless, interpreted as pixels\n * - `%` or `%r`, percentage relative to the length of the reference element\n * - `%p`, percentage relative to the length of the popper element\n * - `vw`, CSS viewport width unit\n * - `vh`, CSS viewport height unit\n *\n * For length is intended the main axis relative to the placement of the popper.
    \n * This means that if the placement is `top` or `bottom`, the length will be the\n * `width`. In case of `left` or `right`, it will be the height.\n *\n * You can provide a single value (as `Number` or `String`), or a pair of values\n * as `String` divided by a comma or one (or more) white spaces.
    \n * The latter is a deprecated method because it leads to confusion and will be\n * removed in v2.
    \n * Additionally, it accepts additions and subtractions between different units.\n * Note that multiplications and divisions aren't supported.\n *\n * Valid examples are:\n * ```\n * 10\n * '10%'\n * '10, 10'\n * '10%, 10'\n * '10 + 10%'\n * '10 - 5vh + 3%'\n * '-10px + 5vh, 5px - 6%'\n * ```\n * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap\n * > with their reference element, unfortunately, you will have to disable the `flip` modifier.\n * > More on this [reading this issue](https://github.com/FezVrasta/popper.js/issues/373)\n *\n * @memberof modifiers\n * @inner\n */\n offset: {\n /** @prop {number} order=200 - Index used to define the order of execution */\n order: 200,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: offset,\n /** @prop {Number|String} offset=0\n * The offset value as described in the modifier description\n */\n offset: 0\n },\n\n /**\n * Modifier used to prevent the popper from being positioned outside the boundary.\n *\n * An scenario exists where the reference itself is not within the boundaries.
    \n * We can say it has \"escaped the boundaries\" — or just \"escaped\".
    \n * In this case we need to decide whether the popper should either:\n *\n * - detach from the reference and remain \"trapped\" in the boundaries, or\n * - if it should ignore the boundary and \"escape with its reference\"\n *\n * When `escapeWithReference` is set to`true` and reference is completely\n * outside its boundaries, the popper will overflow (or completely leave)\n * the boundaries in order to remain attached to the edge of the reference.\n *\n * @memberof modifiers\n * @inner\n */\n preventOverflow: {\n /** @prop {number} order=300 - Index used to define the order of execution */\n order: 300,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: preventOverflow,\n /**\n * @prop {Array} [priority=['left','right','top','bottom']]\n * Popper will try to prevent overflow following these priorities by default,\n * then, it could overflow on the left and on top of the `boundariesElement`\n */\n priority: ['left', 'right', 'top', 'bottom'],\n /**\n * @prop {number} padding=5\n * Amount of pixel used to define a minimum distance between the boundaries\n * and the popper this makes sure the popper has always a little padding\n * between the edges of its container\n */\n padding: 5,\n /**\n * @prop {String|HTMLElement} boundariesElement='scrollParent'\n * Boundaries used by the modifier, can be `scrollParent`, `window`,\n * `viewport` or any DOM element.\n */\n boundariesElement: 'scrollParent'\n },\n\n /**\n * Modifier used to make sure the reference and its popper stay near eachothers\n * without leaving any gap between the two. Expecially useful when the arrow is\n * enabled and you want to assure it to point to its reference element.\n * It cares only about the first axis, you can still have poppers with margin\n * between the popper and its reference element.\n * @memberof modifiers\n * @inner\n */\n keepTogether: {\n /** @prop {number} order=400 - Index used to define the order of execution */\n order: 400,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: keepTogether\n },\n\n /**\n * This modifier is used to move the `arrowElement` of the popper to make\n * sure it is positioned between the reference element and its popper element.\n * It will read the outer size of the `arrowElement` node to detect how many\n * pixels of conjuction are needed.\n *\n * It has no effect if no `arrowElement` is provided.\n * @memberof modifiers\n * @inner\n */\n arrow: {\n /** @prop {number} order=500 - Index used to define the order of execution */\n order: 500,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: arrow,\n /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */\n element: '[x-arrow]'\n },\n\n /**\n * Modifier used to flip the popper's placement when it starts to overlap its\n * reference element.\n *\n * Requires the `preventOverflow` modifier before it in order to work.\n *\n * **NOTE:** this modifier will interrupt the current update cycle and will\n * restart it if it detects the need to flip the placement.\n * @memberof modifiers\n * @inner\n */\n flip: {\n /** @prop {number} order=600 - Index used to define the order of execution */\n order: 600,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: flip,\n /**\n * @prop {String|Array} behavior='flip'\n * The behavior used to change the popper's placement. It can be one of\n * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid\n * placements (with optional variations).\n */\n behavior: 'flip',\n /**\n * @prop {number} padding=5\n * The popper will flip if it hits the edges of the `boundariesElement`\n */\n padding: 5,\n /**\n * @prop {String|HTMLElement} boundariesElement='viewport'\n * The element which will define the boundaries of the popper position,\n * the popper will never be placed outside of the defined boundaries\n * (except if keepTogether is enabled)\n */\n boundariesElement: 'viewport'\n },\n\n /**\n * Modifier used to make the popper flow toward the inner of the reference element.\n * By default, when this modifier is disabled, the popper will be placed outside\n * the reference element.\n * @memberof modifiers\n * @inner\n */\n inner: {\n /** @prop {number} order=700 - Index used to define the order of execution */\n order: 700,\n /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */\n enabled: false,\n /** @prop {ModifierFn} */\n fn: inner\n },\n\n /**\n * Modifier used to hide the popper when its reference element is outside of the\n * popper boundaries. It will set a `x-out-of-boundaries` attribute which can\n * be used to hide with a CSS selector the popper when its reference is\n * out of boundaries.\n *\n * Requires the `preventOverflow` modifier before it in order to work.\n * @memberof modifiers\n * @inner\n */\n hide: {\n /** @prop {number} order=800 - Index used to define the order of execution */\n order: 800,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: hide\n },\n\n /**\n * Computes the style that will be applied to the popper element to gets\n * properly positioned.\n *\n * Note that this modifier will not touch the DOM, it just prepares the styles\n * so that `applyStyle` modifier can apply it. This separation is useful\n * in case you need to replace `applyStyle` with a custom implementation.\n *\n * This modifier has `850` as `order` value to maintain backward compatibility\n * with previous versions of Popper.js. Expect the modifiers ordering method\n * to change in future major versions of the library.\n *\n * @memberof modifiers\n * @inner\n */\n computeStyle: {\n /** @prop {number} order=850 - Index used to define the order of execution */\n order: 850,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: computeStyle,\n /**\n * @prop {Boolean} gpuAcceleration=true\n * If true, it uses the CSS 3d transformation to position the popper.\n * Otherwise, it will use the `top` and `left` properties.\n */\n gpuAcceleration: true,\n /**\n * @prop {string} [x='bottom']\n * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin.\n * Change this if your popper should grow in a direction different from `bottom`\n */\n x: 'bottom',\n /**\n * @prop {string} [x='left']\n * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin.\n * Change this if your popper should grow in a direction different from `right`\n */\n y: 'right'\n },\n\n /**\n * Applies the computed styles to the popper element.\n *\n * All the DOM manipulations are limited to this modifier. This is useful in case\n * you want to integrate Popper.js inside a framework or view library and you\n * want to delegate all the DOM manipulations to it.\n *\n * Note that if you disable this modifier, you must make sure the popper element\n * has its position set to `absolute` before Popper.js can do its work!\n *\n * Just disable this modifier and define you own to achieve the desired effect.\n *\n * @memberof modifiers\n * @inner\n */\n applyStyle: {\n /** @prop {number} order=900 - Index used to define the order of execution */\n order: 900,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: applyStyle,\n /** @prop {Function} */\n onLoad: applyStyleOnLoad,\n /**\n * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier\n * @prop {Boolean} gpuAcceleration=true\n * If true, it uses the CSS 3d transformation to position the popper.\n * Otherwise, it will use the `top` and `left` properties.\n */\n gpuAcceleration: undefined\n }\n};\n\n/**\n * The `dataObject` is an object containing all the informations used by Popper.js\n * this object get passed to modifiers and to the `onCreate` and `onUpdate` callbacks.\n * @name dataObject\n * @property {Object} data.instance The Popper.js instance\n * @property {String} data.placement Placement applied to popper\n * @property {String} data.originalPlacement Placement originally defined on init\n * @property {Boolean} data.flipped True if popper has been flipped by flip modifier\n * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper.\n * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier\n * @property {Object} data.styles Any CSS property defined here will be applied to the popper, it expects the JavaScript nomenclature (eg. `marginBottom`)\n * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow, it expects the JavaScript nomenclature (eg. `marginBottom`)\n * @property {Object} data.boundaries Offsets of the popper boundaries\n * @property {Object} data.offsets The measurements of popper, reference and arrow elements.\n * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values\n * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values\n * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0\n */\n\n/**\n * Default options provided to Popper.js constructor.
    \n * These can be overriden using the `options` argument of Popper.js.
    \n * To override an option, simply pass as 3rd argument an object with the same\n * structure of this object, example:\n * ```\n * new Popper(ref, pop, {\n * modifiers: {\n * preventOverflow: { enabled: false }\n * }\n * })\n * ```\n * @type {Object}\n * @static\n * @memberof Popper\n */\nvar Defaults = {\n /**\n * Popper's placement\n * @prop {Popper.placements} placement='bottom'\n */\n placement: 'bottom',\n\n /**\n * Set this to true if you want popper to position it self in 'fixed' mode\n * @prop {Boolean} positionFixed=false\n */\n positionFixed: false,\n\n /**\n * Whether events (resize, scroll) are initially enabled\n * @prop {Boolean} eventsEnabled=true\n */\n eventsEnabled: true,\n\n /**\n * Set to true if you want to automatically remove the popper when\n * you call the `destroy` method.\n * @prop {Boolean} removeOnDestroy=false\n */\n removeOnDestroy: false,\n\n /**\n * Callback called when the popper is created.
    \n * By default, is set to no-op.
    \n * Access Popper.js instance with `data.instance`.\n * @prop {onCreate}\n */\n onCreate: function onCreate() {},\n\n /**\n * Callback called when the popper is updated, this callback is not called\n * on the initialization/creation of the popper, but only on subsequent\n * updates.
    \n * By default, is set to no-op.
    \n * Access Popper.js instance with `data.instance`.\n * @prop {onUpdate}\n */\n onUpdate: function onUpdate() {},\n\n /**\n * List of modifiers used to modify the offsets before they are applied to the popper.\n * They provide most of the functionalities of Popper.js\n * @prop {modifiers}\n */\n modifiers: modifiers\n};\n\n/**\n * @callback onCreate\n * @param {dataObject} data\n */\n\n/**\n * @callback onUpdate\n * @param {dataObject} data\n */\n\n// Utils\n// Methods\nvar Popper = function () {\n /**\n * Create a new Popper.js instance\n * @class Popper\n * @param {HTMLElement|referenceObject} reference - The reference element used to position the popper\n * @param {HTMLElement} popper - The HTML element used as popper.\n * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults)\n * @return {Object} instance - The generated Popper.js instance\n */\n function Popper(reference, popper) {\n var _this = this;\n\n var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n classCallCheck(this, Popper);\n\n this.scheduleUpdate = function () {\n return requestAnimationFrame(_this.update);\n };\n\n // make update() debounced, so that it only runs at most once-per-tick\n this.update = debounce(this.update.bind(this));\n\n // with {} we create a new object with the options inside it\n this.options = _extends({}, Popper.Defaults, options);\n\n // init state\n this.state = {\n isDestroyed: false,\n isCreated: false,\n scrollParents: []\n };\n\n // get reference and popper elements (allow jQuery wrappers)\n this.reference = reference && reference.jquery ? reference[0] : reference;\n this.popper = popper && popper.jquery ? popper[0] : popper;\n\n // Deep merge modifiers options\n this.options.modifiers = {};\n Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {\n _this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});\n });\n\n // Refactoring modifiers' list (Object => Array)\n this.modifiers = Object.keys(this.options.modifiers).map(function (name) {\n return _extends({\n name: name\n }, _this.options.modifiers[name]);\n })\n // sort the modifiers by order\n .sort(function (a, b) {\n return a.order - b.order;\n });\n\n // modifiers have the ability to execute arbitrary code when Popper.js get inited\n // such code is executed in the same order of its modifier\n // they could add new properties to their options configuration\n // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!\n this.modifiers.forEach(function (modifierOptions) {\n if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {\n modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state);\n }\n });\n\n // fire the first update to position the popper in the right place\n this.update();\n\n var eventsEnabled = this.options.eventsEnabled;\n if (eventsEnabled) {\n // setup event listeners, they will take care of update the position in specific situations\n this.enableEventListeners();\n }\n\n this.state.eventsEnabled = eventsEnabled;\n }\n\n // We can't use class properties because they don't get listed in the\n // class prototype and break stuff like Sinon stubs\n\n\n createClass(Popper, [{\n key: 'update',\n value: function update$$1() {\n return update.call(this);\n }\n }, {\n key: 'destroy',\n value: function destroy$$1() {\n return destroy.call(this);\n }\n }, {\n key: 'enableEventListeners',\n value: function enableEventListeners$$1() {\n return enableEventListeners.call(this);\n }\n }, {\n key: 'disableEventListeners',\n value: function disableEventListeners$$1() {\n return disableEventListeners.call(this);\n }\n\n /**\n * Schedule an update, it will run on the next UI update available\n * @method scheduleUpdate\n * @memberof Popper\n */\n\n\n /**\n * Collection of utilities useful when writing custom modifiers.\n * Starting from version 1.7, this method is available only if you\n * include `popper-utils.js` before `popper.js`.\n *\n * **DEPRECATION**: This way to access PopperUtils is deprecated\n * and will be removed in v2! Use the PopperUtils module directly instead.\n * Due to the high instability of the methods contained in Utils, we can't\n * guarantee them to follow semver. Use them at your own risk!\n * @static\n * @private\n * @type {Object}\n * @deprecated since version 1.8\n * @member Utils\n * @memberof Popper\n */\n\n }]);\n return Popper;\n}();\n\n/**\n * The `referenceObject` is an object that provides an interface compatible with Popper.js\n * and lets you use it as replacement of a real DOM node.
    \n * You can use this method to position a popper relatively to a set of coordinates\n * in case you don't have a DOM node to use as reference.\n *\n * ```\n * new Popper(referenceObject, popperNode);\n * ```\n *\n * NB: This feature isn't supported in Internet Explorer 10\n * @name referenceObject\n * @property {Function} data.getBoundingClientRect\n * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method.\n * @property {number} data.clientWidth\n * An ES6 getter that will return the width of the virtual reference element.\n * @property {number} data.clientHeight\n * An ES6 getter that will return the height of the virtual reference element.\n */\n\n\nPopper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils;\nPopper.placements = placements;\nPopper.Defaults = Defaults;\n\nexport default Popper;\n//# sourceMappingURL=popper.js.map\n","import $ from 'jquery'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): util.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Util = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Private TransitionEnd Helpers\n * ------------------------------------------------------------------------\n */\n\n const TRANSITION_END = 'transitionend'\n const MAX_UID = 1000000\n const MILLISECONDS_MULTIPLIER = 1000\n\n // Shoutout AngusCroll (https://goo.gl/pxwQGp)\n function toType(obj) {\n return {}.toString.call(obj).match(/\\s([a-z]+)/i)[1].toLowerCase()\n }\n\n function getSpecialTransitionEndEvent() {\n return {\n bindType: TRANSITION_END,\n delegateType: TRANSITION_END,\n handle(event) {\n if ($(event.target).is(this)) {\n return event.handleObj.handler.apply(this, arguments) // eslint-disable-line prefer-rest-params\n }\n return undefined // eslint-disable-line no-undefined\n }\n }\n }\n\n function transitionEndEmulator(duration) {\n let called = false\n\n $(this).one(Util.TRANSITION_END, () => {\n called = true\n })\n\n setTimeout(() => {\n if (!called) {\n Util.triggerTransitionEnd(this)\n }\n }, duration)\n\n return this\n }\n\n function setTransitionEndSupport() {\n $.fn.emulateTransitionEnd = transitionEndEmulator\n $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent()\n }\n\n /**\n * --------------------------------------------------------------------------\n * Public Util Api\n * --------------------------------------------------------------------------\n */\n\n const Util = {\n\n TRANSITION_END: 'bsTransitionEnd',\n\n getUID(prefix) {\n do {\n // eslint-disable-next-line no-bitwise\n prefix += ~~(Math.random() * MAX_UID) // \"~~\" acts like a faster Math.floor() here\n } while (document.getElementById(prefix))\n return prefix\n },\n\n getSelectorFromElement(element) {\n let selector = element.getAttribute('data-target')\n if (!selector || selector === '#') {\n selector = element.getAttribute('href') || ''\n }\n\n try {\n return document.querySelector(selector) ? selector : null\n } catch (err) {\n return null\n }\n },\n\n getTransitionDurationFromElement(element) {\n if (!element) {\n return 0\n }\n\n // Get transition-duration of the element\n let transitionDuration = $(element).css('transition-duration')\n const floatTransitionDuration = parseFloat(transitionDuration)\n\n // Return 0 if element or transition duration is not found\n if (!floatTransitionDuration) {\n return 0\n }\n\n // If multiple durations are defined, take the first\n transitionDuration = transitionDuration.split(',')[0]\n\n return parseFloat(transitionDuration) * MILLISECONDS_MULTIPLIER\n },\n\n reflow(element) {\n return element.offsetHeight\n },\n\n triggerTransitionEnd(element) {\n $(element).trigger(TRANSITION_END)\n },\n\n // TODO: Remove in v5\n supportsTransitionEnd() {\n return Boolean(TRANSITION_END)\n },\n\n isElement(obj) {\n return (obj[0] || obj).nodeType\n },\n\n typeCheckConfig(componentName, config, configTypes) {\n for (const property in configTypes) {\n if (Object.prototype.hasOwnProperty.call(configTypes, property)) {\n const expectedTypes = configTypes[property]\n const value = config[property]\n const valueType = value && Util.isElement(value)\n ? 'element' : toType(value)\n\n if (!new RegExp(expectedTypes).test(valueType)) {\n throw new Error(\n `${componentName.toUpperCase()}: ` +\n `Option \"${property}\" provided type \"${valueType}\" ` +\n `but expected type \"${expectedTypes}\".`)\n }\n }\n }\n }\n }\n\n setTransitionEndSupport()\n\n return Util\n})($)\n\nexport default Util\n","import $ from 'jquery'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): alert.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Alert = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'alert'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.alert'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n\n const Selector = {\n DISMISS : '[data-dismiss=\"alert\"]'\n }\n\n const Event = {\n CLOSE : `close${EVENT_KEY}`,\n CLOSED : `closed${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n ALERT : 'alert',\n FADE : 'fade',\n SHOW : 'show'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Alert {\n constructor(element) {\n this._element = element\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n // Public\n\n close(element) {\n let rootElement = this._element\n if (element) {\n rootElement = this._getRootElement(element)\n }\n\n const customEvent = this._triggerCloseEvent(rootElement)\n\n if (customEvent.isDefaultPrevented()) {\n return\n }\n\n this._removeElement(rootElement)\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n this._element = null\n }\n\n // Private\n\n _getRootElement(element) {\n const selector = Util.getSelectorFromElement(element)\n let parent = false\n\n if (selector) {\n parent = document.querySelector(selector)\n }\n\n if (!parent) {\n parent = $(element).closest(`.${ClassName.ALERT}`)[0]\n }\n\n return parent\n }\n\n _triggerCloseEvent(element) {\n const closeEvent = $.Event(Event.CLOSE)\n\n $(element).trigger(closeEvent)\n return closeEvent\n }\n\n _removeElement(element) {\n $(element).removeClass(ClassName.SHOW)\n\n if (!$(element).hasClass(ClassName.FADE)) {\n this._destroyElement(element)\n return\n }\n\n const transitionDuration = Util.getTransitionDurationFromElement(element)\n\n $(element)\n .one(Util.TRANSITION_END, (event) => this._destroyElement(element, event))\n .emulateTransitionEnd(transitionDuration)\n }\n\n _destroyElement(element) {\n $(element)\n .detach()\n .trigger(Event.CLOSED)\n .remove()\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n const $element = $(this)\n let data = $element.data(DATA_KEY)\n\n if (!data) {\n data = new Alert(this)\n $element.data(DATA_KEY, data)\n }\n\n if (config === 'close') {\n data[config](this)\n }\n })\n }\n\n static _handleDismiss(alertInstance) {\n return function (event) {\n if (event) {\n event.preventDefault()\n }\n\n alertInstance.close(this)\n }\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document).on(\n Event.CLICK_DATA_API,\n Selector.DISMISS,\n Alert._handleDismiss(new Alert())\n )\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Alert._jQueryInterface\n $.fn[NAME].Constructor = Alert\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Alert._jQueryInterface\n }\n\n return Alert\n})($)\n\nexport default Alert\n","import $ from 'jquery'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): button.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Button = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'button'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.button'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n\n const ClassName = {\n ACTIVE : 'active',\n BUTTON : 'btn',\n FOCUS : 'focus'\n }\n\n const Selector = {\n DATA_TOGGLE_CARROT : '[data-toggle^=\"button\"]',\n DATA_TOGGLE : '[data-toggle=\"buttons\"]',\n INPUT : 'input',\n ACTIVE : '.active',\n BUTTON : '.btn'\n }\n\n const Event = {\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`,\n FOCUS_BLUR_DATA_API : `focus${EVENT_KEY}${DATA_API_KEY} ` +\n `blur${EVENT_KEY}${DATA_API_KEY}`\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Button {\n constructor(element) {\n this._element = element\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n // Public\n\n toggle() {\n let triggerChangeEvent = true\n let addAriaPressed = true\n const rootElement = $(this._element).closest(\n Selector.DATA_TOGGLE\n )[0]\n\n if (rootElement) {\n const input = this._element.querySelector(Selector.INPUT)\n\n if (input) {\n if (input.type === 'radio') {\n if (input.checked &&\n this._element.classList.contains(ClassName.ACTIVE)) {\n triggerChangeEvent = false\n } else {\n const activeElement = rootElement.querySelector(Selector.ACTIVE)\n\n if (activeElement) {\n $(activeElement).removeClass(ClassName.ACTIVE)\n }\n }\n }\n\n if (triggerChangeEvent) {\n if (input.hasAttribute('disabled') ||\n rootElement.hasAttribute('disabled') ||\n input.classList.contains('disabled') ||\n rootElement.classList.contains('disabled')) {\n return\n }\n input.checked = !this._element.classList.contains(ClassName.ACTIVE)\n $(input).trigger('change')\n }\n\n input.focus()\n addAriaPressed = false\n }\n }\n\n if (addAriaPressed) {\n this._element.setAttribute('aria-pressed',\n !this._element.classList.contains(ClassName.ACTIVE))\n }\n\n if (triggerChangeEvent) {\n $(this._element).toggleClass(ClassName.ACTIVE)\n }\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n this._element = null\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n\n if (!data) {\n data = new Button(this)\n $(this).data(DATA_KEY, data)\n }\n\n if (config === 'toggle') {\n data[config]()\n }\n })\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document)\n .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => {\n event.preventDefault()\n\n let button = event.target\n\n if (!$(button).hasClass(ClassName.BUTTON)) {\n button = $(button).closest(Selector.BUTTON)\n }\n\n Button._jQueryInterface.call($(button), 'toggle')\n })\n .on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => {\n const button = $(event.target).closest(Selector.BUTTON)[0]\n $(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type))\n })\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Button._jQueryInterface\n $.fn[NAME].Constructor = Button\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Button._jQueryInterface\n }\n\n return Button\n})($)\n\nexport default Button\n","import $ from 'jquery'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): carousel.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Carousel = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'carousel'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.carousel'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n const ARROW_LEFT_KEYCODE = 37 // KeyboardEvent.which value for left arrow key\n const ARROW_RIGHT_KEYCODE = 39 // KeyboardEvent.which value for right arrow key\n const TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch\n\n const Default = {\n interval : 5000,\n keyboard : true,\n slide : false,\n pause : 'hover',\n wrap : true\n }\n\n const DefaultType = {\n interval : '(number|boolean)',\n keyboard : 'boolean',\n slide : '(boolean|string)',\n pause : '(string|boolean)',\n wrap : 'boolean'\n }\n\n const Direction = {\n NEXT : 'next',\n PREV : 'prev',\n LEFT : 'left',\n RIGHT : 'right'\n }\n\n const Event = {\n SLIDE : `slide${EVENT_KEY}`,\n SLID : `slid${EVENT_KEY}`,\n KEYDOWN : `keydown${EVENT_KEY}`,\n MOUSEENTER : `mouseenter${EVENT_KEY}`,\n MOUSELEAVE : `mouseleave${EVENT_KEY}`,\n TOUCHEND : `touchend${EVENT_KEY}`,\n LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n CAROUSEL : 'carousel',\n ACTIVE : 'active',\n SLIDE : 'slide',\n RIGHT : 'carousel-item-right',\n LEFT : 'carousel-item-left',\n NEXT : 'carousel-item-next',\n PREV : 'carousel-item-prev',\n ITEM : 'carousel-item'\n }\n\n const Selector = {\n ACTIVE : '.active',\n ACTIVE_ITEM : '.active.carousel-item',\n ITEM : '.carousel-item',\n NEXT_PREV : '.carousel-item-next, .carousel-item-prev',\n INDICATORS : '.carousel-indicators',\n DATA_SLIDE : '[data-slide], [data-slide-to]',\n DATA_RIDE : '[data-ride=\"carousel\"]'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Carousel {\n constructor(element, config) {\n this._items = null\n this._interval = null\n this._activeElement = null\n\n this._isPaused = false\n this._isSliding = false\n\n this.touchTimeout = null\n\n this._config = this._getConfig(config)\n this._element = $(element)[0]\n this._indicatorsElement = this._element.querySelector(Selector.INDICATORS)\n\n this._addEventListeners()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n next() {\n if (!this._isSliding) {\n this._slide(Direction.NEXT)\n }\n }\n\n nextWhenVisible() {\n // Don't call next when the page isn't visible\n // or the carousel or its parent isn't visible\n if (!document.hidden &&\n ($(this._element).is(':visible') && $(this._element).css('visibility') !== 'hidden')) {\n this.next()\n }\n }\n\n prev() {\n if (!this._isSliding) {\n this._slide(Direction.PREV)\n }\n }\n\n pause(event) {\n if (!event) {\n this._isPaused = true\n }\n\n if (this._element.querySelector(Selector.NEXT_PREV)) {\n Util.triggerTransitionEnd(this._element)\n this.cycle(true)\n }\n\n clearInterval(this._interval)\n this._interval = null\n }\n\n cycle(event) {\n if (!event) {\n this._isPaused = false\n }\n\n if (this._interval) {\n clearInterval(this._interval)\n this._interval = null\n }\n\n if (this._config.interval && !this._isPaused) {\n this._interval = setInterval(\n (document.visibilityState ? this.nextWhenVisible : this.next).bind(this),\n this._config.interval\n )\n }\n }\n\n to(index) {\n this._activeElement = this._element.querySelector(Selector.ACTIVE_ITEM)\n\n const activeIndex = this._getItemIndex(this._activeElement)\n\n if (index > this._items.length - 1 || index < 0) {\n return\n }\n\n if (this._isSliding) {\n $(this._element).one(Event.SLID, () => this.to(index))\n return\n }\n\n if (activeIndex === index) {\n this.pause()\n this.cycle()\n return\n }\n\n const direction = index > activeIndex\n ? Direction.NEXT\n : Direction.PREV\n\n this._slide(direction, this._items[index])\n }\n\n dispose() {\n $(this._element).off(EVENT_KEY)\n $.removeData(this._element, DATA_KEY)\n\n this._items = null\n this._config = null\n this._element = null\n this._interval = null\n this._isPaused = null\n this._isSliding = null\n this._activeElement = null\n this._indicatorsElement = null\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...config\n }\n Util.typeCheckConfig(NAME, config, DefaultType)\n return config\n }\n\n _addEventListeners() {\n if (this._config.keyboard) {\n $(this._element)\n .on(Event.KEYDOWN, (event) => this._keydown(event))\n }\n\n if (this._config.pause === 'hover') {\n $(this._element)\n .on(Event.MOUSEENTER, (event) => this.pause(event))\n .on(Event.MOUSELEAVE, (event) => this.cycle(event))\n if ('ontouchstart' in document.documentElement) {\n // If it's a touch-enabled device, mouseenter/leave are fired as\n // part of the mouse compatibility events on first tap - the carousel\n // would stop cycling until user tapped out of it;\n // here, we listen for touchend, explicitly pause the carousel\n // (as if it's the second time we tap on it, mouseenter compat event\n // is NOT fired) and after a timeout (to allow for mouse compatibility\n // events to fire) we explicitly restart cycling\n $(this._element).on(Event.TOUCHEND, () => {\n this.pause()\n if (this.touchTimeout) {\n clearTimeout(this.touchTimeout)\n }\n this.touchTimeout = setTimeout((event) => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval)\n })\n }\n }\n }\n\n _keydown(event) {\n if (/input|textarea/i.test(event.target.tagName)) {\n return\n }\n\n switch (event.which) {\n case ARROW_LEFT_KEYCODE:\n event.preventDefault()\n this.prev()\n break\n case ARROW_RIGHT_KEYCODE:\n event.preventDefault()\n this.next()\n break\n default:\n }\n }\n\n _getItemIndex(element) {\n this._items = element && element.parentNode\n ? [].slice.call(element.parentNode.querySelectorAll(Selector.ITEM))\n : []\n return this._items.indexOf(element)\n }\n\n _getItemByDirection(direction, activeElement) {\n const isNextDirection = direction === Direction.NEXT\n const isPrevDirection = direction === Direction.PREV\n const activeIndex = this._getItemIndex(activeElement)\n const lastItemIndex = this._items.length - 1\n const isGoingToWrap = isPrevDirection && activeIndex === 0 ||\n isNextDirection && activeIndex === lastItemIndex\n\n if (isGoingToWrap && !this._config.wrap) {\n return activeElement\n }\n\n const delta = direction === Direction.PREV ? -1 : 1\n const itemIndex = (activeIndex + delta) % this._items.length\n\n return itemIndex === -1\n ? this._items[this._items.length - 1] : this._items[itemIndex]\n }\n\n _triggerSlideEvent(relatedTarget, eventDirectionName) {\n const targetIndex = this._getItemIndex(relatedTarget)\n const fromIndex = this._getItemIndex(this._element.querySelector(Selector.ACTIVE_ITEM))\n const slideEvent = $.Event(Event.SLIDE, {\n relatedTarget,\n direction: eventDirectionName,\n from: fromIndex,\n to: targetIndex\n })\n\n $(this._element).trigger(slideEvent)\n\n return slideEvent\n }\n\n _setActiveIndicatorElement(element) {\n if (this._indicatorsElement) {\n const indicators = [].slice.call(this._indicatorsElement.querySelectorAll(Selector.ACTIVE))\n $(indicators)\n .removeClass(ClassName.ACTIVE)\n\n const nextIndicator = this._indicatorsElement.children[\n this._getItemIndex(element)\n ]\n\n if (nextIndicator) {\n $(nextIndicator).addClass(ClassName.ACTIVE)\n }\n }\n }\n\n _slide(direction, element) {\n const activeElement = this._element.querySelector(Selector.ACTIVE_ITEM)\n const activeElementIndex = this._getItemIndex(activeElement)\n const nextElement = element || activeElement &&\n this._getItemByDirection(direction, activeElement)\n const nextElementIndex = this._getItemIndex(nextElement)\n const isCycling = Boolean(this._interval)\n\n let directionalClassName\n let orderClassName\n let eventDirectionName\n\n if (direction === Direction.NEXT) {\n directionalClassName = ClassName.LEFT\n orderClassName = ClassName.NEXT\n eventDirectionName = Direction.LEFT\n } else {\n directionalClassName = ClassName.RIGHT\n orderClassName = ClassName.PREV\n eventDirectionName = Direction.RIGHT\n }\n\n if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) {\n this._isSliding = false\n return\n }\n\n const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName)\n if (slideEvent.isDefaultPrevented()) {\n return\n }\n\n if (!activeElement || !nextElement) {\n // Some weirdness is happening, so we bail\n return\n }\n\n this._isSliding = true\n\n if (isCycling) {\n this.pause()\n }\n\n this._setActiveIndicatorElement(nextElement)\n\n const slidEvent = $.Event(Event.SLID, {\n relatedTarget: nextElement,\n direction: eventDirectionName,\n from: activeElementIndex,\n to: nextElementIndex\n })\n\n if ($(this._element).hasClass(ClassName.SLIDE)) {\n $(nextElement).addClass(orderClassName)\n\n Util.reflow(nextElement)\n\n $(activeElement).addClass(directionalClassName)\n $(nextElement).addClass(directionalClassName)\n\n const transitionDuration = Util.getTransitionDurationFromElement(activeElement)\n\n $(activeElement)\n .one(Util.TRANSITION_END, () => {\n $(nextElement)\n .removeClass(`${directionalClassName} ${orderClassName}`)\n .addClass(ClassName.ACTIVE)\n\n $(activeElement).removeClass(`${ClassName.ACTIVE} ${orderClassName} ${directionalClassName}`)\n\n this._isSliding = false\n\n setTimeout(() => $(this._element).trigger(slidEvent), 0)\n })\n .emulateTransitionEnd(transitionDuration)\n } else {\n $(activeElement).removeClass(ClassName.ACTIVE)\n $(nextElement).addClass(ClassName.ACTIVE)\n\n this._isSliding = false\n $(this._element).trigger(slidEvent)\n }\n\n if (isCycling) {\n this.cycle()\n }\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n let _config = {\n ...Default,\n ...$(this).data()\n }\n\n if (typeof config === 'object') {\n _config = {\n ..._config,\n ...config\n }\n }\n\n const action = typeof config === 'string' ? config : _config.slide\n\n if (!data) {\n data = new Carousel(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'number') {\n data.to(config)\n } else if (typeof action === 'string') {\n if (typeof data[action] === 'undefined') {\n throw new TypeError(`No method named \"${action}\"`)\n }\n data[action]()\n } else if (_config.interval) {\n data.pause()\n data.cycle()\n }\n })\n }\n\n static _dataApiClickHandler(event) {\n const selector = Util.getSelectorFromElement(this)\n\n if (!selector) {\n return\n }\n\n const target = $(selector)[0]\n\n if (!target || !$(target).hasClass(ClassName.CAROUSEL)) {\n return\n }\n\n const config = {\n ...$(target).data(),\n ...$(this).data()\n }\n const slideIndex = this.getAttribute('data-slide-to')\n\n if (slideIndex) {\n config.interval = false\n }\n\n Carousel._jQueryInterface.call($(target), config)\n\n if (slideIndex) {\n $(target).data(DATA_KEY).to(slideIndex)\n }\n\n event.preventDefault()\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document)\n .on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler)\n\n $(window).on(Event.LOAD_DATA_API, () => {\n const carousels = [].slice.call(document.querySelectorAll(Selector.DATA_RIDE))\n for (let i = 0, len = carousels.length; i < len; i++) {\n const $carousel = $(carousels[i])\n Carousel._jQueryInterface.call($carousel, $carousel.data())\n }\n })\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Carousel._jQueryInterface\n $.fn[NAME].Constructor = Carousel\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Carousel._jQueryInterface\n }\n\n return Carousel\n})($)\n\nexport default Carousel\n","import $ from 'jquery'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): collapse.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Collapse = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'collapse'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.collapse'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n\n const Default = {\n toggle : true,\n parent : ''\n }\n\n const DefaultType = {\n toggle : 'boolean',\n parent : '(string|element)'\n }\n\n const Event = {\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n SHOW : 'show',\n COLLAPSE : 'collapse',\n COLLAPSING : 'collapsing',\n COLLAPSED : 'collapsed'\n }\n\n const Dimension = {\n WIDTH : 'width',\n HEIGHT : 'height'\n }\n\n const Selector = {\n ACTIVES : '.show, .collapsing',\n DATA_TOGGLE : '[data-toggle=\"collapse\"]'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Collapse {\n constructor(element, config) {\n this._isTransitioning = false\n this._element = element\n this._config = this._getConfig(config)\n this._triggerArray = $.makeArray(document.querySelectorAll(\n `[data-toggle=\"collapse\"][href=\"#${element.id}\"],` +\n `[data-toggle=\"collapse\"][data-target=\"#${element.id}\"]`\n ))\n const toggleList = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE))\n for (let i = 0, len = toggleList.length; i < len; i++) {\n const elem = toggleList[i]\n const selector = Util.getSelectorFromElement(elem)\n const filterElement = [].slice.call(document.querySelectorAll(selector))\n .filter((foundElem) => foundElem === element)\n\n if (selector !== null && filterElement.length > 0) {\n this._selector = selector\n this._triggerArray.push(elem)\n }\n }\n\n this._parent = this._config.parent ? this._getParent() : null\n\n if (!this._config.parent) {\n this._addAriaAndCollapsedClass(this._element, this._triggerArray)\n }\n\n if (this._config.toggle) {\n this.toggle()\n }\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n toggle() {\n if ($(this._element).hasClass(ClassName.SHOW)) {\n this.hide()\n } else {\n this.show()\n }\n }\n\n show() {\n if (this._isTransitioning ||\n $(this._element).hasClass(ClassName.SHOW)) {\n return\n }\n\n let actives\n let activesData\n\n if (this._parent) {\n actives = [].slice.call(this._parent.querySelectorAll(Selector.ACTIVES))\n .filter((elem) => elem.getAttribute('data-parent') === this._config.parent)\n\n if (actives.length === 0) {\n actives = null\n }\n }\n\n if (actives) {\n activesData = $(actives).not(this._selector).data(DATA_KEY)\n if (activesData && activesData._isTransitioning) {\n return\n }\n }\n\n const startEvent = $.Event(Event.SHOW)\n $(this._element).trigger(startEvent)\n if (startEvent.isDefaultPrevented()) {\n return\n }\n\n if (actives) {\n Collapse._jQueryInterface.call($(actives).not(this._selector), 'hide')\n if (!activesData) {\n $(actives).data(DATA_KEY, null)\n }\n }\n\n const dimension = this._getDimension()\n\n $(this._element)\n .removeClass(ClassName.COLLAPSE)\n .addClass(ClassName.COLLAPSING)\n\n this._element.style[dimension] = 0\n\n if (this._triggerArray.length) {\n $(this._triggerArray)\n .removeClass(ClassName.COLLAPSED)\n .attr('aria-expanded', true)\n }\n\n this.setTransitioning(true)\n\n const complete = () => {\n $(this._element)\n .removeClass(ClassName.COLLAPSING)\n .addClass(ClassName.COLLAPSE)\n .addClass(ClassName.SHOW)\n\n this._element.style[dimension] = ''\n\n this.setTransitioning(false)\n\n $(this._element).trigger(Event.SHOWN)\n }\n\n const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1)\n const scrollSize = `scroll${capitalizedDimension}`\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._element)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n\n this._element.style[dimension] = `${this._element[scrollSize]}px`\n }\n\n hide() {\n if (this._isTransitioning ||\n !$(this._element).hasClass(ClassName.SHOW)) {\n return\n }\n\n const startEvent = $.Event(Event.HIDE)\n $(this._element).trigger(startEvent)\n if (startEvent.isDefaultPrevented()) {\n return\n }\n\n const dimension = this._getDimension()\n\n this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`\n\n Util.reflow(this._element)\n\n $(this._element)\n .addClass(ClassName.COLLAPSING)\n .removeClass(ClassName.COLLAPSE)\n .removeClass(ClassName.SHOW)\n\n const triggerArrayLength = this._triggerArray.length\n if (triggerArrayLength > 0) {\n for (let i = 0; i < triggerArrayLength; i++) {\n const trigger = this._triggerArray[i]\n const selector = Util.getSelectorFromElement(trigger)\n if (selector !== null) {\n const $elem = $([].slice.call(document.querySelectorAll(selector)))\n if (!$elem.hasClass(ClassName.SHOW)) {\n $(trigger).addClass(ClassName.COLLAPSED)\n .attr('aria-expanded', false)\n }\n }\n }\n }\n\n this.setTransitioning(true)\n\n const complete = () => {\n this.setTransitioning(false)\n $(this._element)\n .removeClass(ClassName.COLLAPSING)\n .addClass(ClassName.COLLAPSE)\n .trigger(Event.HIDDEN)\n }\n\n this._element.style[dimension] = ''\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._element)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n }\n\n setTransitioning(isTransitioning) {\n this._isTransitioning = isTransitioning\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n\n this._config = null\n this._parent = null\n this._element = null\n this._triggerArray = null\n this._isTransitioning = null\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...config\n }\n config.toggle = Boolean(config.toggle) // Coerce string values\n Util.typeCheckConfig(NAME, config, DefaultType)\n return config\n }\n\n _getDimension() {\n const hasWidth = $(this._element).hasClass(Dimension.WIDTH)\n return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT\n }\n\n _getParent() {\n let parent = null\n if (Util.isElement(this._config.parent)) {\n parent = this._config.parent\n\n // It's a jQuery object\n if (typeof this._config.parent.jquery !== 'undefined') {\n parent = this._config.parent[0]\n }\n } else {\n parent = document.querySelector(this._config.parent)\n }\n\n const selector =\n `[data-toggle=\"collapse\"][data-parent=\"${this._config.parent}\"]`\n\n const children = [].slice.call(parent.querySelectorAll(selector))\n $(children).each((i, element) => {\n this._addAriaAndCollapsedClass(\n Collapse._getTargetFromElement(element),\n [element]\n )\n })\n\n return parent\n }\n\n _addAriaAndCollapsedClass(element, triggerArray) {\n if (element) {\n const isOpen = $(element).hasClass(ClassName.SHOW)\n\n if (triggerArray.length) {\n $(triggerArray)\n .toggleClass(ClassName.COLLAPSED, !isOpen)\n .attr('aria-expanded', isOpen)\n }\n }\n }\n\n // Static\n\n static _getTargetFromElement(element) {\n const selector = Util.getSelectorFromElement(element)\n return selector ? document.querySelector(selector) : null\n }\n\n static _jQueryInterface(config) {\n return this.each(function () {\n const $this = $(this)\n let data = $this.data(DATA_KEY)\n const _config = {\n ...Default,\n ...$this.data(),\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (!data && _config.toggle && /show|hide/.test(config)) {\n _config.toggle = false\n }\n\n if (!data) {\n data = new Collapse(this, _config)\n $this.data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config]()\n }\n })\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n // preventDefault only for
    elements (which change the URL) not inside the collapsible element\n if (event.currentTarget.tagName === 'A') {\n event.preventDefault()\n }\n\n const $trigger = $(this)\n const selector = Util.getSelectorFromElement(this)\n const selectors = [].slice.call(document.querySelectorAll(selector))\n $(selectors).each(function () {\n const $target = $(this)\n const data = $target.data(DATA_KEY)\n const config = data ? 'toggle' : $trigger.data()\n Collapse._jQueryInterface.call($target, config)\n })\n })\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Collapse._jQueryInterface\n $.fn[NAME].Constructor = Collapse\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Collapse._jQueryInterface\n }\n\n return Collapse\n})($)\n\nexport default Collapse\n","import $ from 'jquery'\nimport Popper from 'popper.js'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): dropdown.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Dropdown = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'dropdown'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.dropdown'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n const ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key\n const SPACE_KEYCODE = 32 // KeyboardEvent.which value for space key\n const TAB_KEYCODE = 9 // KeyboardEvent.which value for tab key\n const ARROW_UP_KEYCODE = 38 // KeyboardEvent.which value for up arrow key\n const ARROW_DOWN_KEYCODE = 40 // KeyboardEvent.which value for down arrow key\n const RIGHT_MOUSE_BUTTON_WHICH = 3 // MouseEvent.which value for the right button (assuming a right-handed mouse)\n const REGEXP_KEYDOWN = new RegExp(`${ARROW_UP_KEYCODE}|${ARROW_DOWN_KEYCODE}|${ESCAPE_KEYCODE}`)\n\n const Event = {\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n CLICK : `click${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`,\n KEYDOWN_DATA_API : `keydown${EVENT_KEY}${DATA_API_KEY}`,\n KEYUP_DATA_API : `keyup${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n DISABLED : 'disabled',\n SHOW : 'show',\n DROPUP : 'dropup',\n DROPRIGHT : 'dropright',\n DROPLEFT : 'dropleft',\n MENURIGHT : 'dropdown-menu-right',\n MENULEFT : 'dropdown-menu-left',\n POSITION_STATIC : 'position-static'\n }\n\n const Selector = {\n DATA_TOGGLE : '[data-toggle=\"dropdown\"]',\n FORM_CHILD : '.dropdown form',\n MENU : '.dropdown-menu',\n NAVBAR_NAV : '.navbar-nav',\n VISIBLE_ITEMS : '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'\n }\n\n const AttachmentMap = {\n TOP : 'top-start',\n TOPEND : 'top-end',\n BOTTOM : 'bottom-start',\n BOTTOMEND : 'bottom-end',\n RIGHT : 'right-start',\n RIGHTEND : 'right-end',\n LEFT : 'left-start',\n LEFTEND : 'left-end'\n }\n\n const Default = {\n offset : 0,\n flip : true,\n boundary : 'scrollParent',\n reference : 'toggle',\n display : 'dynamic'\n }\n\n const DefaultType = {\n offset : '(number|string|function)',\n flip : 'boolean',\n boundary : '(string|element)',\n reference : '(string|element)',\n display : 'string'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Dropdown {\n constructor(element, config) {\n this._element = element\n this._popper = null\n this._config = this._getConfig(config)\n this._menu = this._getMenuElement()\n this._inNavbar = this._detectNavbar()\n\n this._addEventListeners()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n // Public\n\n toggle() {\n if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED)) {\n return\n }\n\n const parent = Dropdown._getParentFromElement(this._element)\n const isActive = $(this._menu).hasClass(ClassName.SHOW)\n\n Dropdown._clearMenus()\n\n if (isActive) {\n return\n }\n\n const relatedTarget = {\n relatedTarget: this._element\n }\n const showEvent = $.Event(Event.SHOW, relatedTarget)\n\n $(parent).trigger(showEvent)\n\n if (showEvent.isDefaultPrevented()) {\n return\n }\n\n // Disable totally Popper.js for Dropdown in Navbar\n if (!this._inNavbar) {\n /**\n * Check for Popper dependency\n * Popper - https://popper.js.org\n */\n if (typeof Popper === 'undefined') {\n throw new TypeError('Bootstrap dropdown require Popper.js (https://popper.js.org)')\n }\n\n let referenceElement = this._element\n\n if (this._config.reference === 'parent') {\n referenceElement = parent\n } else if (Util.isElement(this._config.reference)) {\n referenceElement = this._config.reference\n\n // Check if it's jQuery element\n if (typeof this._config.reference.jquery !== 'undefined') {\n referenceElement = this._config.reference[0]\n }\n }\n\n // If boundary is not `scrollParent`, then set position to `static`\n // to allow the menu to \"escape\" the scroll parent's boundaries\n // https://github.com/twbs/bootstrap/issues/24251\n if (this._config.boundary !== 'scrollParent') {\n $(parent).addClass(ClassName.POSITION_STATIC)\n }\n this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig())\n }\n\n // If this is a touch-enabled device we add extra\n // empty mouseover listeners to the body's immediate children;\n // only needed because of broken event delegation on iOS\n // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n if ('ontouchstart' in document.documentElement &&\n $(parent).closest(Selector.NAVBAR_NAV).length === 0) {\n $(document.body).children().on('mouseover', null, $.noop)\n }\n\n this._element.focus()\n this._element.setAttribute('aria-expanded', true)\n\n $(this._menu).toggleClass(ClassName.SHOW)\n $(parent)\n .toggleClass(ClassName.SHOW)\n .trigger($.Event(Event.SHOWN, relatedTarget))\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n $(this._element).off(EVENT_KEY)\n this._element = null\n this._menu = null\n if (this._popper !== null) {\n this._popper.destroy()\n this._popper = null\n }\n }\n\n update() {\n this._inNavbar = this._detectNavbar()\n if (this._popper !== null) {\n this._popper.scheduleUpdate()\n }\n }\n\n // Private\n\n _addEventListeners() {\n $(this._element).on(Event.CLICK, (event) => {\n event.preventDefault()\n event.stopPropagation()\n this.toggle()\n })\n }\n\n _getConfig(config) {\n config = {\n ...this.constructor.Default,\n ...$(this._element).data(),\n ...config\n }\n\n Util.typeCheckConfig(\n NAME,\n config,\n this.constructor.DefaultType\n )\n\n return config\n }\n\n _getMenuElement() {\n if (!this._menu) {\n const parent = Dropdown._getParentFromElement(this._element)\n if (parent) {\n this._menu = parent.querySelector(Selector.MENU)\n }\n }\n return this._menu\n }\n\n _getPlacement() {\n const $parentDropdown = $(this._element.parentNode)\n let placement = AttachmentMap.BOTTOM\n\n // Handle dropup\n if ($parentDropdown.hasClass(ClassName.DROPUP)) {\n placement = AttachmentMap.TOP\n if ($(this._menu).hasClass(ClassName.MENURIGHT)) {\n placement = AttachmentMap.TOPEND\n }\n } else if ($parentDropdown.hasClass(ClassName.DROPRIGHT)) {\n placement = AttachmentMap.RIGHT\n } else if ($parentDropdown.hasClass(ClassName.DROPLEFT)) {\n placement = AttachmentMap.LEFT\n } else if ($(this._menu).hasClass(ClassName.MENURIGHT)) {\n placement = AttachmentMap.BOTTOMEND\n }\n return placement\n }\n\n _detectNavbar() {\n return $(this._element).closest('.navbar').length > 0\n }\n\n _getPopperConfig() {\n const offsetConf = {}\n if (typeof this._config.offset === 'function') {\n offsetConf.fn = (data) => {\n data.offsets = {\n ...data.offsets,\n ...this._config.offset(data.offsets) || {}\n }\n return data\n }\n } else {\n offsetConf.offset = this._config.offset\n }\n\n const popperConfig = {\n placement: this._getPlacement(),\n modifiers: {\n offset: offsetConf,\n flip: {\n enabled: this._config.flip\n },\n preventOverflow: {\n boundariesElement: this._config.boundary\n }\n }\n }\n\n // Disable Popper.js if we have a static display\n if (this._config.display === 'static') {\n popperConfig.modifiers.applyStyle = {\n enabled: false\n }\n }\n return popperConfig\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = typeof config === 'object' ? config : null\n\n if (!data) {\n data = new Dropdown(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config]()\n }\n })\n }\n\n static _clearMenus(event) {\n if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH ||\n event.type === 'keyup' && event.which !== TAB_KEYCODE)) {\n return\n }\n\n const toggles = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE))\n for (let i = 0, len = toggles.length; i < len; i++) {\n const parent = Dropdown._getParentFromElement(toggles[i])\n const context = $(toggles[i]).data(DATA_KEY)\n const relatedTarget = {\n relatedTarget: toggles[i]\n }\n\n if (event && event.type === 'click') {\n relatedTarget.clickEvent = event\n }\n\n if (!context) {\n continue\n }\n\n const dropdownMenu = context._menu\n if (!$(parent).hasClass(ClassName.SHOW)) {\n continue\n }\n\n if (event && (event.type === 'click' &&\n /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) &&\n $.contains(parent, event.target)) {\n continue\n }\n\n const hideEvent = $.Event(Event.HIDE, relatedTarget)\n $(parent).trigger(hideEvent)\n if (hideEvent.isDefaultPrevented()) {\n continue\n }\n\n // If this is a touch-enabled device we remove the extra\n // empty mouseover listeners we added for iOS support\n if ('ontouchstart' in document.documentElement) {\n $(document.body).children().off('mouseover', null, $.noop)\n }\n\n toggles[i].setAttribute('aria-expanded', 'false')\n\n $(dropdownMenu).removeClass(ClassName.SHOW)\n $(parent)\n .removeClass(ClassName.SHOW)\n .trigger($.Event(Event.HIDDEN, relatedTarget))\n }\n }\n\n static _getParentFromElement(element) {\n let parent\n const selector = Util.getSelectorFromElement(element)\n\n if (selector) {\n parent = document.querySelector(selector)\n }\n\n return parent || element.parentNode\n }\n\n // eslint-disable-next-line complexity\n static _dataApiKeydownHandler(event) {\n // If not input/textarea:\n // - And not a key in REGEXP_KEYDOWN => not a dropdown command\n // If input/textarea:\n // - If space key => not a dropdown command\n // - If key is other than escape\n // - If key is not up or down => not a dropdown command\n // - If trigger inside the menu => not a dropdown command\n if (/input|textarea/i.test(event.target.tagName)\n ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE &&\n (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE ||\n $(event.target).closest(Selector.MENU).length) : !REGEXP_KEYDOWN.test(event.which)) {\n return\n }\n\n event.preventDefault()\n event.stopPropagation()\n\n if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {\n return\n }\n\n const parent = Dropdown._getParentFromElement(this)\n const isActive = $(parent).hasClass(ClassName.SHOW)\n\n if (!isActive && (event.which !== ESCAPE_KEYCODE || event.which !== SPACE_KEYCODE) ||\n isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) {\n if (event.which === ESCAPE_KEYCODE) {\n const toggle = parent.querySelector(Selector.DATA_TOGGLE)\n $(toggle).trigger('focus')\n }\n\n $(this).trigger('click')\n return\n }\n\n const items = [].slice.call(parent.querySelectorAll(Selector.VISIBLE_ITEMS))\n\n if (items.length === 0) {\n return\n }\n\n let index = items.indexOf(event.target)\n\n if (event.which === ARROW_UP_KEYCODE && index > 0) { // Up\n index--\n }\n\n if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) { // Down\n index++\n }\n\n if (index < 0) {\n index = 0\n }\n\n items[index].focus()\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document)\n .on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler)\n .on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler)\n .on(`${Event.CLICK_DATA_API} ${Event.KEYUP_DATA_API}`, Dropdown._clearMenus)\n .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n event.preventDefault()\n event.stopPropagation()\n Dropdown._jQueryInterface.call($(this), 'toggle')\n })\n .on(Event.CLICK_DATA_API, Selector.FORM_CHILD, (e) => {\n e.stopPropagation()\n })\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Dropdown._jQueryInterface\n $.fn[NAME].Constructor = Dropdown\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Dropdown._jQueryInterface\n }\n\n return Dropdown\n})($, Popper)\n\nexport default Dropdown\n","import $ from 'jquery'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): modal.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Modal = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'modal'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.modal'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n const ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key\n\n const Default = {\n backdrop : true,\n keyboard : true,\n focus : true,\n show : true\n }\n\n const DefaultType = {\n backdrop : '(boolean|string)',\n keyboard : 'boolean',\n focus : 'boolean',\n show : 'boolean'\n }\n\n const Event = {\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n FOCUSIN : `focusin${EVENT_KEY}`,\n RESIZE : `resize${EVENT_KEY}`,\n CLICK_DISMISS : `click.dismiss${EVENT_KEY}`,\n KEYDOWN_DISMISS : `keydown.dismiss${EVENT_KEY}`,\n MOUSEUP_DISMISS : `mouseup.dismiss${EVENT_KEY}`,\n MOUSEDOWN_DISMISS : `mousedown.dismiss${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n SCROLLBAR_MEASURER : 'modal-scrollbar-measure',\n BACKDROP : 'modal-backdrop',\n OPEN : 'modal-open',\n FADE : 'fade',\n SHOW : 'show'\n }\n\n const Selector = {\n DIALOG : '.modal-dialog',\n DATA_TOGGLE : '[data-toggle=\"modal\"]',\n DATA_DISMISS : '[data-dismiss=\"modal\"]',\n FIXED_CONTENT : '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top',\n STICKY_CONTENT : '.sticky-top'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Modal {\n constructor(element, config) {\n this._config = this._getConfig(config)\n this._element = element\n this._dialog = element.querySelector(Selector.DIALOG)\n this._backdrop = null\n this._isShown = false\n this._isBodyOverflowing = false\n this._ignoreBackdropClick = false\n this._scrollbarWidth = 0\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n toggle(relatedTarget) {\n return this._isShown ? this.hide() : this.show(relatedTarget)\n }\n\n show(relatedTarget) {\n if (this._isTransitioning || this._isShown) {\n return\n }\n\n if ($(this._element).hasClass(ClassName.FADE)) {\n this._isTransitioning = true\n }\n\n const showEvent = $.Event(Event.SHOW, {\n relatedTarget\n })\n\n $(this._element).trigger(showEvent)\n\n if (this._isShown || showEvent.isDefaultPrevented()) {\n return\n }\n\n this._isShown = true\n\n this._checkScrollbar()\n this._setScrollbar()\n\n this._adjustDialog()\n\n $(document.body).addClass(ClassName.OPEN)\n\n this._setEscapeEvent()\n this._setResizeEvent()\n\n $(this._element).on(\n Event.CLICK_DISMISS,\n Selector.DATA_DISMISS,\n (event) => this.hide(event)\n )\n\n $(this._dialog).on(Event.MOUSEDOWN_DISMISS, () => {\n $(this._element).one(Event.MOUSEUP_DISMISS, (event) => {\n if ($(event.target).is(this._element)) {\n this._ignoreBackdropClick = true\n }\n })\n })\n\n this._showBackdrop(() => this._showElement(relatedTarget))\n }\n\n hide(event) {\n if (event) {\n event.preventDefault()\n }\n\n if (this._isTransitioning || !this._isShown) {\n return\n }\n\n const hideEvent = $.Event(Event.HIDE)\n\n $(this._element).trigger(hideEvent)\n\n if (!this._isShown || hideEvent.isDefaultPrevented()) {\n return\n }\n\n this._isShown = false\n const transition = $(this._element).hasClass(ClassName.FADE)\n\n if (transition) {\n this._isTransitioning = true\n }\n\n this._setEscapeEvent()\n this._setResizeEvent()\n\n $(document).off(Event.FOCUSIN)\n\n $(this._element).removeClass(ClassName.SHOW)\n\n $(this._element).off(Event.CLICK_DISMISS)\n $(this._dialog).off(Event.MOUSEDOWN_DISMISS)\n\n\n if (transition) {\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._element)\n .one(Util.TRANSITION_END, (event) => this._hideModal(event))\n .emulateTransitionEnd(transitionDuration)\n } else {\n this._hideModal()\n }\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n\n $(window, document, this._element, this._backdrop).off(EVENT_KEY)\n\n this._config = null\n this._element = null\n this._dialog = null\n this._backdrop = null\n this._isShown = null\n this._isBodyOverflowing = null\n this._ignoreBackdropClick = null\n this._scrollbarWidth = null\n }\n\n handleUpdate() {\n this._adjustDialog()\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...config\n }\n Util.typeCheckConfig(NAME, config, DefaultType)\n return config\n }\n\n _showElement(relatedTarget) {\n const transition = $(this._element).hasClass(ClassName.FADE)\n\n if (!this._element.parentNode ||\n this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {\n // Don't move modal's DOM position\n document.body.appendChild(this._element)\n }\n\n this._element.style.display = 'block'\n this._element.removeAttribute('aria-hidden')\n this._element.scrollTop = 0\n\n if (transition) {\n Util.reflow(this._element)\n }\n\n $(this._element).addClass(ClassName.SHOW)\n\n if (this._config.focus) {\n this._enforceFocus()\n }\n\n const shownEvent = $.Event(Event.SHOWN, {\n relatedTarget\n })\n\n const transitionComplete = () => {\n if (this._config.focus) {\n this._element.focus()\n }\n this._isTransitioning = false\n $(this._element).trigger(shownEvent)\n }\n\n if (transition) {\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._dialog)\n .one(Util.TRANSITION_END, transitionComplete)\n .emulateTransitionEnd(transitionDuration)\n } else {\n transitionComplete()\n }\n }\n\n _enforceFocus() {\n $(document)\n .off(Event.FOCUSIN) // Guard against infinite focus loop\n .on(Event.FOCUSIN, (event) => {\n if (document !== event.target &&\n this._element !== event.target &&\n $(this._element).has(event.target).length === 0) {\n this._element.focus()\n }\n })\n }\n\n _setEscapeEvent() {\n if (this._isShown && this._config.keyboard) {\n $(this._element).on(Event.KEYDOWN_DISMISS, (event) => {\n if (event.which === ESCAPE_KEYCODE) {\n event.preventDefault()\n this.hide()\n }\n })\n } else if (!this._isShown) {\n $(this._element).off(Event.KEYDOWN_DISMISS)\n }\n }\n\n _setResizeEvent() {\n if (this._isShown) {\n $(window).on(Event.RESIZE, (event) => this.handleUpdate(event))\n } else {\n $(window).off(Event.RESIZE)\n }\n }\n\n _hideModal() {\n this._element.style.display = 'none'\n this._element.setAttribute('aria-hidden', true)\n this._isTransitioning = false\n this._showBackdrop(() => {\n $(document.body).removeClass(ClassName.OPEN)\n this._resetAdjustments()\n this._resetScrollbar()\n $(this._element).trigger(Event.HIDDEN)\n })\n }\n\n _removeBackdrop() {\n if (this._backdrop) {\n $(this._backdrop).remove()\n this._backdrop = null\n }\n }\n\n _showBackdrop(callback) {\n const animate = $(this._element).hasClass(ClassName.FADE)\n ? ClassName.FADE : ''\n\n if (this._isShown && this._config.backdrop) {\n this._backdrop = document.createElement('div')\n this._backdrop.className = ClassName.BACKDROP\n\n if (animate) {\n this._backdrop.classList.add(animate)\n }\n\n $(this._backdrop).appendTo(document.body)\n\n $(this._element).on(Event.CLICK_DISMISS, (event) => {\n if (this._ignoreBackdropClick) {\n this._ignoreBackdropClick = false\n return\n }\n if (event.target !== event.currentTarget) {\n return\n }\n if (this._config.backdrop === 'static') {\n this._element.focus()\n } else {\n this.hide()\n }\n })\n\n if (animate) {\n Util.reflow(this._backdrop)\n }\n\n $(this._backdrop).addClass(ClassName.SHOW)\n\n if (!callback) {\n return\n }\n\n if (!animate) {\n callback()\n return\n }\n\n const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop)\n\n $(this._backdrop)\n .one(Util.TRANSITION_END, callback)\n .emulateTransitionEnd(backdropTransitionDuration)\n } else if (!this._isShown && this._backdrop) {\n $(this._backdrop).removeClass(ClassName.SHOW)\n\n const callbackRemove = () => {\n this._removeBackdrop()\n if (callback) {\n callback()\n }\n }\n\n if ($(this._element).hasClass(ClassName.FADE)) {\n const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop)\n\n $(this._backdrop)\n .one(Util.TRANSITION_END, callbackRemove)\n .emulateTransitionEnd(backdropTransitionDuration)\n } else {\n callbackRemove()\n }\n } else if (callback) {\n callback()\n }\n }\n\n // ----------------------------------------------------------------------\n // the following methods are used to handle overflowing modals\n // todo (fat): these should probably be refactored out of modal.js\n // ----------------------------------------------------------------------\n\n _adjustDialog() {\n const isModalOverflowing =\n this._element.scrollHeight > document.documentElement.clientHeight\n\n if (!this._isBodyOverflowing && isModalOverflowing) {\n this._element.style.paddingLeft = `${this._scrollbarWidth}px`\n }\n\n if (this._isBodyOverflowing && !isModalOverflowing) {\n this._element.style.paddingRight = `${this._scrollbarWidth}px`\n }\n }\n\n _resetAdjustments() {\n this._element.style.paddingLeft = ''\n this._element.style.paddingRight = ''\n }\n\n _checkScrollbar() {\n const rect = document.body.getBoundingClientRect()\n this._isBodyOverflowing = rect.left + rect.right < window.innerWidth\n this._scrollbarWidth = this._getScrollbarWidth()\n }\n\n _setScrollbar() {\n if (this._isBodyOverflowing) {\n // Note: DOMNode.style.paddingRight returns the actual value or '' if not set\n // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set\n const fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT))\n const stickyContent = [].slice.call(document.querySelectorAll(Selector.STICKY_CONTENT))\n\n // Adjust fixed content padding\n $(fixedContent).each((index, element) => {\n const actualPadding = element.style.paddingRight\n const calculatedPadding = $(element).css('padding-right')\n $(element)\n .data('padding-right', actualPadding)\n .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`)\n })\n\n // Adjust sticky content margin\n $(stickyContent).each((index, element) => {\n const actualMargin = element.style.marginRight\n const calculatedMargin = $(element).css('margin-right')\n $(element)\n .data('margin-right', actualMargin)\n .css('margin-right', `${parseFloat(calculatedMargin) - this._scrollbarWidth}px`)\n })\n\n // Adjust body padding\n const actualPadding = document.body.style.paddingRight\n const calculatedPadding = $(document.body).css('padding-right')\n $(document.body)\n .data('padding-right', actualPadding)\n .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`)\n }\n }\n\n _resetScrollbar() {\n // Restore fixed content padding\n const fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT))\n $(fixedContent).each((index, element) => {\n const padding = $(element).data('padding-right')\n $(element).removeData('padding-right')\n element.style.paddingRight = padding ? padding : ''\n })\n\n // Restore sticky content\n const elements = [].slice.call(document.querySelectorAll(`${Selector.STICKY_CONTENT}`))\n $(elements).each((index, element) => {\n const margin = $(element).data('margin-right')\n if (typeof margin !== 'undefined') {\n $(element).css('margin-right', margin).removeData('margin-right')\n }\n })\n\n // Restore body padding\n const padding = $(document.body).data('padding-right')\n $(document.body).removeData('padding-right')\n document.body.style.paddingRight = padding ? padding : ''\n }\n\n _getScrollbarWidth() { // thx d.walsh\n const scrollDiv = document.createElement('div')\n scrollDiv.className = ClassName.SCROLLBAR_MEASURER\n document.body.appendChild(scrollDiv)\n const scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth\n document.body.removeChild(scrollDiv)\n return scrollbarWidth\n }\n\n // Static\n\n static _jQueryInterface(config, relatedTarget) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = {\n ...Default,\n ...$(this).data(),\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (!data) {\n data = new Modal(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config](relatedTarget)\n } else if (_config.show) {\n data.show(relatedTarget)\n }\n })\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n let target\n const selector = Util.getSelectorFromElement(this)\n\n if (selector) {\n target = document.querySelector(selector)\n }\n\n const config = $(target).data(DATA_KEY)\n ? 'toggle' : {\n ...$(target).data(),\n ...$(this).data()\n }\n\n if (this.tagName === 'A' || this.tagName === 'AREA') {\n event.preventDefault()\n }\n\n const $target = $(target).one(Event.SHOW, (showEvent) => {\n if (showEvent.isDefaultPrevented()) {\n // Only register focus restorer if modal will actually get shown\n return\n }\n\n $target.one(Event.HIDDEN, () => {\n if ($(this).is(':visible')) {\n this.focus()\n }\n })\n })\n\n Modal._jQueryInterface.call($(target), config, this)\n })\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Modal._jQueryInterface\n $.fn[NAME].Constructor = Modal\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Modal._jQueryInterface\n }\n\n return Modal\n})($)\n\nexport default Modal\n","import $ from 'jquery'\nimport Popper from 'popper.js'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): tooltip.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Tooltip = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'tooltip'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.tooltip'\n const EVENT_KEY = `.${DATA_KEY}`\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n const CLASS_PREFIX = 'bs-tooltip'\n const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\\\s)${CLASS_PREFIX}\\\\S+`, 'g')\n\n const DefaultType = {\n animation : 'boolean',\n template : 'string',\n title : '(string|element|function)',\n trigger : 'string',\n delay : '(number|object)',\n html : 'boolean',\n selector : '(string|boolean)',\n placement : '(string|function)',\n offset : '(number|string)',\n container : '(string|element|boolean)',\n fallbackPlacement : '(string|array)',\n boundary : '(string|element)'\n }\n\n const AttachmentMap = {\n AUTO : 'auto',\n TOP : 'top',\n RIGHT : 'right',\n BOTTOM : 'bottom',\n LEFT : 'left'\n }\n\n const Default = {\n animation : true,\n template : '
    ' +\n '
    ' +\n '
    ',\n trigger : 'hover focus',\n title : '',\n delay : 0,\n html : false,\n selector : false,\n placement : 'top',\n offset : 0,\n container : false,\n fallbackPlacement : 'flip',\n boundary : 'scrollParent'\n }\n\n const HoverState = {\n SHOW : 'show',\n OUT : 'out'\n }\n\n const Event = {\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n INSERTED : `inserted${EVENT_KEY}`,\n CLICK : `click${EVENT_KEY}`,\n FOCUSIN : `focusin${EVENT_KEY}`,\n FOCUSOUT : `focusout${EVENT_KEY}`,\n MOUSEENTER : `mouseenter${EVENT_KEY}`,\n MOUSELEAVE : `mouseleave${EVENT_KEY}`\n }\n\n const ClassName = {\n FADE : 'fade',\n SHOW : 'show'\n }\n\n const Selector = {\n TOOLTIP : '.tooltip',\n TOOLTIP_INNER : '.tooltip-inner',\n ARROW : '.arrow'\n }\n\n const Trigger = {\n HOVER : 'hover',\n FOCUS : 'focus',\n CLICK : 'click',\n MANUAL : 'manual'\n }\n\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Tooltip {\n constructor(element, config) {\n /**\n * Check for Popper dependency\n * Popper - https://popper.js.org\n */\n if (typeof Popper === 'undefined') {\n throw new TypeError('Bootstrap tooltips require Popper.js (https://popper.js.org)')\n }\n\n // private\n this._isEnabled = true\n this._timeout = 0\n this._hoverState = ''\n this._activeTrigger = {}\n this._popper = null\n\n // Protected\n this.element = element\n this.config = this._getConfig(config)\n this.tip = null\n\n this._setListeners()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n static get NAME() {\n return NAME\n }\n\n static get DATA_KEY() {\n return DATA_KEY\n }\n\n static get Event() {\n return Event\n }\n\n static get EVENT_KEY() {\n return EVENT_KEY\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n // Public\n\n enable() {\n this._isEnabled = true\n }\n\n disable() {\n this._isEnabled = false\n }\n\n toggleEnabled() {\n this._isEnabled = !this._isEnabled\n }\n\n toggle(event) {\n if (!this._isEnabled) {\n return\n }\n\n if (event) {\n const dataKey = this.constructor.DATA_KEY\n let context = $(event.currentTarget).data(dataKey)\n\n if (!context) {\n context = new this.constructor(\n event.currentTarget,\n this._getDelegateConfig()\n )\n $(event.currentTarget).data(dataKey, context)\n }\n\n context._activeTrigger.click = !context._activeTrigger.click\n\n if (context._isWithActiveTrigger()) {\n context._enter(null, context)\n } else {\n context._leave(null, context)\n }\n } else {\n if ($(this.getTipElement()).hasClass(ClassName.SHOW)) {\n this._leave(null, this)\n return\n }\n\n this._enter(null, this)\n }\n }\n\n dispose() {\n clearTimeout(this._timeout)\n\n $.removeData(this.element, this.constructor.DATA_KEY)\n\n $(this.element).off(this.constructor.EVENT_KEY)\n $(this.element).closest('.modal').off('hide.bs.modal')\n\n if (this.tip) {\n $(this.tip).remove()\n }\n\n this._isEnabled = null\n this._timeout = null\n this._hoverState = null\n this._activeTrigger = null\n if (this._popper !== null) {\n this._popper.destroy()\n }\n\n this._popper = null\n this.element = null\n this.config = null\n this.tip = null\n }\n\n show() {\n if ($(this.element).css('display') === 'none') {\n throw new Error('Please use show on visible elements')\n }\n\n const showEvent = $.Event(this.constructor.Event.SHOW)\n if (this.isWithContent() && this._isEnabled) {\n $(this.element).trigger(showEvent)\n\n const isInTheDom = $.contains(\n this.element.ownerDocument.documentElement,\n this.element\n )\n\n if (showEvent.isDefaultPrevented() || !isInTheDom) {\n return\n }\n\n const tip = this.getTipElement()\n const tipId = Util.getUID(this.constructor.NAME)\n\n tip.setAttribute('id', tipId)\n this.element.setAttribute('aria-describedby', tipId)\n\n this.setContent()\n\n if (this.config.animation) {\n $(tip).addClass(ClassName.FADE)\n }\n\n const placement = typeof this.config.placement === 'function'\n ? this.config.placement.call(this, tip, this.element)\n : this.config.placement\n\n const attachment = this._getAttachment(placement)\n this.addAttachmentClass(attachment)\n\n const container = this.config.container === false ? document.body : $(document).find(this.config.container)\n\n $(tip).data(this.constructor.DATA_KEY, this)\n\n if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) {\n $(tip).appendTo(container)\n }\n\n $(this.element).trigger(this.constructor.Event.INSERTED)\n\n this._popper = new Popper(this.element, tip, {\n placement: attachment,\n modifiers: {\n offset: {\n offset: this.config.offset\n },\n flip: {\n behavior: this.config.fallbackPlacement\n },\n arrow: {\n element: Selector.ARROW\n },\n preventOverflow: {\n boundariesElement: this.config.boundary\n }\n },\n onCreate: (data) => {\n if (data.originalPlacement !== data.placement) {\n this._handlePopperPlacementChange(data)\n }\n },\n onUpdate: (data) => {\n this._handlePopperPlacementChange(data)\n }\n })\n\n $(tip).addClass(ClassName.SHOW)\n\n // If this is a touch-enabled device we add extra\n // empty mouseover listeners to the body's immediate children;\n // only needed because of broken event delegation on iOS\n // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n if ('ontouchstart' in document.documentElement) {\n $(document.body).children().on('mouseover', null, $.noop)\n }\n\n const complete = () => {\n if (this.config.animation) {\n this._fixTransition()\n }\n const prevHoverState = this._hoverState\n this._hoverState = null\n\n $(this.element).trigger(this.constructor.Event.SHOWN)\n\n if (prevHoverState === HoverState.OUT) {\n this._leave(null, this)\n }\n }\n\n if ($(this.tip).hasClass(ClassName.FADE)) {\n const transitionDuration = Util.getTransitionDurationFromElement(this.tip)\n\n $(this.tip)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n } else {\n complete()\n }\n }\n }\n\n hide(callback) {\n const tip = this.getTipElement()\n const hideEvent = $.Event(this.constructor.Event.HIDE)\n const complete = () => {\n if (this._hoverState !== HoverState.SHOW && tip.parentNode) {\n tip.parentNode.removeChild(tip)\n }\n\n this._cleanTipClass()\n this.element.removeAttribute('aria-describedby')\n $(this.element).trigger(this.constructor.Event.HIDDEN)\n if (this._popper !== null) {\n this._popper.destroy()\n }\n\n if (callback) {\n callback()\n }\n }\n\n $(this.element).trigger(hideEvent)\n\n if (hideEvent.isDefaultPrevented()) {\n return\n }\n\n $(tip).removeClass(ClassName.SHOW)\n\n // If this is a touch-enabled device we remove the extra\n // empty mouseover listeners we added for iOS support\n if ('ontouchstart' in document.documentElement) {\n $(document.body).children().off('mouseover', null, $.noop)\n }\n\n this._activeTrigger[Trigger.CLICK] = false\n this._activeTrigger[Trigger.FOCUS] = false\n this._activeTrigger[Trigger.HOVER] = false\n\n if ($(this.tip).hasClass(ClassName.FADE)) {\n const transitionDuration = Util.getTransitionDurationFromElement(tip)\n\n $(tip)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n } else {\n complete()\n }\n\n this._hoverState = ''\n }\n\n update() {\n if (this._popper !== null) {\n this._popper.scheduleUpdate()\n }\n }\n\n // Protected\n\n isWithContent() {\n return Boolean(this.getTitle())\n }\n\n addAttachmentClass(attachment) {\n $(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`)\n }\n\n getTipElement() {\n this.tip = this.tip || $(this.config.template)[0]\n return this.tip\n }\n\n setContent() {\n const tip = this.getTipElement()\n this.setElementContent($(tip.querySelectorAll(Selector.TOOLTIP_INNER)), this.getTitle())\n $(tip).removeClass(`${ClassName.FADE} ${ClassName.SHOW}`)\n }\n\n setElementContent($element, content) {\n const html = this.config.html\n if (typeof content === 'object' && (content.nodeType || content.jquery)) {\n // Content is a DOM node or a jQuery\n if (html) {\n if (!$(content).parent().is($element)) {\n $element.empty().append(content)\n }\n } else {\n $element.text($(content).text())\n }\n } else {\n $element[html ? 'html' : 'text'](content)\n }\n }\n\n getTitle() {\n let title = this.element.getAttribute('data-original-title')\n\n if (!title) {\n title = typeof this.config.title === 'function'\n ? this.config.title.call(this.element)\n : this.config.title\n }\n\n return title\n }\n\n // Private\n\n _getAttachment(placement) {\n return AttachmentMap[placement.toUpperCase()]\n }\n\n _setListeners() {\n const triggers = this.config.trigger.split(' ')\n\n triggers.forEach((trigger) => {\n if (trigger === 'click') {\n $(this.element).on(\n this.constructor.Event.CLICK,\n this.config.selector,\n (event) => this.toggle(event)\n )\n } else if (trigger !== Trigger.MANUAL) {\n const eventIn = trigger === Trigger.HOVER\n ? this.constructor.Event.MOUSEENTER\n : this.constructor.Event.FOCUSIN\n const eventOut = trigger === Trigger.HOVER\n ? this.constructor.Event.MOUSELEAVE\n : this.constructor.Event.FOCUSOUT\n\n $(this.element)\n .on(\n eventIn,\n this.config.selector,\n (event) => this._enter(event)\n )\n .on(\n eventOut,\n this.config.selector,\n (event) => this._leave(event)\n )\n }\n\n $(this.element).closest('.modal').on(\n 'hide.bs.modal',\n () => this.hide()\n )\n })\n\n if (this.config.selector) {\n this.config = {\n ...this.config,\n trigger: 'manual',\n selector: ''\n }\n } else {\n this._fixTitle()\n }\n }\n\n _fixTitle() {\n const titleType = typeof this.element.getAttribute('data-original-title')\n if (this.element.getAttribute('title') ||\n titleType !== 'string') {\n this.element.setAttribute(\n 'data-original-title',\n this.element.getAttribute('title') || ''\n )\n this.element.setAttribute('title', '')\n }\n }\n\n _enter(event, context) {\n const dataKey = this.constructor.DATA_KEY\n\n context = context || $(event.currentTarget).data(dataKey)\n\n if (!context) {\n context = new this.constructor(\n event.currentTarget,\n this._getDelegateConfig()\n )\n $(event.currentTarget).data(dataKey, context)\n }\n\n if (event) {\n context._activeTrigger[\n event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER\n ] = true\n }\n\n if ($(context.getTipElement()).hasClass(ClassName.SHOW) ||\n context._hoverState === HoverState.SHOW) {\n context._hoverState = HoverState.SHOW\n return\n }\n\n clearTimeout(context._timeout)\n\n context._hoverState = HoverState.SHOW\n\n if (!context.config.delay || !context.config.delay.show) {\n context.show()\n return\n }\n\n context._timeout = setTimeout(() => {\n if (context._hoverState === HoverState.SHOW) {\n context.show()\n }\n }, context.config.delay.show)\n }\n\n _leave(event, context) {\n const dataKey = this.constructor.DATA_KEY\n\n context = context || $(event.currentTarget).data(dataKey)\n\n if (!context) {\n context = new this.constructor(\n event.currentTarget,\n this._getDelegateConfig()\n )\n $(event.currentTarget).data(dataKey, context)\n }\n\n if (event) {\n context._activeTrigger[\n event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER\n ] = false\n }\n\n if (context._isWithActiveTrigger()) {\n return\n }\n\n clearTimeout(context._timeout)\n\n context._hoverState = HoverState.OUT\n\n if (!context.config.delay || !context.config.delay.hide) {\n context.hide()\n return\n }\n\n context._timeout = setTimeout(() => {\n if (context._hoverState === HoverState.OUT) {\n context.hide()\n }\n }, context.config.delay.hide)\n }\n\n _isWithActiveTrigger() {\n for (const trigger in this._activeTrigger) {\n if (this._activeTrigger[trigger]) {\n return true\n }\n }\n\n return false\n }\n\n _getConfig(config) {\n config = {\n ...this.constructor.Default,\n ...$(this.element).data(),\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (typeof config.delay === 'number') {\n config.delay = {\n show: config.delay,\n hide: config.delay\n }\n }\n\n if (typeof config.title === 'number') {\n config.title = config.title.toString()\n }\n\n if (typeof config.content === 'number') {\n config.content = config.content.toString()\n }\n\n Util.typeCheckConfig(\n NAME,\n config,\n this.constructor.DefaultType\n )\n\n return config\n }\n\n _getDelegateConfig() {\n const config = {}\n\n if (this.config) {\n for (const key in this.config) {\n if (this.constructor.Default[key] !== this.config[key]) {\n config[key] = this.config[key]\n }\n }\n }\n\n return config\n }\n\n _cleanTipClass() {\n const $tip = $(this.getTipElement())\n const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX)\n if (tabClass !== null && tabClass.length) {\n $tip.removeClass(tabClass.join(''))\n }\n }\n\n _handlePopperPlacementChange(popperData) {\n const popperInstance = popperData.instance\n this.tip = popperInstance.popper\n this._cleanTipClass()\n this.addAttachmentClass(this._getAttachment(popperData.placement))\n }\n\n _fixTransition() {\n const tip = this.getTipElement()\n const initConfigAnimation = this.config.animation\n if (tip.getAttribute('x-placement') !== null) {\n return\n }\n $(tip).removeClass(ClassName.FADE)\n this.config.animation = false\n this.hide()\n this.show()\n this.config.animation = initConfigAnimation\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = typeof config === 'object' && config\n\n if (!data && /dispose|hide/.test(config)) {\n return\n }\n\n if (!data) {\n data = new Tooltip(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config]()\n }\n })\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Tooltip._jQueryInterface\n $.fn[NAME].Constructor = Tooltip\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Tooltip._jQueryInterface\n }\n\n return Tooltip\n})($, Popper)\n\nexport default Tooltip\n","import $ from 'jquery'\nimport Tooltip from './tooltip'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): popover.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Popover = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'popover'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.popover'\n const EVENT_KEY = `.${DATA_KEY}`\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n const CLASS_PREFIX = 'bs-popover'\n const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\\\s)${CLASS_PREFIX}\\\\S+`, 'g')\n\n const Default = {\n ...Tooltip.Default,\n placement : 'right',\n trigger : 'click',\n content : '',\n template : '
    ' +\n '
    ' +\n '

    ' +\n '
    '\n }\n\n const DefaultType = {\n ...Tooltip.DefaultType,\n content : '(string|element|function)'\n }\n\n const ClassName = {\n FADE : 'fade',\n SHOW : 'show'\n }\n\n const Selector = {\n TITLE : '.popover-header',\n CONTENT : '.popover-body'\n }\n\n const Event = {\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n INSERTED : `inserted${EVENT_KEY}`,\n CLICK : `click${EVENT_KEY}`,\n FOCUSIN : `focusin${EVENT_KEY}`,\n FOCUSOUT : `focusout${EVENT_KEY}`,\n MOUSEENTER : `mouseenter${EVENT_KEY}`,\n MOUSELEAVE : `mouseleave${EVENT_KEY}`\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Popover extends Tooltip {\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n static get NAME() {\n return NAME\n }\n\n static get DATA_KEY() {\n return DATA_KEY\n }\n\n static get Event() {\n return Event\n }\n\n static get EVENT_KEY() {\n return EVENT_KEY\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n // Overrides\n\n isWithContent() {\n return this.getTitle() || this._getContent()\n }\n\n addAttachmentClass(attachment) {\n $(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`)\n }\n\n getTipElement() {\n this.tip = this.tip || $(this.config.template)[0]\n return this.tip\n }\n\n setContent() {\n const $tip = $(this.getTipElement())\n\n // We use append for html objects to maintain js events\n this.setElementContent($tip.find(Selector.TITLE), this.getTitle())\n let content = this._getContent()\n if (typeof content === 'function') {\n content = content.call(this.element)\n }\n this.setElementContent($tip.find(Selector.CONTENT), content)\n\n $tip.removeClass(`${ClassName.FADE} ${ClassName.SHOW}`)\n }\n\n // Private\n\n _getContent() {\n return this.element.getAttribute('data-content') ||\n this.config.content\n }\n\n _cleanTipClass() {\n const $tip = $(this.getTipElement())\n const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX)\n if (tabClass !== null && tabClass.length > 0) {\n $tip.removeClass(tabClass.join(''))\n }\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = typeof config === 'object' ? config : null\n\n if (!data && /destroy|hide/.test(config)) {\n return\n }\n\n if (!data) {\n data = new Popover(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config]()\n }\n })\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Popover._jQueryInterface\n $.fn[NAME].Constructor = Popover\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Popover._jQueryInterface\n }\n\n return Popover\n})($)\n\nexport default Popover\n","import $ from 'jquery'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): scrollspy.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst ScrollSpy = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'scrollspy'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.scrollspy'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n\n const Default = {\n offset : 10,\n method : 'auto',\n target : ''\n }\n\n const DefaultType = {\n offset : 'number',\n method : 'string',\n target : '(string|element)'\n }\n\n const Event = {\n ACTIVATE : `activate${EVENT_KEY}`,\n SCROLL : `scroll${EVENT_KEY}`,\n LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n DROPDOWN_ITEM : 'dropdown-item',\n DROPDOWN_MENU : 'dropdown-menu',\n ACTIVE : 'active'\n }\n\n const Selector = {\n DATA_SPY : '[data-spy=\"scroll\"]',\n ACTIVE : '.active',\n NAV_LIST_GROUP : '.nav, .list-group',\n NAV_LINKS : '.nav-link',\n NAV_ITEMS : '.nav-item',\n LIST_ITEMS : '.list-group-item',\n DROPDOWN : '.dropdown',\n DROPDOWN_ITEMS : '.dropdown-item',\n DROPDOWN_TOGGLE : '.dropdown-toggle'\n }\n\n const OffsetMethod = {\n OFFSET : 'offset',\n POSITION : 'position'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class ScrollSpy {\n constructor(element, config) {\n this._element = element\n this._scrollElement = element.tagName === 'BODY' ? window : element\n this._config = this._getConfig(config)\n this._selector = `${this._config.target} ${Selector.NAV_LINKS},` +\n `${this._config.target} ${Selector.LIST_ITEMS},` +\n `${this._config.target} ${Selector.DROPDOWN_ITEMS}`\n this._offsets = []\n this._targets = []\n this._activeTarget = null\n this._scrollHeight = 0\n\n $(this._scrollElement).on(Event.SCROLL, (event) => this._process(event))\n\n this.refresh()\n this._process()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n refresh() {\n const autoMethod = this._scrollElement === this._scrollElement.window\n ? OffsetMethod.OFFSET : OffsetMethod.POSITION\n\n const offsetMethod = this._config.method === 'auto'\n ? autoMethod : this._config.method\n\n const offsetBase = offsetMethod === OffsetMethod.POSITION\n ? this._getScrollTop() : 0\n\n this._offsets = []\n this._targets = []\n\n this._scrollHeight = this._getScrollHeight()\n\n const targets = [].slice.call(document.querySelectorAll(this._selector))\n\n targets\n .map((element) => {\n let target\n const targetSelector = Util.getSelectorFromElement(element)\n\n if (targetSelector) {\n target = document.querySelector(targetSelector)\n }\n\n if (target) {\n const targetBCR = target.getBoundingClientRect()\n if (targetBCR.width || targetBCR.height) {\n // TODO (fat): remove sketch reliance on jQuery position/offset\n return [\n $(target)[offsetMethod]().top + offsetBase,\n targetSelector\n ]\n }\n }\n return null\n })\n .filter((item) => item)\n .sort((a, b) => a[0] - b[0])\n .forEach((item) => {\n this._offsets.push(item[0])\n this._targets.push(item[1])\n })\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n $(this._scrollElement).off(EVENT_KEY)\n\n this._element = null\n this._scrollElement = null\n this._config = null\n this._selector = null\n this._offsets = null\n this._targets = null\n this._activeTarget = null\n this._scrollHeight = null\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (typeof config.target !== 'string') {\n let id = $(config.target).attr('id')\n if (!id) {\n id = Util.getUID(NAME)\n $(config.target).attr('id', id)\n }\n config.target = `#${id}`\n }\n\n Util.typeCheckConfig(NAME, config, DefaultType)\n\n return config\n }\n\n _getScrollTop() {\n return this._scrollElement === window\n ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop\n }\n\n _getScrollHeight() {\n return this._scrollElement.scrollHeight || Math.max(\n document.body.scrollHeight,\n document.documentElement.scrollHeight\n )\n }\n\n _getOffsetHeight() {\n return this._scrollElement === window\n ? window.innerHeight : this._scrollElement.getBoundingClientRect().height\n }\n\n _process() {\n const scrollTop = this._getScrollTop() + this._config.offset\n const scrollHeight = this._getScrollHeight()\n const maxScroll = this._config.offset +\n scrollHeight -\n this._getOffsetHeight()\n\n if (this._scrollHeight !== scrollHeight) {\n this.refresh()\n }\n\n if (scrollTop >= maxScroll) {\n const target = this._targets[this._targets.length - 1]\n\n if (this._activeTarget !== target) {\n this._activate(target)\n }\n return\n }\n\n if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {\n this._activeTarget = null\n this._clear()\n return\n }\n\n const offsetLength = this._offsets.length\n for (let i = offsetLength; i--;) {\n const isActiveTarget = this._activeTarget !== this._targets[i] &&\n scrollTop >= this._offsets[i] &&\n (typeof this._offsets[i + 1] === 'undefined' ||\n scrollTop < this._offsets[i + 1])\n\n if (isActiveTarget) {\n this._activate(this._targets[i])\n }\n }\n }\n\n _activate(target) {\n this._activeTarget = target\n\n this._clear()\n\n let queries = this._selector.split(',')\n // eslint-disable-next-line arrow-body-style\n queries = queries.map((selector) => {\n return `${selector}[data-target=\"${target}\"],` +\n `${selector}[href=\"${target}\"]`\n })\n\n const $link = $([].slice.call(document.querySelectorAll(queries.join(','))))\n\n if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {\n $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE)\n $link.addClass(ClassName.ACTIVE)\n } else {\n // Set triggered link as active\n $link.addClass(ClassName.ACTIVE)\n // Set triggered links parents as active\n // With both
    ',trigger:"hover focus",title:"",delay:0,html:!(Ie={AUTO:"auto",TOP:"top",RIGHT:"right",BOTTOM:"bottom",LEFT:"left"}),selector:!(Se={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)"}),placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent"},we="out",Ne={HIDE:"hide"+Ee,HIDDEN:"hidden"+Ee,SHOW:(De="show")+Ee,SHOWN:"shown"+Ee,INSERTED:"inserted"+Ee,CLICK:"click"+Ee,FOCUSIN:"focusin"+Ee,FOCUSOUT:"focusout"+Ee,MOUSEENTER:"mouseenter"+Ee,MOUSELEAVE:"mouseleave"+Ee},Oe="fade",ke="show",Pe=".tooltip-inner",je=".arrow",He="hover",Le="focus",Re="click",xe="manual",We=function(){function i(t,e){if("undefined"==typeof h)throw new TypeError("Bootstrap tooltips require Popper.js (https://popper.js.org)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var t=i.prototype;return t.enable=function(){this._isEnabled=!0},t.disable=function(){this._isEnabled=!1},t.toggleEnabled=function(){this._isEnabled=!this._isEnabled},t.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=pe(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),pe(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(pe(this.getTipElement()).hasClass(ke))return void this._leave(null,this);this._enter(null,this)}},t.dispose=function(){clearTimeout(this._timeout),pe.removeData(this.element,this.constructor.DATA_KEY),pe(this.element).off(this.constructor.EVENT_KEY),pe(this.element).closest(".modal").off("hide.bs.modal"),this.tip&&pe(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,(this._activeTrigger=null)!==this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},t.show=function(){var e=this;if("none"===pe(this.element).css("display"))throw new Error("Please use show on visible elements");var t=pe.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){pe(this.element).trigger(t);var n=pe.contains(this.element.ownerDocument.documentElement,this.element);if(t.isDefaultPrevented()||!n)return;var i=this.getTipElement(),r=Fn.getUID(this.constructor.NAME);i.setAttribute("id",r),this.element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&pe(i).addClass(Oe);var o="function"==typeof this.config.placement?this.config.placement.call(this,i,this.element):this.config.placement,s=this._getAttachment(o);this.addAttachmentClass(s);var a=!1===this.config.container?document.body:pe(document).find(this.config.container);pe(i).data(this.constructor.DATA_KEY,this),pe.contains(this.element.ownerDocument.documentElement,this.tip)||pe(i).appendTo(a),pe(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new h(this.element,i,{placement:s,modifiers:{offset:{offset:this.config.offset},flip:{behavior:this.config.fallbackPlacement},arrow:{element:je},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){e._handlePopperPlacementChange(t)}}),pe(i).addClass(ke),"ontouchstart"in document.documentElement&&pe(document.body).children().on("mouseover",null,pe.noop);var l=function(){e.config.animation&&e._fixTransition();var t=e._hoverState;e._hoverState=null,pe(e.element).trigger(e.constructor.Event.SHOWN),t===we&&e._leave(null,e)};if(pe(this.tip).hasClass(Oe)){var c=Fn.getTransitionDurationFromElement(this.tip);pe(this.tip).one(Fn.TRANSITION_END,l).emulateTransitionEnd(c)}else l()}},t.hide=function(t){var e=this,n=this.getTipElement(),i=pe.Event(this.constructor.Event.HIDE),r=function(){e._hoverState!==De&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),pe(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(pe(this.element).trigger(i),!i.isDefaultPrevented()){if(pe(n).removeClass(ke),"ontouchstart"in document.documentElement&&pe(document.body).children().off("mouseover",null,pe.noop),this._activeTrigger[Re]=!1,this._activeTrigger[Le]=!1,this._activeTrigger[He]=!1,pe(this.tip).hasClass(Oe)){var o=Fn.getTransitionDurationFromElement(n);pe(n).one(Fn.TRANSITION_END,r).emulateTransitionEnd(o)}else r();this._hoverState=""}},t.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},t.isWithContent=function(){return Boolean(this.getTitle())},t.addAttachmentClass=function(t){pe(this.getTipElement()).addClass(Te+"-"+t)},t.getTipElement=function(){return this.tip=this.tip||pe(this.config.template)[0],this.tip},t.setContent=function(){var t=this.getTipElement();this.setElementContent(pe(t.querySelectorAll(Pe)),this.getTitle()),pe(t).removeClass(Oe+" "+ke)},t.setElementContent=function(t,e){var n=this.config.html;"object"==typeof e&&(e.nodeType||e.jquery)?n?pe(e).parent().is(t)||t.empty().append(e):t.text(pe(e).text()):t[n?"html":"text"](e)},t.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},t._getAttachment=function(t){return Ie[t.toUpperCase()]},t._setListeners=function(){var i=this;this.config.trigger.split(" ").forEach(function(t){if("click"===t)pe(i.element).on(i.constructor.Event.CLICK,i.config.selector,function(t){return i.toggle(t)});else if(t!==xe){var e=t===He?i.constructor.Event.MOUSEENTER:i.constructor.Event.FOCUSIN,n=t===He?i.constructor.Event.MOUSELEAVE:i.constructor.Event.FOCUSOUT;pe(i.element).on(e,i.config.selector,function(t){return i._enter(t)}).on(n,i.config.selector,function(t){return i._leave(t)})}pe(i.element).closest(".modal").on("hide.bs.modal",function(){return i.hide()})}),this.config.selector?this.config=l({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},t._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},t._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||pe(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),pe(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Le:He]=!0),pe(e.getTipElement()).hasClass(ke)||e._hoverState===De?e._hoverState=De:(clearTimeout(e._timeout),e._hoverState=De,e.config.delay&&e.config.delay.show?e._timeout=setTimeout(function(){e._hoverState===De&&e.show()},e.config.delay.show):e.show())},t._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||pe(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),pe(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Le:He]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=we,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout(function(){e._hoverState===we&&e.hide()},e.config.delay.hide):e.hide())},t._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},t._getConfig=function(t){return"number"==typeof(t=l({},this.constructor.Default,pe(this.element).data(),"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),Fn.typeCheckConfig(ve,t,this.constructor.DefaultType),t},t._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},t._cleanTipClass=function(){var t=pe(this.getTipElement()),e=t.attr("class").match(be);null!==e&&e.length&&t.removeClass(e.join(""))},t._handlePopperPlacementChange=function(t){var e=t.instance;this.tip=e.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},t._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(pe(t).removeClass(Oe),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},i._jQueryInterface=function(n){return this.each(function(){var t=pe(this).data(ye),e="object"==typeof n&&n;if((t||!/dispose|hide/.test(n))&&(t||(t=new i(this,e),pe(this).data(ye,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.1.3"}},{key:"Default",get:function(){return Ae}},{key:"NAME",get:function(){return ve}},{key:"DATA_KEY",get:function(){return ye}},{key:"Event",get:function(){return Ne}},{key:"EVENT_KEY",get:function(){return Ee}},{key:"DefaultType",get:function(){return Se}}]),i}(),pe.fn[ve]=We._jQueryInterface,pe.fn[ve].Constructor=We,pe.fn[ve].noConflict=function(){return pe.fn[ve]=Ce,We._jQueryInterface},We),Jn=(qe="popover",Ke="."+(Fe="bs.popover"),Me=(Ue=e).fn[qe],Qe="bs-popover",Be=new RegExp("(^|\\s)"+Qe+"\\S+","g"),Ve=l({},zn.Default,{placement:"right",trigger:"click",content:"",template:''}),Ye=l({},zn.DefaultType,{content:"(string|element|function)"}),ze="fade",Ze=".popover-header",Ge=".popover-body",$e={HIDE:"hide"+Ke,HIDDEN:"hidden"+Ke,SHOW:(Je="show")+Ke,SHOWN:"shown"+Ke,INSERTED:"inserted"+Ke,CLICK:"click"+Ke,FOCUSIN:"focusin"+Ke,FOCUSOUT:"focusout"+Ke,MOUSEENTER:"mouseenter"+Ke,MOUSELEAVE:"mouseleave"+Ke},Xe=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),(e.prototype.constructor=e).__proto__=n;var r=i.prototype;return r.isWithContent=function(){return this.getTitle()||this._getContent()},r.addAttachmentClass=function(t){Ue(this.getTipElement()).addClass(Qe+"-"+t)},r.getTipElement=function(){return this.tip=this.tip||Ue(this.config.template)[0],this.tip},r.setContent=function(){var t=Ue(this.getTipElement());this.setElementContent(t.find(Ze),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(Ge),e),t.removeClass(ze+" "+Je)},r._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},r._cleanTipClass=function(){var t=Ue(this.getTipElement()),e=t.attr("class").match(Be);null!==e&&0=this._offsets[r]&&("undefined"==typeof this._offsets[r+1]||tthis._items.length-1||t<0))if(this._isSliding)g(this._element).one(Q.SLID,function(){return e.to(t)});else{if(n===t)return this.pause(),void this.cycle();var i=ndocument.documentElement.clientHeight;!this._isBodyOverflowing&&t&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!t&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},t._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},t._checkScrollbar=function(){var t=document.body.getBoundingClientRect();this._isBodyOverflowing=t.left+t.right
    ',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:Ee},je="show",He="out",Re={HIDE:"hide"+De,HIDDEN:"hidden"+De,SHOW:"show"+De,SHOWN:"shown"+De,INSERTED:"inserted"+De,CLICK:"click"+De,FOCUSIN:"focusin"+De,FOCUSOUT:"focusout"+De,MOUSEENTER:"mouseenter"+De,MOUSELEAVE:"mouseleave"+De},xe="fade",Fe="show",Ue=".tooltip-inner",We=".arrow",qe="hover",Me="focus",Ke="click",Qe="manual",Be=function(){function i(t,e){if("undefined"==typeof u)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var t=i.prototype;return t.enable=function(){this._isEnabled=!0},t.disable=function(){this._isEnabled=!1},t.toggleEnabled=function(){this._isEnabled=!this._isEnabled},t.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=g(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(g(this.getTipElement()).hasClass(Fe))return void this._leave(null,this);this._enter(null,this)}},t.dispose=function(){clearTimeout(this._timeout),g.removeData(this.element,this.constructor.DATA_KEY),g(this.element).off(this.constructor.EVENT_KEY),g(this.element).closest(".modal").off("hide.bs.modal"),this.tip&&g(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,(this._activeTrigger=null)!==this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},t.show=function(){var e=this;if("none"===g(this.element).css("display"))throw new Error("Please use show on visible elements");var t=g.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){g(this.element).trigger(t);var n=_.findShadowRoot(this.element),i=g.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(t.isDefaultPrevented()||!i)return;var o=this.getTipElement(),r=_.getUID(this.constructor.NAME);o.setAttribute("id",r),this.element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&g(o).addClass(xe);var s="function"==typeof this.config.placement?this.config.placement.call(this,o,this.element):this.config.placement,a=this._getAttachment(s);this.addAttachmentClass(a);var l=this._getContainer();g(o).data(this.constructor.DATA_KEY,this),g.contains(this.element.ownerDocument.documentElement,this.tip)||g(o).appendTo(l),g(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new u(this.element,o,{placement:a,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:We},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){return e._handlePopperPlacementChange(t)}}),g(o).addClass(Fe),"ontouchstart"in document.documentElement&&g(document.body).children().on("mouseover",null,g.noop);var c=function(){e.config.animation&&e._fixTransition();var t=e._hoverState;e._hoverState=null,g(e.element).trigger(e.constructor.Event.SHOWN),t===He&&e._leave(null,e)};if(g(this.tip).hasClass(xe)){var h=_.getTransitionDurationFromElement(this.tip);g(this.tip).one(_.TRANSITION_END,c).emulateTransitionEnd(h)}else c()}},t.hide=function(t){var e=this,n=this.getTipElement(),i=g.Event(this.constructor.Event.HIDE),o=function(){e._hoverState!==je&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),g(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(g(this.element).trigger(i),!i.isDefaultPrevented()){if(g(n).removeClass(Fe),"ontouchstart"in document.documentElement&&g(document.body).children().off("mouseover",null,g.noop),this._activeTrigger[Ke]=!1,this._activeTrigger[Me]=!1,this._activeTrigger[qe]=!1,g(this.tip).hasClass(xe)){var r=_.getTransitionDurationFromElement(n);g(n).one(_.TRANSITION_END,o).emulateTransitionEnd(r)}else o();this._hoverState=""}},t.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},t.isWithContent=function(){return Boolean(this.getTitle())},t.addAttachmentClass=function(t){g(this.getTipElement()).addClass(Ae+"-"+t)},t.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},t.setContent=function(){var t=this.getTipElement();this.setElementContent(g(t.querySelectorAll(Ue)),this.getTitle()),g(t).removeClass(xe+" "+Fe)},t.setElementContent=function(t,e){"object"!=typeof e||!e.nodeType&&!e.jquery?this.config.html?(this.config.sanitize&&(e=Se(e,this.config.whiteList,this.config.sanitizeFn)),t.html(e)):t.text(e):this.config.html?g(e).parent().is(t)||t.empty().append(e):t.text(g(e).text())},t.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},t._getOffset=function(){var e=this,t={};return"function"==typeof this.config.offset?t.fn=function(t){return t.offsets=l({},t.offsets,e.config.offset(t.offsets,e.element)||{}),t}:t.offset=this.config.offset,t},t._getContainer=function(){return!1===this.config.container?document.body:_.isElement(this.config.container)?g(this.config.container):g(document).find(this.config.container)},t._getAttachment=function(t){return Pe[t.toUpperCase()]},t._setListeners=function(){var i=this;this.config.trigger.split(" ").forEach(function(t){if("click"===t)g(i.element).on(i.constructor.Event.CLICK,i.config.selector,function(t){return i.toggle(t)});else if(t!==Qe){var e=t===qe?i.constructor.Event.MOUSEENTER:i.constructor.Event.FOCUSIN,n=t===qe?i.constructor.Event.MOUSELEAVE:i.constructor.Event.FOCUSOUT;g(i.element).on(e,i.config.selector,function(t){return i._enter(t)}).on(n,i.config.selector,function(t){return i._leave(t)})}}),g(this.element).closest(".modal").on("hide.bs.modal",function(){i.element&&i.hide()}),this.config.selector?this.config=l({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},t._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},t._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Me:qe]=!0),g(e.getTipElement()).hasClass(Fe)||e._hoverState===je?e._hoverState=je:(clearTimeout(e._timeout),e._hoverState=je,e.config.delay&&e.config.delay.show?e._timeout=setTimeout(function(){e._hoverState===je&&e.show()},e.config.delay.show):e.show())},t._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||g(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),g(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Me:qe]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=He,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout(function(){e._hoverState===He&&e.hide()},e.config.delay.hide):e.hide())},t._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},t._getConfig=function(t){var e=g(this.element).data();return Object.keys(e).forEach(function(t){-1!==Oe.indexOf(t)&&delete e[t]}),"number"==typeof(t=l({},this.constructor.Default,e,"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),_.typeCheckConfig(be,t,this.constructor.DefaultType),t.sanitize&&(t.template=Se(t.template,t.whiteList,t.sanitizeFn)),t},t._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},t._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(Ne);null!==e&&e.length&&t.removeClass(e.join(""))},t._handlePopperPlacementChange=function(t){var e=t.instance;this.tip=e.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},t._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(g(t).removeClass(xe),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},i._jQueryInterface=function(n){return this.each(function(){var t=g(this).data(Ie),e="object"==typeof n&&n;if((t||!/dispose|hide/.test(n))&&(t||(t=new i(this,e),g(this).data(Ie,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.3.1"}},{key:"Default",get:function(){return Le}},{key:"NAME",get:function(){return be}},{key:"DATA_KEY",get:function(){return Ie}},{key:"Event",get:function(){return Re}},{key:"EVENT_KEY",get:function(){return De}},{key:"DefaultType",get:function(){return ke}}]),i}();g.fn[be]=Be._jQueryInterface,g.fn[be].Constructor=Be,g.fn[be].noConflict=function(){return g.fn[be]=we,Be._jQueryInterface};var Ve="popover",Ye="bs.popover",ze="."+Ye,Xe=g.fn[Ve],$e="bs-popover",Ge=new RegExp("(^|\\s)"+$e+"\\S+","g"),Je=l({},Be.Default,{placement:"right",trigger:"click",content:"",template:''}),Ze=l({},Be.DefaultType,{content:"(string|element|function)"}),tn="fade",en="show",nn=".popover-header",on=".popover-body",rn={HIDE:"hide"+ze,HIDDEN:"hidden"+ze,SHOW:"show"+ze,SHOWN:"shown"+ze,INSERTED:"inserted"+ze,CLICK:"click"+ze,FOCUSIN:"focusin"+ze,FOCUSOUT:"focusout"+ze,MOUSEENTER:"mouseenter"+ze,MOUSELEAVE:"mouseleave"+ze},sn=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),(e.prototype.constructor=e).__proto__=n;var o=i.prototype;return o.isWithContent=function(){return this.getTitle()||this._getContent()},o.addAttachmentClass=function(t){g(this.getTipElement()).addClass($e+"-"+t)},o.getTipElement=function(){return this.tip=this.tip||g(this.config.template)[0],this.tip},o.setContent=function(){var t=g(this.getTipElement());this.setElementContent(t.find(nn),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(on),e),t.removeClass(tn+" "+en)},o._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},o._cleanTipClass=function(){var t=g(this.getTipElement()),e=t.attr("class").match(Ge);null!==e&&0=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||t {\n /**\n * ------------------------------------------------------------------------\n * Private TransitionEnd Helpers\n * ------------------------------------------------------------------------\n */\n\n const TRANSITION_END = 'transitionend'\n const MAX_UID = 1000000\n const MILLISECONDS_MULTIPLIER = 1000\n\n // Shoutout AngusCroll (https://goo.gl/pxwQGp)\n function toType(obj) {\n return {}.toString.call(obj).match(/\\s([a-z]+)/i)[1].toLowerCase()\n }\n\n function getSpecialTransitionEndEvent() {\n return {\n bindType: TRANSITION_END,\n delegateType: TRANSITION_END,\n handle(event) {\n if ($(event.target).is(this)) {\n return event.handleObj.handler.apply(this, arguments) // eslint-disable-line prefer-rest-params\n }\n return undefined // eslint-disable-line no-undefined\n }\n }\n }\n\n function transitionEndEmulator(duration) {\n let called = false\n\n $(this).one(Util.TRANSITION_END, () => {\n called = true\n })\n\n setTimeout(() => {\n if (!called) {\n Util.triggerTransitionEnd(this)\n }\n }, duration)\n\n return this\n }\n\n function setTransitionEndSupport() {\n $.fn.emulateTransitionEnd = transitionEndEmulator\n $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent()\n }\n\n /**\n * --------------------------------------------------------------------------\n * Public Util Api\n * --------------------------------------------------------------------------\n */\n\n const Util = {\n\n TRANSITION_END: 'bsTransitionEnd',\n\n getUID(prefix) {\n do {\n // eslint-disable-next-line no-bitwise\n prefix += ~~(Math.random() * MAX_UID) // \"~~\" acts like a faster Math.floor() here\n } while (document.getElementById(prefix))\n return prefix\n },\n\n getSelectorFromElement(element) {\n let selector = element.getAttribute('data-target')\n if (!selector || selector === '#') {\n selector = element.getAttribute('href') || ''\n }\n\n try {\n return document.querySelector(selector) ? selector : null\n } catch (err) {\n return null\n }\n },\n\n getTransitionDurationFromElement(element) {\n if (!element) {\n return 0\n }\n\n // Get transition-duration of the element\n let transitionDuration = $(element).css('transition-duration')\n const floatTransitionDuration = parseFloat(transitionDuration)\n\n // Return 0 if element or transition duration is not found\n if (!floatTransitionDuration) {\n return 0\n }\n\n // If multiple durations are defined, take the first\n transitionDuration = transitionDuration.split(',')[0]\n\n return parseFloat(transitionDuration) * MILLISECONDS_MULTIPLIER\n },\n\n reflow(element) {\n return element.offsetHeight\n },\n\n triggerTransitionEnd(element) {\n $(element).trigger(TRANSITION_END)\n },\n\n // TODO: Remove in v5\n supportsTransitionEnd() {\n return Boolean(TRANSITION_END)\n },\n\n isElement(obj) {\n return (obj[0] || obj).nodeType\n },\n\n typeCheckConfig(componentName, config, configTypes) {\n for (const property in configTypes) {\n if (Object.prototype.hasOwnProperty.call(configTypes, property)) {\n const expectedTypes = configTypes[property]\n const value = config[property]\n const valueType = value && Util.isElement(value)\n ? 'element' : toType(value)\n\n if (!new RegExp(expectedTypes).test(valueType)) {\n throw new Error(\n `${componentName.toUpperCase()}: ` +\n `Option \"${property}\" provided type \"${valueType}\" ` +\n `but expected type \"${expectedTypes}\".`)\n }\n }\n }\n }\n }\n\n setTransitionEndSupport()\n\n return Util\n})($)\n\nexport default Util\n","import $ from 'jquery'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): alert.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Alert = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'alert'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.alert'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n\n const Selector = {\n DISMISS : '[data-dismiss=\"alert\"]'\n }\n\n const Event = {\n CLOSE : `close${EVENT_KEY}`,\n CLOSED : `closed${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n ALERT : 'alert',\n FADE : 'fade',\n SHOW : 'show'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Alert {\n constructor(element) {\n this._element = element\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n // Public\n\n close(element) {\n let rootElement = this._element\n if (element) {\n rootElement = this._getRootElement(element)\n }\n\n const customEvent = this._triggerCloseEvent(rootElement)\n\n if (customEvent.isDefaultPrevented()) {\n return\n }\n\n this._removeElement(rootElement)\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n this._element = null\n }\n\n // Private\n\n _getRootElement(element) {\n const selector = Util.getSelectorFromElement(element)\n let parent = false\n\n if (selector) {\n parent = document.querySelector(selector)\n }\n\n if (!parent) {\n parent = $(element).closest(`.${ClassName.ALERT}`)[0]\n }\n\n return parent\n }\n\n _triggerCloseEvent(element) {\n const closeEvent = $.Event(Event.CLOSE)\n\n $(element).trigger(closeEvent)\n return closeEvent\n }\n\n _removeElement(element) {\n $(element).removeClass(ClassName.SHOW)\n\n if (!$(element).hasClass(ClassName.FADE)) {\n this._destroyElement(element)\n return\n }\n\n const transitionDuration = Util.getTransitionDurationFromElement(element)\n\n $(element)\n .one(Util.TRANSITION_END, (event) => this._destroyElement(element, event))\n .emulateTransitionEnd(transitionDuration)\n }\n\n _destroyElement(element) {\n $(element)\n .detach()\n .trigger(Event.CLOSED)\n .remove()\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n const $element = $(this)\n let data = $element.data(DATA_KEY)\n\n if (!data) {\n data = new Alert(this)\n $element.data(DATA_KEY, data)\n }\n\n if (config === 'close') {\n data[config](this)\n }\n })\n }\n\n static _handleDismiss(alertInstance) {\n return function (event) {\n if (event) {\n event.preventDefault()\n }\n\n alertInstance.close(this)\n }\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document).on(\n Event.CLICK_DATA_API,\n Selector.DISMISS,\n Alert._handleDismiss(new Alert())\n )\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Alert._jQueryInterface\n $.fn[NAME].Constructor = Alert\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Alert._jQueryInterface\n }\n\n return Alert\n})($)\n\nexport default Alert\n","import $ from 'jquery'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): button.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Button = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'button'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.button'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n\n const ClassName = {\n ACTIVE : 'active',\n BUTTON : 'btn',\n FOCUS : 'focus'\n }\n\n const Selector = {\n DATA_TOGGLE_CARROT : '[data-toggle^=\"button\"]',\n DATA_TOGGLE : '[data-toggle=\"buttons\"]',\n INPUT : 'input',\n ACTIVE : '.active',\n BUTTON : '.btn'\n }\n\n const Event = {\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`,\n FOCUS_BLUR_DATA_API : `focus${EVENT_KEY}${DATA_API_KEY} ` +\n `blur${EVENT_KEY}${DATA_API_KEY}`\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Button {\n constructor(element) {\n this._element = element\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n // Public\n\n toggle() {\n let triggerChangeEvent = true\n let addAriaPressed = true\n const rootElement = $(this._element).closest(\n Selector.DATA_TOGGLE\n )[0]\n\n if (rootElement) {\n const input = this._element.querySelector(Selector.INPUT)\n\n if (input) {\n if (input.type === 'radio') {\n if (input.checked &&\n this._element.classList.contains(ClassName.ACTIVE)) {\n triggerChangeEvent = false\n } else {\n const activeElement = rootElement.querySelector(Selector.ACTIVE)\n\n if (activeElement) {\n $(activeElement).removeClass(ClassName.ACTIVE)\n }\n }\n }\n\n if (triggerChangeEvent) {\n if (input.hasAttribute('disabled') ||\n rootElement.hasAttribute('disabled') ||\n input.classList.contains('disabled') ||\n rootElement.classList.contains('disabled')) {\n return\n }\n input.checked = !this._element.classList.contains(ClassName.ACTIVE)\n $(input).trigger('change')\n }\n\n input.focus()\n addAriaPressed = false\n }\n }\n\n if (addAriaPressed) {\n this._element.setAttribute('aria-pressed',\n !this._element.classList.contains(ClassName.ACTIVE))\n }\n\n if (triggerChangeEvent) {\n $(this._element).toggleClass(ClassName.ACTIVE)\n }\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n this._element = null\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n\n if (!data) {\n data = new Button(this)\n $(this).data(DATA_KEY, data)\n }\n\n if (config === 'toggle') {\n data[config]()\n }\n })\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document)\n .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => {\n event.preventDefault()\n\n let button = event.target\n\n if (!$(button).hasClass(ClassName.BUTTON)) {\n button = $(button).closest(Selector.BUTTON)\n }\n\n Button._jQueryInterface.call($(button), 'toggle')\n })\n .on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => {\n const button = $(event.target).closest(Selector.BUTTON)[0]\n $(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type))\n })\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Button._jQueryInterface\n $.fn[NAME].Constructor = Button\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Button._jQueryInterface\n }\n\n return Button\n})($)\n\nexport default Button\n","import $ from 'jquery'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): carousel.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Carousel = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'carousel'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.carousel'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n const ARROW_LEFT_KEYCODE = 37 // KeyboardEvent.which value for left arrow key\n const ARROW_RIGHT_KEYCODE = 39 // KeyboardEvent.which value for right arrow key\n const TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch\n\n const Default = {\n interval : 5000,\n keyboard : true,\n slide : false,\n pause : 'hover',\n wrap : true\n }\n\n const DefaultType = {\n interval : '(number|boolean)',\n keyboard : 'boolean',\n slide : '(boolean|string)',\n pause : '(string|boolean)',\n wrap : 'boolean'\n }\n\n const Direction = {\n NEXT : 'next',\n PREV : 'prev',\n LEFT : 'left',\n RIGHT : 'right'\n }\n\n const Event = {\n SLIDE : `slide${EVENT_KEY}`,\n SLID : `slid${EVENT_KEY}`,\n KEYDOWN : `keydown${EVENT_KEY}`,\n MOUSEENTER : `mouseenter${EVENT_KEY}`,\n MOUSELEAVE : `mouseleave${EVENT_KEY}`,\n TOUCHEND : `touchend${EVENT_KEY}`,\n LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n CAROUSEL : 'carousel',\n ACTIVE : 'active',\n SLIDE : 'slide',\n RIGHT : 'carousel-item-right',\n LEFT : 'carousel-item-left',\n NEXT : 'carousel-item-next',\n PREV : 'carousel-item-prev',\n ITEM : 'carousel-item'\n }\n\n const Selector = {\n ACTIVE : '.active',\n ACTIVE_ITEM : '.active.carousel-item',\n ITEM : '.carousel-item',\n NEXT_PREV : '.carousel-item-next, .carousel-item-prev',\n INDICATORS : '.carousel-indicators',\n DATA_SLIDE : '[data-slide], [data-slide-to]',\n DATA_RIDE : '[data-ride=\"carousel\"]'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Carousel {\n constructor(element, config) {\n this._items = null\n this._interval = null\n this._activeElement = null\n\n this._isPaused = false\n this._isSliding = false\n\n this.touchTimeout = null\n\n this._config = this._getConfig(config)\n this._element = $(element)[0]\n this._indicatorsElement = this._element.querySelector(Selector.INDICATORS)\n\n this._addEventListeners()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n next() {\n if (!this._isSliding) {\n this._slide(Direction.NEXT)\n }\n }\n\n nextWhenVisible() {\n // Don't call next when the page isn't visible\n // or the carousel or its parent isn't visible\n if (!document.hidden &&\n ($(this._element).is(':visible') && $(this._element).css('visibility') !== 'hidden')) {\n this.next()\n }\n }\n\n prev() {\n if (!this._isSliding) {\n this._slide(Direction.PREV)\n }\n }\n\n pause(event) {\n if (!event) {\n this._isPaused = true\n }\n\n if (this._element.querySelector(Selector.NEXT_PREV)) {\n Util.triggerTransitionEnd(this._element)\n this.cycle(true)\n }\n\n clearInterval(this._interval)\n this._interval = null\n }\n\n cycle(event) {\n if (!event) {\n this._isPaused = false\n }\n\n if (this._interval) {\n clearInterval(this._interval)\n this._interval = null\n }\n\n if (this._config.interval && !this._isPaused) {\n this._interval = setInterval(\n (document.visibilityState ? this.nextWhenVisible : this.next).bind(this),\n this._config.interval\n )\n }\n }\n\n to(index) {\n this._activeElement = this._element.querySelector(Selector.ACTIVE_ITEM)\n\n const activeIndex = this._getItemIndex(this._activeElement)\n\n if (index > this._items.length - 1 || index < 0) {\n return\n }\n\n if (this._isSliding) {\n $(this._element).one(Event.SLID, () => this.to(index))\n return\n }\n\n if (activeIndex === index) {\n this.pause()\n this.cycle()\n return\n }\n\n const direction = index > activeIndex\n ? Direction.NEXT\n : Direction.PREV\n\n this._slide(direction, this._items[index])\n }\n\n dispose() {\n $(this._element).off(EVENT_KEY)\n $.removeData(this._element, DATA_KEY)\n\n this._items = null\n this._config = null\n this._element = null\n this._interval = null\n this._isPaused = null\n this._isSliding = null\n this._activeElement = null\n this._indicatorsElement = null\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...config\n }\n Util.typeCheckConfig(NAME, config, DefaultType)\n return config\n }\n\n _addEventListeners() {\n if (this._config.keyboard) {\n $(this._element)\n .on(Event.KEYDOWN, (event) => this._keydown(event))\n }\n\n if (this._config.pause === 'hover') {\n $(this._element)\n .on(Event.MOUSEENTER, (event) => this.pause(event))\n .on(Event.MOUSELEAVE, (event) => this.cycle(event))\n if ('ontouchstart' in document.documentElement) {\n // If it's a touch-enabled device, mouseenter/leave are fired as\n // part of the mouse compatibility events on first tap - the carousel\n // would stop cycling until user tapped out of it;\n // here, we listen for touchend, explicitly pause the carousel\n // (as if it's the second time we tap on it, mouseenter compat event\n // is NOT fired) and after a timeout (to allow for mouse compatibility\n // events to fire) we explicitly restart cycling\n $(this._element).on(Event.TOUCHEND, () => {\n this.pause()\n if (this.touchTimeout) {\n clearTimeout(this.touchTimeout)\n }\n this.touchTimeout = setTimeout((event) => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval)\n })\n }\n }\n }\n\n _keydown(event) {\n if (/input|textarea/i.test(event.target.tagName)) {\n return\n }\n\n switch (event.which) {\n case ARROW_LEFT_KEYCODE:\n event.preventDefault()\n this.prev()\n break\n case ARROW_RIGHT_KEYCODE:\n event.preventDefault()\n this.next()\n break\n default:\n }\n }\n\n _getItemIndex(element) {\n this._items = element && element.parentNode\n ? [].slice.call(element.parentNode.querySelectorAll(Selector.ITEM))\n : []\n return this._items.indexOf(element)\n }\n\n _getItemByDirection(direction, activeElement) {\n const isNextDirection = direction === Direction.NEXT\n const isPrevDirection = direction === Direction.PREV\n const activeIndex = this._getItemIndex(activeElement)\n const lastItemIndex = this._items.length - 1\n const isGoingToWrap = isPrevDirection && activeIndex === 0 ||\n isNextDirection && activeIndex === lastItemIndex\n\n if (isGoingToWrap && !this._config.wrap) {\n return activeElement\n }\n\n const delta = direction === Direction.PREV ? -1 : 1\n const itemIndex = (activeIndex + delta) % this._items.length\n\n return itemIndex === -1\n ? this._items[this._items.length - 1] : this._items[itemIndex]\n }\n\n _triggerSlideEvent(relatedTarget, eventDirectionName) {\n const targetIndex = this._getItemIndex(relatedTarget)\n const fromIndex = this._getItemIndex(this._element.querySelector(Selector.ACTIVE_ITEM))\n const slideEvent = $.Event(Event.SLIDE, {\n relatedTarget,\n direction: eventDirectionName,\n from: fromIndex,\n to: targetIndex\n })\n\n $(this._element).trigger(slideEvent)\n\n return slideEvent\n }\n\n _setActiveIndicatorElement(element) {\n if (this._indicatorsElement) {\n const indicators = [].slice.call(this._indicatorsElement.querySelectorAll(Selector.ACTIVE))\n $(indicators)\n .removeClass(ClassName.ACTIVE)\n\n const nextIndicator = this._indicatorsElement.children[\n this._getItemIndex(element)\n ]\n\n if (nextIndicator) {\n $(nextIndicator).addClass(ClassName.ACTIVE)\n }\n }\n }\n\n _slide(direction, element) {\n const activeElement = this._element.querySelector(Selector.ACTIVE_ITEM)\n const activeElementIndex = this._getItemIndex(activeElement)\n const nextElement = element || activeElement &&\n this._getItemByDirection(direction, activeElement)\n const nextElementIndex = this._getItemIndex(nextElement)\n const isCycling = Boolean(this._interval)\n\n let directionalClassName\n let orderClassName\n let eventDirectionName\n\n if (direction === Direction.NEXT) {\n directionalClassName = ClassName.LEFT\n orderClassName = ClassName.NEXT\n eventDirectionName = Direction.LEFT\n } else {\n directionalClassName = ClassName.RIGHT\n orderClassName = ClassName.PREV\n eventDirectionName = Direction.RIGHT\n }\n\n if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) {\n this._isSliding = false\n return\n }\n\n const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName)\n if (slideEvent.isDefaultPrevented()) {\n return\n }\n\n if (!activeElement || !nextElement) {\n // Some weirdness is happening, so we bail\n return\n }\n\n this._isSliding = true\n\n if (isCycling) {\n this.pause()\n }\n\n this._setActiveIndicatorElement(nextElement)\n\n const slidEvent = $.Event(Event.SLID, {\n relatedTarget: nextElement,\n direction: eventDirectionName,\n from: activeElementIndex,\n to: nextElementIndex\n })\n\n if ($(this._element).hasClass(ClassName.SLIDE)) {\n $(nextElement).addClass(orderClassName)\n\n Util.reflow(nextElement)\n\n $(activeElement).addClass(directionalClassName)\n $(nextElement).addClass(directionalClassName)\n\n const transitionDuration = Util.getTransitionDurationFromElement(activeElement)\n\n $(activeElement)\n .one(Util.TRANSITION_END, () => {\n $(nextElement)\n .removeClass(`${directionalClassName} ${orderClassName}`)\n .addClass(ClassName.ACTIVE)\n\n $(activeElement).removeClass(`${ClassName.ACTIVE} ${orderClassName} ${directionalClassName}`)\n\n this._isSliding = false\n\n setTimeout(() => $(this._element).trigger(slidEvent), 0)\n })\n .emulateTransitionEnd(transitionDuration)\n } else {\n $(activeElement).removeClass(ClassName.ACTIVE)\n $(nextElement).addClass(ClassName.ACTIVE)\n\n this._isSliding = false\n $(this._element).trigger(slidEvent)\n }\n\n if (isCycling) {\n this.cycle()\n }\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n let _config = {\n ...Default,\n ...$(this).data()\n }\n\n if (typeof config === 'object') {\n _config = {\n ..._config,\n ...config\n }\n }\n\n const action = typeof config === 'string' ? config : _config.slide\n\n if (!data) {\n data = new Carousel(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'number') {\n data.to(config)\n } else if (typeof action === 'string') {\n if (typeof data[action] === 'undefined') {\n throw new TypeError(`No method named \"${action}\"`)\n }\n data[action]()\n } else if (_config.interval) {\n data.pause()\n data.cycle()\n }\n })\n }\n\n static _dataApiClickHandler(event) {\n const selector = Util.getSelectorFromElement(this)\n\n if (!selector) {\n return\n }\n\n const target = $(selector)[0]\n\n if (!target || !$(target).hasClass(ClassName.CAROUSEL)) {\n return\n }\n\n const config = {\n ...$(target).data(),\n ...$(this).data()\n }\n const slideIndex = this.getAttribute('data-slide-to')\n\n if (slideIndex) {\n config.interval = false\n }\n\n Carousel._jQueryInterface.call($(target), config)\n\n if (slideIndex) {\n $(target).data(DATA_KEY).to(slideIndex)\n }\n\n event.preventDefault()\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document)\n .on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler)\n\n $(window).on(Event.LOAD_DATA_API, () => {\n const carousels = [].slice.call(document.querySelectorAll(Selector.DATA_RIDE))\n for (let i = 0, len = carousels.length; i < len; i++) {\n const $carousel = $(carousels[i])\n Carousel._jQueryInterface.call($carousel, $carousel.data())\n }\n })\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Carousel._jQueryInterface\n $.fn[NAME].Constructor = Carousel\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Carousel._jQueryInterface\n }\n\n return Carousel\n})($)\n\nexport default Carousel\n","import $ from 'jquery'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): collapse.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Collapse = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'collapse'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.collapse'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n\n const Default = {\n toggle : true,\n parent : ''\n }\n\n const DefaultType = {\n toggle : 'boolean',\n parent : '(string|element)'\n }\n\n const Event = {\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n SHOW : 'show',\n COLLAPSE : 'collapse',\n COLLAPSING : 'collapsing',\n COLLAPSED : 'collapsed'\n }\n\n const Dimension = {\n WIDTH : 'width',\n HEIGHT : 'height'\n }\n\n const Selector = {\n ACTIVES : '.show, .collapsing',\n DATA_TOGGLE : '[data-toggle=\"collapse\"]'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Collapse {\n constructor(element, config) {\n this._isTransitioning = false\n this._element = element\n this._config = this._getConfig(config)\n this._triggerArray = $.makeArray(document.querySelectorAll(\n `[data-toggle=\"collapse\"][href=\"#${element.id}\"],` +\n `[data-toggle=\"collapse\"][data-target=\"#${element.id}\"]`\n ))\n const toggleList = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE))\n for (let i = 0, len = toggleList.length; i < len; i++) {\n const elem = toggleList[i]\n const selector = Util.getSelectorFromElement(elem)\n const filterElement = [].slice.call(document.querySelectorAll(selector))\n .filter((foundElem) => foundElem === element)\n\n if (selector !== null && filterElement.length > 0) {\n this._selector = selector\n this._triggerArray.push(elem)\n }\n }\n\n this._parent = this._config.parent ? this._getParent() : null\n\n if (!this._config.parent) {\n this._addAriaAndCollapsedClass(this._element, this._triggerArray)\n }\n\n if (this._config.toggle) {\n this.toggle()\n }\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n toggle() {\n if ($(this._element).hasClass(ClassName.SHOW)) {\n this.hide()\n } else {\n this.show()\n }\n }\n\n show() {\n if (this._isTransitioning ||\n $(this._element).hasClass(ClassName.SHOW)) {\n return\n }\n\n let actives\n let activesData\n\n if (this._parent) {\n actives = [].slice.call(this._parent.querySelectorAll(Selector.ACTIVES))\n .filter((elem) => elem.getAttribute('data-parent') === this._config.parent)\n\n if (actives.length === 0) {\n actives = null\n }\n }\n\n if (actives) {\n activesData = $(actives).not(this._selector).data(DATA_KEY)\n if (activesData && activesData._isTransitioning) {\n return\n }\n }\n\n const startEvent = $.Event(Event.SHOW)\n $(this._element).trigger(startEvent)\n if (startEvent.isDefaultPrevented()) {\n return\n }\n\n if (actives) {\n Collapse._jQueryInterface.call($(actives).not(this._selector), 'hide')\n if (!activesData) {\n $(actives).data(DATA_KEY, null)\n }\n }\n\n const dimension = this._getDimension()\n\n $(this._element)\n .removeClass(ClassName.COLLAPSE)\n .addClass(ClassName.COLLAPSING)\n\n this._element.style[dimension] = 0\n\n if (this._triggerArray.length) {\n $(this._triggerArray)\n .removeClass(ClassName.COLLAPSED)\n .attr('aria-expanded', true)\n }\n\n this.setTransitioning(true)\n\n const complete = () => {\n $(this._element)\n .removeClass(ClassName.COLLAPSING)\n .addClass(ClassName.COLLAPSE)\n .addClass(ClassName.SHOW)\n\n this._element.style[dimension] = ''\n\n this.setTransitioning(false)\n\n $(this._element).trigger(Event.SHOWN)\n }\n\n const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1)\n const scrollSize = `scroll${capitalizedDimension}`\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._element)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n\n this._element.style[dimension] = `${this._element[scrollSize]}px`\n }\n\n hide() {\n if (this._isTransitioning ||\n !$(this._element).hasClass(ClassName.SHOW)) {\n return\n }\n\n const startEvent = $.Event(Event.HIDE)\n $(this._element).trigger(startEvent)\n if (startEvent.isDefaultPrevented()) {\n return\n }\n\n const dimension = this._getDimension()\n\n this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`\n\n Util.reflow(this._element)\n\n $(this._element)\n .addClass(ClassName.COLLAPSING)\n .removeClass(ClassName.COLLAPSE)\n .removeClass(ClassName.SHOW)\n\n const triggerArrayLength = this._triggerArray.length\n if (triggerArrayLength > 0) {\n for (let i = 0; i < triggerArrayLength; i++) {\n const trigger = this._triggerArray[i]\n const selector = Util.getSelectorFromElement(trigger)\n if (selector !== null) {\n const $elem = $([].slice.call(document.querySelectorAll(selector)))\n if (!$elem.hasClass(ClassName.SHOW)) {\n $(trigger).addClass(ClassName.COLLAPSED)\n .attr('aria-expanded', false)\n }\n }\n }\n }\n\n this.setTransitioning(true)\n\n const complete = () => {\n this.setTransitioning(false)\n $(this._element)\n .removeClass(ClassName.COLLAPSING)\n .addClass(ClassName.COLLAPSE)\n .trigger(Event.HIDDEN)\n }\n\n this._element.style[dimension] = ''\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._element)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n }\n\n setTransitioning(isTransitioning) {\n this._isTransitioning = isTransitioning\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n\n this._config = null\n this._parent = null\n this._element = null\n this._triggerArray = null\n this._isTransitioning = null\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...config\n }\n config.toggle = Boolean(config.toggle) // Coerce string values\n Util.typeCheckConfig(NAME, config, DefaultType)\n return config\n }\n\n _getDimension() {\n const hasWidth = $(this._element).hasClass(Dimension.WIDTH)\n return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT\n }\n\n _getParent() {\n let parent = null\n if (Util.isElement(this._config.parent)) {\n parent = this._config.parent\n\n // It's a jQuery object\n if (typeof this._config.parent.jquery !== 'undefined') {\n parent = this._config.parent[0]\n }\n } else {\n parent = document.querySelector(this._config.parent)\n }\n\n const selector =\n `[data-toggle=\"collapse\"][data-parent=\"${this._config.parent}\"]`\n\n const children = [].slice.call(parent.querySelectorAll(selector))\n $(children).each((i, element) => {\n this._addAriaAndCollapsedClass(\n Collapse._getTargetFromElement(element),\n [element]\n )\n })\n\n return parent\n }\n\n _addAriaAndCollapsedClass(element, triggerArray) {\n if (element) {\n const isOpen = $(element).hasClass(ClassName.SHOW)\n\n if (triggerArray.length) {\n $(triggerArray)\n .toggleClass(ClassName.COLLAPSED, !isOpen)\n .attr('aria-expanded', isOpen)\n }\n }\n }\n\n // Static\n\n static _getTargetFromElement(element) {\n const selector = Util.getSelectorFromElement(element)\n return selector ? document.querySelector(selector) : null\n }\n\n static _jQueryInterface(config) {\n return this.each(function () {\n const $this = $(this)\n let data = $this.data(DATA_KEY)\n const _config = {\n ...Default,\n ...$this.data(),\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (!data && _config.toggle && /show|hide/.test(config)) {\n _config.toggle = false\n }\n\n if (!data) {\n data = new Collapse(this, _config)\n $this.data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config]()\n }\n })\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n // preventDefault only for elements (which change the URL) not inside the collapsible element\n if (event.currentTarget.tagName === 'A') {\n event.preventDefault()\n }\n\n const $trigger = $(this)\n const selector = Util.getSelectorFromElement(this)\n const selectors = [].slice.call(document.querySelectorAll(selector))\n $(selectors).each(function () {\n const $target = $(this)\n const data = $target.data(DATA_KEY)\n const config = data ? 'toggle' : $trigger.data()\n Collapse._jQueryInterface.call($target, config)\n })\n })\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Collapse._jQueryInterface\n $.fn[NAME].Constructor = Collapse\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Collapse._jQueryInterface\n }\n\n return Collapse\n})($)\n\nexport default Collapse\n","import $ from 'jquery'\nimport Popper from 'popper.js'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): dropdown.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Dropdown = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'dropdown'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.dropdown'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n const ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key\n const SPACE_KEYCODE = 32 // KeyboardEvent.which value for space key\n const TAB_KEYCODE = 9 // KeyboardEvent.which value for tab key\n const ARROW_UP_KEYCODE = 38 // KeyboardEvent.which value for up arrow key\n const ARROW_DOWN_KEYCODE = 40 // KeyboardEvent.which value for down arrow key\n const RIGHT_MOUSE_BUTTON_WHICH = 3 // MouseEvent.which value for the right button (assuming a right-handed mouse)\n const REGEXP_KEYDOWN = new RegExp(`${ARROW_UP_KEYCODE}|${ARROW_DOWN_KEYCODE}|${ESCAPE_KEYCODE}`)\n\n const Event = {\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n CLICK : `click${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`,\n KEYDOWN_DATA_API : `keydown${EVENT_KEY}${DATA_API_KEY}`,\n KEYUP_DATA_API : `keyup${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n DISABLED : 'disabled',\n SHOW : 'show',\n DROPUP : 'dropup',\n DROPRIGHT : 'dropright',\n DROPLEFT : 'dropleft',\n MENURIGHT : 'dropdown-menu-right',\n MENULEFT : 'dropdown-menu-left',\n POSITION_STATIC : 'position-static'\n }\n\n const Selector = {\n DATA_TOGGLE : '[data-toggle=\"dropdown\"]',\n FORM_CHILD : '.dropdown form',\n MENU : '.dropdown-menu',\n NAVBAR_NAV : '.navbar-nav',\n VISIBLE_ITEMS : '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'\n }\n\n const AttachmentMap = {\n TOP : 'top-start',\n TOPEND : 'top-end',\n BOTTOM : 'bottom-start',\n BOTTOMEND : 'bottom-end',\n RIGHT : 'right-start',\n RIGHTEND : 'right-end',\n LEFT : 'left-start',\n LEFTEND : 'left-end'\n }\n\n const Default = {\n offset : 0,\n flip : true,\n boundary : 'scrollParent',\n reference : 'toggle',\n display : 'dynamic'\n }\n\n const DefaultType = {\n offset : '(number|string|function)',\n flip : 'boolean',\n boundary : '(string|element)',\n reference : '(string|element)',\n display : 'string'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Dropdown {\n constructor(element, config) {\n this._element = element\n this._popper = null\n this._config = this._getConfig(config)\n this._menu = this._getMenuElement()\n this._inNavbar = this._detectNavbar()\n\n this._addEventListeners()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n // Public\n\n toggle() {\n if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED)) {\n return\n }\n\n const parent = Dropdown._getParentFromElement(this._element)\n const isActive = $(this._menu).hasClass(ClassName.SHOW)\n\n Dropdown._clearMenus()\n\n if (isActive) {\n return\n }\n\n const relatedTarget = {\n relatedTarget: this._element\n }\n const showEvent = $.Event(Event.SHOW, relatedTarget)\n\n $(parent).trigger(showEvent)\n\n if (showEvent.isDefaultPrevented()) {\n return\n }\n\n // Disable totally Popper.js for Dropdown in Navbar\n if (!this._inNavbar) {\n /**\n * Check for Popper dependency\n * Popper - https://popper.js.org\n */\n if (typeof Popper === 'undefined') {\n throw new TypeError('Bootstrap dropdown require Popper.js (https://popper.js.org)')\n }\n\n let referenceElement = this._element\n\n if (this._config.reference === 'parent') {\n referenceElement = parent\n } else if (Util.isElement(this._config.reference)) {\n referenceElement = this._config.reference\n\n // Check if it's jQuery element\n if (typeof this._config.reference.jquery !== 'undefined') {\n referenceElement = this._config.reference[0]\n }\n }\n\n // If boundary is not `scrollParent`, then set position to `static`\n // to allow the menu to \"escape\" the scroll parent's boundaries\n // https://github.com/twbs/bootstrap/issues/24251\n if (this._config.boundary !== 'scrollParent') {\n $(parent).addClass(ClassName.POSITION_STATIC)\n }\n this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig())\n }\n\n // If this is a touch-enabled device we add extra\n // empty mouseover listeners to the body's immediate children;\n // only needed because of broken event delegation on iOS\n // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n if ('ontouchstart' in document.documentElement &&\n $(parent).closest(Selector.NAVBAR_NAV).length === 0) {\n $(document.body).children().on('mouseover', null, $.noop)\n }\n\n this._element.focus()\n this._element.setAttribute('aria-expanded', true)\n\n $(this._menu).toggleClass(ClassName.SHOW)\n $(parent)\n .toggleClass(ClassName.SHOW)\n .trigger($.Event(Event.SHOWN, relatedTarget))\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n $(this._element).off(EVENT_KEY)\n this._element = null\n this._menu = null\n if (this._popper !== null) {\n this._popper.destroy()\n this._popper = null\n }\n }\n\n update() {\n this._inNavbar = this._detectNavbar()\n if (this._popper !== null) {\n this._popper.scheduleUpdate()\n }\n }\n\n // Private\n\n _addEventListeners() {\n $(this._element).on(Event.CLICK, (event) => {\n event.preventDefault()\n event.stopPropagation()\n this.toggle()\n })\n }\n\n _getConfig(config) {\n config = {\n ...this.constructor.Default,\n ...$(this._element).data(),\n ...config\n }\n\n Util.typeCheckConfig(\n NAME,\n config,\n this.constructor.DefaultType\n )\n\n return config\n }\n\n _getMenuElement() {\n if (!this._menu) {\n const parent = Dropdown._getParentFromElement(this._element)\n if (parent) {\n this._menu = parent.querySelector(Selector.MENU)\n }\n }\n return this._menu\n }\n\n _getPlacement() {\n const $parentDropdown = $(this._element.parentNode)\n let placement = AttachmentMap.BOTTOM\n\n // Handle dropup\n if ($parentDropdown.hasClass(ClassName.DROPUP)) {\n placement = AttachmentMap.TOP\n if ($(this._menu).hasClass(ClassName.MENURIGHT)) {\n placement = AttachmentMap.TOPEND\n }\n } else if ($parentDropdown.hasClass(ClassName.DROPRIGHT)) {\n placement = AttachmentMap.RIGHT\n } else if ($parentDropdown.hasClass(ClassName.DROPLEFT)) {\n placement = AttachmentMap.LEFT\n } else if ($(this._menu).hasClass(ClassName.MENURIGHT)) {\n placement = AttachmentMap.BOTTOMEND\n }\n return placement\n }\n\n _detectNavbar() {\n return $(this._element).closest('.navbar').length > 0\n }\n\n _getPopperConfig() {\n const offsetConf = {}\n if (typeof this._config.offset === 'function') {\n offsetConf.fn = (data) => {\n data.offsets = {\n ...data.offsets,\n ...this._config.offset(data.offsets) || {}\n }\n return data\n }\n } else {\n offsetConf.offset = this._config.offset\n }\n\n const popperConfig = {\n placement: this._getPlacement(),\n modifiers: {\n offset: offsetConf,\n flip: {\n enabled: this._config.flip\n },\n preventOverflow: {\n boundariesElement: this._config.boundary\n }\n }\n }\n\n // Disable Popper.js if we have a static display\n if (this._config.display === 'static') {\n popperConfig.modifiers.applyStyle = {\n enabled: false\n }\n }\n return popperConfig\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = typeof config === 'object' ? config : null\n\n if (!data) {\n data = new Dropdown(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config]()\n }\n })\n }\n\n static _clearMenus(event) {\n if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH ||\n event.type === 'keyup' && event.which !== TAB_KEYCODE)) {\n return\n }\n\n const toggles = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE))\n for (let i = 0, len = toggles.length; i < len; i++) {\n const parent = Dropdown._getParentFromElement(toggles[i])\n const context = $(toggles[i]).data(DATA_KEY)\n const relatedTarget = {\n relatedTarget: toggles[i]\n }\n\n if (event && event.type === 'click') {\n relatedTarget.clickEvent = event\n }\n\n if (!context) {\n continue\n }\n\n const dropdownMenu = context._menu\n if (!$(parent).hasClass(ClassName.SHOW)) {\n continue\n }\n\n if (event && (event.type === 'click' &&\n /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) &&\n $.contains(parent, event.target)) {\n continue\n }\n\n const hideEvent = $.Event(Event.HIDE, relatedTarget)\n $(parent).trigger(hideEvent)\n if (hideEvent.isDefaultPrevented()) {\n continue\n }\n\n // If this is a touch-enabled device we remove the extra\n // empty mouseover listeners we added for iOS support\n if ('ontouchstart' in document.documentElement) {\n $(document.body).children().off('mouseover', null, $.noop)\n }\n\n toggles[i].setAttribute('aria-expanded', 'false')\n\n $(dropdownMenu).removeClass(ClassName.SHOW)\n $(parent)\n .removeClass(ClassName.SHOW)\n .trigger($.Event(Event.HIDDEN, relatedTarget))\n }\n }\n\n static _getParentFromElement(element) {\n let parent\n const selector = Util.getSelectorFromElement(element)\n\n if (selector) {\n parent = document.querySelector(selector)\n }\n\n return parent || element.parentNode\n }\n\n // eslint-disable-next-line complexity\n static _dataApiKeydownHandler(event) {\n // If not input/textarea:\n // - And not a key in REGEXP_KEYDOWN => not a dropdown command\n // If input/textarea:\n // - If space key => not a dropdown command\n // - If key is other than escape\n // - If key is not up or down => not a dropdown command\n // - If trigger inside the menu => not a dropdown command\n if (/input|textarea/i.test(event.target.tagName)\n ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE &&\n (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE ||\n $(event.target).closest(Selector.MENU).length) : !REGEXP_KEYDOWN.test(event.which)) {\n return\n }\n\n event.preventDefault()\n event.stopPropagation()\n\n if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {\n return\n }\n\n const parent = Dropdown._getParentFromElement(this)\n const isActive = $(parent).hasClass(ClassName.SHOW)\n\n if (!isActive && (event.which !== ESCAPE_KEYCODE || event.which !== SPACE_KEYCODE) ||\n isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) {\n if (event.which === ESCAPE_KEYCODE) {\n const toggle = parent.querySelector(Selector.DATA_TOGGLE)\n $(toggle).trigger('focus')\n }\n\n $(this).trigger('click')\n return\n }\n\n const items = [].slice.call(parent.querySelectorAll(Selector.VISIBLE_ITEMS))\n\n if (items.length === 0) {\n return\n }\n\n let index = items.indexOf(event.target)\n\n if (event.which === ARROW_UP_KEYCODE && index > 0) { // Up\n index--\n }\n\n if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) { // Down\n index++\n }\n\n if (index < 0) {\n index = 0\n }\n\n items[index].focus()\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document)\n .on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler)\n .on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler)\n .on(`${Event.CLICK_DATA_API} ${Event.KEYUP_DATA_API}`, Dropdown._clearMenus)\n .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n event.preventDefault()\n event.stopPropagation()\n Dropdown._jQueryInterface.call($(this), 'toggle')\n })\n .on(Event.CLICK_DATA_API, Selector.FORM_CHILD, (e) => {\n e.stopPropagation()\n })\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Dropdown._jQueryInterface\n $.fn[NAME].Constructor = Dropdown\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Dropdown._jQueryInterface\n }\n\n return Dropdown\n})($, Popper)\n\nexport default Dropdown\n","import $ from 'jquery'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): modal.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Modal = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'modal'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.modal'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n const ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key\n\n const Default = {\n backdrop : true,\n keyboard : true,\n focus : true,\n show : true\n }\n\n const DefaultType = {\n backdrop : '(boolean|string)',\n keyboard : 'boolean',\n focus : 'boolean',\n show : 'boolean'\n }\n\n const Event = {\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n FOCUSIN : `focusin${EVENT_KEY}`,\n RESIZE : `resize${EVENT_KEY}`,\n CLICK_DISMISS : `click.dismiss${EVENT_KEY}`,\n KEYDOWN_DISMISS : `keydown.dismiss${EVENT_KEY}`,\n MOUSEUP_DISMISS : `mouseup.dismiss${EVENT_KEY}`,\n MOUSEDOWN_DISMISS : `mousedown.dismiss${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n SCROLLBAR_MEASURER : 'modal-scrollbar-measure',\n BACKDROP : 'modal-backdrop',\n OPEN : 'modal-open',\n FADE : 'fade',\n SHOW : 'show'\n }\n\n const Selector = {\n DIALOG : '.modal-dialog',\n DATA_TOGGLE : '[data-toggle=\"modal\"]',\n DATA_DISMISS : '[data-dismiss=\"modal\"]',\n FIXED_CONTENT : '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top',\n STICKY_CONTENT : '.sticky-top'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Modal {\n constructor(element, config) {\n this._config = this._getConfig(config)\n this._element = element\n this._dialog = element.querySelector(Selector.DIALOG)\n this._backdrop = null\n this._isShown = false\n this._isBodyOverflowing = false\n this._ignoreBackdropClick = false\n this._scrollbarWidth = 0\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n toggle(relatedTarget) {\n return this._isShown ? this.hide() : this.show(relatedTarget)\n }\n\n show(relatedTarget) {\n if (this._isTransitioning || this._isShown) {\n return\n }\n\n if ($(this._element).hasClass(ClassName.FADE)) {\n this._isTransitioning = true\n }\n\n const showEvent = $.Event(Event.SHOW, {\n relatedTarget\n })\n\n $(this._element).trigger(showEvent)\n\n if (this._isShown || showEvent.isDefaultPrevented()) {\n return\n }\n\n this._isShown = true\n\n this._checkScrollbar()\n this._setScrollbar()\n\n this._adjustDialog()\n\n $(document.body).addClass(ClassName.OPEN)\n\n this._setEscapeEvent()\n this._setResizeEvent()\n\n $(this._element).on(\n Event.CLICK_DISMISS,\n Selector.DATA_DISMISS,\n (event) => this.hide(event)\n )\n\n $(this._dialog).on(Event.MOUSEDOWN_DISMISS, () => {\n $(this._element).one(Event.MOUSEUP_DISMISS, (event) => {\n if ($(event.target).is(this._element)) {\n this._ignoreBackdropClick = true\n }\n })\n })\n\n this._showBackdrop(() => this._showElement(relatedTarget))\n }\n\n hide(event) {\n if (event) {\n event.preventDefault()\n }\n\n if (this._isTransitioning || !this._isShown) {\n return\n }\n\n const hideEvent = $.Event(Event.HIDE)\n\n $(this._element).trigger(hideEvent)\n\n if (!this._isShown || hideEvent.isDefaultPrevented()) {\n return\n }\n\n this._isShown = false\n const transition = $(this._element).hasClass(ClassName.FADE)\n\n if (transition) {\n this._isTransitioning = true\n }\n\n this._setEscapeEvent()\n this._setResizeEvent()\n\n $(document).off(Event.FOCUSIN)\n\n $(this._element).removeClass(ClassName.SHOW)\n\n $(this._element).off(Event.CLICK_DISMISS)\n $(this._dialog).off(Event.MOUSEDOWN_DISMISS)\n\n\n if (transition) {\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._element)\n .one(Util.TRANSITION_END, (event) => this._hideModal(event))\n .emulateTransitionEnd(transitionDuration)\n } else {\n this._hideModal()\n }\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n\n $(window, document, this._element, this._backdrop).off(EVENT_KEY)\n\n this._config = null\n this._element = null\n this._dialog = null\n this._backdrop = null\n this._isShown = null\n this._isBodyOverflowing = null\n this._ignoreBackdropClick = null\n this._scrollbarWidth = null\n }\n\n handleUpdate() {\n this._adjustDialog()\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...config\n }\n Util.typeCheckConfig(NAME, config, DefaultType)\n return config\n }\n\n _showElement(relatedTarget) {\n const transition = $(this._element).hasClass(ClassName.FADE)\n\n if (!this._element.parentNode ||\n this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {\n // Don't move modal's DOM position\n document.body.appendChild(this._element)\n }\n\n this._element.style.display = 'block'\n this._element.removeAttribute('aria-hidden')\n this._element.scrollTop = 0\n\n if (transition) {\n Util.reflow(this._element)\n }\n\n $(this._element).addClass(ClassName.SHOW)\n\n if (this._config.focus) {\n this._enforceFocus()\n }\n\n const shownEvent = $.Event(Event.SHOWN, {\n relatedTarget\n })\n\n const transitionComplete = () => {\n if (this._config.focus) {\n this._element.focus()\n }\n this._isTransitioning = false\n $(this._element).trigger(shownEvent)\n }\n\n if (transition) {\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._dialog)\n .one(Util.TRANSITION_END, transitionComplete)\n .emulateTransitionEnd(transitionDuration)\n } else {\n transitionComplete()\n }\n }\n\n _enforceFocus() {\n $(document)\n .off(Event.FOCUSIN) // Guard against infinite focus loop\n .on(Event.FOCUSIN, (event) => {\n if (document !== event.target &&\n this._element !== event.target &&\n $(this._element).has(event.target).length === 0) {\n this._element.focus()\n }\n })\n }\n\n _setEscapeEvent() {\n if (this._isShown && this._config.keyboard) {\n $(this._element).on(Event.KEYDOWN_DISMISS, (event) => {\n if (event.which === ESCAPE_KEYCODE) {\n event.preventDefault()\n this.hide()\n }\n })\n } else if (!this._isShown) {\n $(this._element).off(Event.KEYDOWN_DISMISS)\n }\n }\n\n _setResizeEvent() {\n if (this._isShown) {\n $(window).on(Event.RESIZE, (event) => this.handleUpdate(event))\n } else {\n $(window).off(Event.RESIZE)\n }\n }\n\n _hideModal() {\n this._element.style.display = 'none'\n this._element.setAttribute('aria-hidden', true)\n this._isTransitioning = false\n this._showBackdrop(() => {\n $(document.body).removeClass(ClassName.OPEN)\n this._resetAdjustments()\n this._resetScrollbar()\n $(this._element).trigger(Event.HIDDEN)\n })\n }\n\n _removeBackdrop() {\n if (this._backdrop) {\n $(this._backdrop).remove()\n this._backdrop = null\n }\n }\n\n _showBackdrop(callback) {\n const animate = $(this._element).hasClass(ClassName.FADE)\n ? ClassName.FADE : ''\n\n if (this._isShown && this._config.backdrop) {\n this._backdrop = document.createElement('div')\n this._backdrop.className = ClassName.BACKDROP\n\n if (animate) {\n this._backdrop.classList.add(animate)\n }\n\n $(this._backdrop).appendTo(document.body)\n\n $(this._element).on(Event.CLICK_DISMISS, (event) => {\n if (this._ignoreBackdropClick) {\n this._ignoreBackdropClick = false\n return\n }\n if (event.target !== event.currentTarget) {\n return\n }\n if (this._config.backdrop === 'static') {\n this._element.focus()\n } else {\n this.hide()\n }\n })\n\n if (animate) {\n Util.reflow(this._backdrop)\n }\n\n $(this._backdrop).addClass(ClassName.SHOW)\n\n if (!callback) {\n return\n }\n\n if (!animate) {\n callback()\n return\n }\n\n const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop)\n\n $(this._backdrop)\n .one(Util.TRANSITION_END, callback)\n .emulateTransitionEnd(backdropTransitionDuration)\n } else if (!this._isShown && this._backdrop) {\n $(this._backdrop).removeClass(ClassName.SHOW)\n\n const callbackRemove = () => {\n this._removeBackdrop()\n if (callback) {\n callback()\n }\n }\n\n if ($(this._element).hasClass(ClassName.FADE)) {\n const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop)\n\n $(this._backdrop)\n .one(Util.TRANSITION_END, callbackRemove)\n .emulateTransitionEnd(backdropTransitionDuration)\n } else {\n callbackRemove()\n }\n } else if (callback) {\n callback()\n }\n }\n\n // ----------------------------------------------------------------------\n // the following methods are used to handle overflowing modals\n // todo (fat): these should probably be refactored out of modal.js\n // ----------------------------------------------------------------------\n\n _adjustDialog() {\n const isModalOverflowing =\n this._element.scrollHeight > document.documentElement.clientHeight\n\n if (!this._isBodyOverflowing && isModalOverflowing) {\n this._element.style.paddingLeft = `${this._scrollbarWidth}px`\n }\n\n if (this._isBodyOverflowing && !isModalOverflowing) {\n this._element.style.paddingRight = `${this._scrollbarWidth}px`\n }\n }\n\n _resetAdjustments() {\n this._element.style.paddingLeft = ''\n this._element.style.paddingRight = ''\n }\n\n _checkScrollbar() {\n const rect = document.body.getBoundingClientRect()\n this._isBodyOverflowing = rect.left + rect.right < window.innerWidth\n this._scrollbarWidth = this._getScrollbarWidth()\n }\n\n _setScrollbar() {\n if (this._isBodyOverflowing) {\n // Note: DOMNode.style.paddingRight returns the actual value or '' if not set\n // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set\n const fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT))\n const stickyContent = [].slice.call(document.querySelectorAll(Selector.STICKY_CONTENT))\n\n // Adjust fixed content padding\n $(fixedContent).each((index, element) => {\n const actualPadding = element.style.paddingRight\n const calculatedPadding = $(element).css('padding-right')\n $(element)\n .data('padding-right', actualPadding)\n .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`)\n })\n\n // Adjust sticky content margin\n $(stickyContent).each((index, element) => {\n const actualMargin = element.style.marginRight\n const calculatedMargin = $(element).css('margin-right')\n $(element)\n .data('margin-right', actualMargin)\n .css('margin-right', `${parseFloat(calculatedMargin) - this._scrollbarWidth}px`)\n })\n\n // Adjust body padding\n const actualPadding = document.body.style.paddingRight\n const calculatedPadding = $(document.body).css('padding-right')\n $(document.body)\n .data('padding-right', actualPadding)\n .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`)\n }\n }\n\n _resetScrollbar() {\n // Restore fixed content padding\n const fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT))\n $(fixedContent).each((index, element) => {\n const padding = $(element).data('padding-right')\n $(element).removeData('padding-right')\n element.style.paddingRight = padding ? padding : ''\n })\n\n // Restore sticky content\n const elements = [].slice.call(document.querySelectorAll(`${Selector.STICKY_CONTENT}`))\n $(elements).each((index, element) => {\n const margin = $(element).data('margin-right')\n if (typeof margin !== 'undefined') {\n $(element).css('margin-right', margin).removeData('margin-right')\n }\n })\n\n // Restore body padding\n const padding = $(document.body).data('padding-right')\n $(document.body).removeData('padding-right')\n document.body.style.paddingRight = padding ? padding : ''\n }\n\n _getScrollbarWidth() { // thx d.walsh\n const scrollDiv = document.createElement('div')\n scrollDiv.className = ClassName.SCROLLBAR_MEASURER\n document.body.appendChild(scrollDiv)\n const scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth\n document.body.removeChild(scrollDiv)\n return scrollbarWidth\n }\n\n // Static\n\n static _jQueryInterface(config, relatedTarget) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = {\n ...Default,\n ...$(this).data(),\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (!data) {\n data = new Modal(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config](relatedTarget)\n } else if (_config.show) {\n data.show(relatedTarget)\n }\n })\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n let target\n const selector = Util.getSelectorFromElement(this)\n\n if (selector) {\n target = document.querySelector(selector)\n }\n\n const config = $(target).data(DATA_KEY)\n ? 'toggle' : {\n ...$(target).data(),\n ...$(this).data()\n }\n\n if (this.tagName === 'A' || this.tagName === 'AREA') {\n event.preventDefault()\n }\n\n const $target = $(target).one(Event.SHOW, (showEvent) => {\n if (showEvent.isDefaultPrevented()) {\n // Only register focus restorer if modal will actually get shown\n return\n }\n\n $target.one(Event.HIDDEN, () => {\n if ($(this).is(':visible')) {\n this.focus()\n }\n })\n })\n\n Modal._jQueryInterface.call($(target), config, this)\n })\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Modal._jQueryInterface\n $.fn[NAME].Constructor = Modal\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Modal._jQueryInterface\n }\n\n return Modal\n})($)\n\nexport default Modal\n","import $ from 'jquery'\nimport Popper from 'popper.js'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): tooltip.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Tooltip = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'tooltip'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.tooltip'\n const EVENT_KEY = `.${DATA_KEY}`\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n const CLASS_PREFIX = 'bs-tooltip'\n const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\\\s)${CLASS_PREFIX}\\\\S+`, 'g')\n\n const DefaultType = {\n animation : 'boolean',\n template : 'string',\n title : '(string|element|function)',\n trigger : 'string',\n delay : '(number|object)',\n html : 'boolean',\n selector : '(string|boolean)',\n placement : '(string|function)',\n offset : '(number|string)',\n container : '(string|element|boolean)',\n fallbackPlacement : '(string|array)',\n boundary : '(string|element)'\n }\n\n const AttachmentMap = {\n AUTO : 'auto',\n TOP : 'top',\n RIGHT : 'right',\n BOTTOM : 'bottom',\n LEFT : 'left'\n }\n\n const Default = {\n animation : true,\n template : '
    ' +\n '
    ' +\n '
    ',\n trigger : 'hover focus',\n title : '',\n delay : 0,\n html : false,\n selector : false,\n placement : 'top',\n offset : 0,\n container : false,\n fallbackPlacement : 'flip',\n boundary : 'scrollParent'\n }\n\n const HoverState = {\n SHOW : 'show',\n OUT : 'out'\n }\n\n const Event = {\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n INSERTED : `inserted${EVENT_KEY}`,\n CLICK : `click${EVENT_KEY}`,\n FOCUSIN : `focusin${EVENT_KEY}`,\n FOCUSOUT : `focusout${EVENT_KEY}`,\n MOUSEENTER : `mouseenter${EVENT_KEY}`,\n MOUSELEAVE : `mouseleave${EVENT_KEY}`\n }\n\n const ClassName = {\n FADE : 'fade',\n SHOW : 'show'\n }\n\n const Selector = {\n TOOLTIP : '.tooltip',\n TOOLTIP_INNER : '.tooltip-inner',\n ARROW : '.arrow'\n }\n\n const Trigger = {\n HOVER : 'hover',\n FOCUS : 'focus',\n CLICK : 'click',\n MANUAL : 'manual'\n }\n\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Tooltip {\n constructor(element, config) {\n /**\n * Check for Popper dependency\n * Popper - https://popper.js.org\n */\n if (typeof Popper === 'undefined') {\n throw new TypeError('Bootstrap tooltips require Popper.js (https://popper.js.org)')\n }\n\n // private\n this._isEnabled = true\n this._timeout = 0\n this._hoverState = ''\n this._activeTrigger = {}\n this._popper = null\n\n // Protected\n this.element = element\n this.config = this._getConfig(config)\n this.tip = null\n\n this._setListeners()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n static get NAME() {\n return NAME\n }\n\n static get DATA_KEY() {\n return DATA_KEY\n }\n\n static get Event() {\n return Event\n }\n\n static get EVENT_KEY() {\n return EVENT_KEY\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n // Public\n\n enable() {\n this._isEnabled = true\n }\n\n disable() {\n this._isEnabled = false\n }\n\n toggleEnabled() {\n this._isEnabled = !this._isEnabled\n }\n\n toggle(event) {\n if (!this._isEnabled) {\n return\n }\n\n if (event) {\n const dataKey = this.constructor.DATA_KEY\n let context = $(event.currentTarget).data(dataKey)\n\n if (!context) {\n context = new this.constructor(\n event.currentTarget,\n this._getDelegateConfig()\n )\n $(event.currentTarget).data(dataKey, context)\n }\n\n context._activeTrigger.click = !context._activeTrigger.click\n\n if (context._isWithActiveTrigger()) {\n context._enter(null, context)\n } else {\n context._leave(null, context)\n }\n } else {\n if ($(this.getTipElement()).hasClass(ClassName.SHOW)) {\n this._leave(null, this)\n return\n }\n\n this._enter(null, this)\n }\n }\n\n dispose() {\n clearTimeout(this._timeout)\n\n $.removeData(this.element, this.constructor.DATA_KEY)\n\n $(this.element).off(this.constructor.EVENT_KEY)\n $(this.element).closest('.modal').off('hide.bs.modal')\n\n if (this.tip) {\n $(this.tip).remove()\n }\n\n this._isEnabled = null\n this._timeout = null\n this._hoverState = null\n this._activeTrigger = null\n if (this._popper !== null) {\n this._popper.destroy()\n }\n\n this._popper = null\n this.element = null\n this.config = null\n this.tip = null\n }\n\n show() {\n if ($(this.element).css('display') === 'none') {\n throw new Error('Please use show on visible elements')\n }\n\n const showEvent = $.Event(this.constructor.Event.SHOW)\n if (this.isWithContent() && this._isEnabled) {\n $(this.element).trigger(showEvent)\n\n const isInTheDom = $.contains(\n this.element.ownerDocument.documentElement,\n this.element\n )\n\n if (showEvent.isDefaultPrevented() || !isInTheDom) {\n return\n }\n\n const tip = this.getTipElement()\n const tipId = Util.getUID(this.constructor.NAME)\n\n tip.setAttribute('id', tipId)\n this.element.setAttribute('aria-describedby', tipId)\n\n this.setContent()\n\n if (this.config.animation) {\n $(tip).addClass(ClassName.FADE)\n }\n\n const placement = typeof this.config.placement === 'function'\n ? this.config.placement.call(this, tip, this.element)\n : this.config.placement\n\n const attachment = this._getAttachment(placement)\n this.addAttachmentClass(attachment)\n\n const container = this.config.container === false ? document.body : $(document).find(this.config.container)\n\n $(tip).data(this.constructor.DATA_KEY, this)\n\n if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) {\n $(tip).appendTo(container)\n }\n\n $(this.element).trigger(this.constructor.Event.INSERTED)\n\n this._popper = new Popper(this.element, tip, {\n placement: attachment,\n modifiers: {\n offset: {\n offset: this.config.offset\n },\n flip: {\n behavior: this.config.fallbackPlacement\n },\n arrow: {\n element: Selector.ARROW\n },\n preventOverflow: {\n boundariesElement: this.config.boundary\n }\n },\n onCreate: (data) => {\n if (data.originalPlacement !== data.placement) {\n this._handlePopperPlacementChange(data)\n }\n },\n onUpdate: (data) => {\n this._handlePopperPlacementChange(data)\n }\n })\n\n $(tip).addClass(ClassName.SHOW)\n\n // If this is a touch-enabled device we add extra\n // empty mouseover listeners to the body's immediate children;\n // only needed because of broken event delegation on iOS\n // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n if ('ontouchstart' in document.documentElement) {\n $(document.body).children().on('mouseover', null, $.noop)\n }\n\n const complete = () => {\n if (this.config.animation) {\n this._fixTransition()\n }\n const prevHoverState = this._hoverState\n this._hoverState = null\n\n $(this.element).trigger(this.constructor.Event.SHOWN)\n\n if (prevHoverState === HoverState.OUT) {\n this._leave(null, this)\n }\n }\n\n if ($(this.tip).hasClass(ClassName.FADE)) {\n const transitionDuration = Util.getTransitionDurationFromElement(this.tip)\n\n $(this.tip)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n } else {\n complete()\n }\n }\n }\n\n hide(callback) {\n const tip = this.getTipElement()\n const hideEvent = $.Event(this.constructor.Event.HIDE)\n const complete = () => {\n if (this._hoverState !== HoverState.SHOW && tip.parentNode) {\n tip.parentNode.removeChild(tip)\n }\n\n this._cleanTipClass()\n this.element.removeAttribute('aria-describedby')\n $(this.element).trigger(this.constructor.Event.HIDDEN)\n if (this._popper !== null) {\n this._popper.destroy()\n }\n\n if (callback) {\n callback()\n }\n }\n\n $(this.element).trigger(hideEvent)\n\n if (hideEvent.isDefaultPrevented()) {\n return\n }\n\n $(tip).removeClass(ClassName.SHOW)\n\n // If this is a touch-enabled device we remove the extra\n // empty mouseover listeners we added for iOS support\n if ('ontouchstart' in document.documentElement) {\n $(document.body).children().off('mouseover', null, $.noop)\n }\n\n this._activeTrigger[Trigger.CLICK] = false\n this._activeTrigger[Trigger.FOCUS] = false\n this._activeTrigger[Trigger.HOVER] = false\n\n if ($(this.tip).hasClass(ClassName.FADE)) {\n const transitionDuration = Util.getTransitionDurationFromElement(tip)\n\n $(tip)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n } else {\n complete()\n }\n\n this._hoverState = ''\n }\n\n update() {\n if (this._popper !== null) {\n this._popper.scheduleUpdate()\n }\n }\n\n // Protected\n\n isWithContent() {\n return Boolean(this.getTitle())\n }\n\n addAttachmentClass(attachment) {\n $(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`)\n }\n\n getTipElement() {\n this.tip = this.tip || $(this.config.template)[0]\n return this.tip\n }\n\n setContent() {\n const tip = this.getTipElement()\n this.setElementContent($(tip.querySelectorAll(Selector.TOOLTIP_INNER)), this.getTitle())\n $(tip).removeClass(`${ClassName.FADE} ${ClassName.SHOW}`)\n }\n\n setElementContent($element, content) {\n const html = this.config.html\n if (typeof content === 'object' && (content.nodeType || content.jquery)) {\n // Content is a DOM node or a jQuery\n if (html) {\n if (!$(content).parent().is($element)) {\n $element.empty().append(content)\n }\n } else {\n $element.text($(content).text())\n }\n } else {\n $element[html ? 'html' : 'text'](content)\n }\n }\n\n getTitle() {\n let title = this.element.getAttribute('data-original-title')\n\n if (!title) {\n title = typeof this.config.title === 'function'\n ? this.config.title.call(this.element)\n : this.config.title\n }\n\n return title\n }\n\n // Private\n\n _getAttachment(placement) {\n return AttachmentMap[placement.toUpperCase()]\n }\n\n _setListeners() {\n const triggers = this.config.trigger.split(' ')\n\n triggers.forEach((trigger) => {\n if (trigger === 'click') {\n $(this.element).on(\n this.constructor.Event.CLICK,\n this.config.selector,\n (event) => this.toggle(event)\n )\n } else if (trigger !== Trigger.MANUAL) {\n const eventIn = trigger === Trigger.HOVER\n ? this.constructor.Event.MOUSEENTER\n : this.constructor.Event.FOCUSIN\n const eventOut = trigger === Trigger.HOVER\n ? this.constructor.Event.MOUSELEAVE\n : this.constructor.Event.FOCUSOUT\n\n $(this.element)\n .on(\n eventIn,\n this.config.selector,\n (event) => this._enter(event)\n )\n .on(\n eventOut,\n this.config.selector,\n (event) => this._leave(event)\n )\n }\n\n $(this.element).closest('.modal').on(\n 'hide.bs.modal',\n () => this.hide()\n )\n })\n\n if (this.config.selector) {\n this.config = {\n ...this.config,\n trigger: 'manual',\n selector: ''\n }\n } else {\n this._fixTitle()\n }\n }\n\n _fixTitle() {\n const titleType = typeof this.element.getAttribute('data-original-title')\n if (this.element.getAttribute('title') ||\n titleType !== 'string') {\n this.element.setAttribute(\n 'data-original-title',\n this.element.getAttribute('title') || ''\n )\n this.element.setAttribute('title', '')\n }\n }\n\n _enter(event, context) {\n const dataKey = this.constructor.DATA_KEY\n\n context = context || $(event.currentTarget).data(dataKey)\n\n if (!context) {\n context = new this.constructor(\n event.currentTarget,\n this._getDelegateConfig()\n )\n $(event.currentTarget).data(dataKey, context)\n }\n\n if (event) {\n context._activeTrigger[\n event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER\n ] = true\n }\n\n if ($(context.getTipElement()).hasClass(ClassName.SHOW) ||\n context._hoverState === HoverState.SHOW) {\n context._hoverState = HoverState.SHOW\n return\n }\n\n clearTimeout(context._timeout)\n\n context._hoverState = HoverState.SHOW\n\n if (!context.config.delay || !context.config.delay.show) {\n context.show()\n return\n }\n\n context._timeout = setTimeout(() => {\n if (context._hoverState === HoverState.SHOW) {\n context.show()\n }\n }, context.config.delay.show)\n }\n\n _leave(event, context) {\n const dataKey = this.constructor.DATA_KEY\n\n context = context || $(event.currentTarget).data(dataKey)\n\n if (!context) {\n context = new this.constructor(\n event.currentTarget,\n this._getDelegateConfig()\n )\n $(event.currentTarget).data(dataKey, context)\n }\n\n if (event) {\n context._activeTrigger[\n event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER\n ] = false\n }\n\n if (context._isWithActiveTrigger()) {\n return\n }\n\n clearTimeout(context._timeout)\n\n context._hoverState = HoverState.OUT\n\n if (!context.config.delay || !context.config.delay.hide) {\n context.hide()\n return\n }\n\n context._timeout = setTimeout(() => {\n if (context._hoverState === HoverState.OUT) {\n context.hide()\n }\n }, context.config.delay.hide)\n }\n\n _isWithActiveTrigger() {\n for (const trigger in this._activeTrigger) {\n if (this._activeTrigger[trigger]) {\n return true\n }\n }\n\n return false\n }\n\n _getConfig(config) {\n config = {\n ...this.constructor.Default,\n ...$(this.element).data(),\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (typeof config.delay === 'number') {\n config.delay = {\n show: config.delay,\n hide: config.delay\n }\n }\n\n if (typeof config.title === 'number') {\n config.title = config.title.toString()\n }\n\n if (typeof config.content === 'number') {\n config.content = config.content.toString()\n }\n\n Util.typeCheckConfig(\n NAME,\n config,\n this.constructor.DefaultType\n )\n\n return config\n }\n\n _getDelegateConfig() {\n const config = {}\n\n if (this.config) {\n for (const key in this.config) {\n if (this.constructor.Default[key] !== this.config[key]) {\n config[key] = this.config[key]\n }\n }\n }\n\n return config\n }\n\n _cleanTipClass() {\n const $tip = $(this.getTipElement())\n const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX)\n if (tabClass !== null && tabClass.length) {\n $tip.removeClass(tabClass.join(''))\n }\n }\n\n _handlePopperPlacementChange(popperData) {\n const popperInstance = popperData.instance\n this.tip = popperInstance.popper\n this._cleanTipClass()\n this.addAttachmentClass(this._getAttachment(popperData.placement))\n }\n\n _fixTransition() {\n const tip = this.getTipElement()\n const initConfigAnimation = this.config.animation\n if (tip.getAttribute('x-placement') !== null) {\n return\n }\n $(tip).removeClass(ClassName.FADE)\n this.config.animation = false\n this.hide()\n this.show()\n this.config.animation = initConfigAnimation\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = typeof config === 'object' && config\n\n if (!data && /dispose|hide/.test(config)) {\n return\n }\n\n if (!data) {\n data = new Tooltip(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config]()\n }\n })\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Tooltip._jQueryInterface\n $.fn[NAME].Constructor = Tooltip\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Tooltip._jQueryInterface\n }\n\n return Tooltip\n})($, Popper)\n\nexport default Tooltip\n","import $ from 'jquery'\nimport Tooltip from './tooltip'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): popover.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Popover = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'popover'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.popover'\n const EVENT_KEY = `.${DATA_KEY}`\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n const CLASS_PREFIX = 'bs-popover'\n const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\\\s)${CLASS_PREFIX}\\\\S+`, 'g')\n\n const Default = {\n ...Tooltip.Default,\n placement : 'right',\n trigger : 'click',\n content : '',\n template : '
    ' +\n '
    ' +\n '

    ' +\n '
    '\n }\n\n const DefaultType = {\n ...Tooltip.DefaultType,\n content : '(string|element|function)'\n }\n\n const ClassName = {\n FADE : 'fade',\n SHOW : 'show'\n }\n\n const Selector = {\n TITLE : '.popover-header',\n CONTENT : '.popover-body'\n }\n\n const Event = {\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n INSERTED : `inserted${EVENT_KEY}`,\n CLICK : `click${EVENT_KEY}`,\n FOCUSIN : `focusin${EVENT_KEY}`,\n FOCUSOUT : `focusout${EVENT_KEY}`,\n MOUSEENTER : `mouseenter${EVENT_KEY}`,\n MOUSELEAVE : `mouseleave${EVENT_KEY}`\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Popover extends Tooltip {\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n static get NAME() {\n return NAME\n }\n\n static get DATA_KEY() {\n return DATA_KEY\n }\n\n static get Event() {\n return Event\n }\n\n static get EVENT_KEY() {\n return EVENT_KEY\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n // Overrides\n\n isWithContent() {\n return this.getTitle() || this._getContent()\n }\n\n addAttachmentClass(attachment) {\n $(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`)\n }\n\n getTipElement() {\n this.tip = this.tip || $(this.config.template)[0]\n return this.tip\n }\n\n setContent() {\n const $tip = $(this.getTipElement())\n\n // We use append for html objects to maintain js events\n this.setElementContent($tip.find(Selector.TITLE), this.getTitle())\n let content = this._getContent()\n if (typeof content === 'function') {\n content = content.call(this.element)\n }\n this.setElementContent($tip.find(Selector.CONTENT), content)\n\n $tip.removeClass(`${ClassName.FADE} ${ClassName.SHOW}`)\n }\n\n // Private\n\n _getContent() {\n return this.element.getAttribute('data-content') ||\n this.config.content\n }\n\n _cleanTipClass() {\n const $tip = $(this.getTipElement())\n const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX)\n if (tabClass !== null && tabClass.length > 0) {\n $tip.removeClass(tabClass.join(''))\n }\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = typeof config === 'object' ? config : null\n\n if (!data && /destroy|hide/.test(config)) {\n return\n }\n\n if (!data) {\n data = new Popover(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config]()\n }\n })\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Popover._jQueryInterface\n $.fn[NAME].Constructor = Popover\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Popover._jQueryInterface\n }\n\n return Popover\n})($)\n\nexport default Popover\n","import $ from 'jquery'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): scrollspy.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst ScrollSpy = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'scrollspy'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.scrollspy'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n\n const Default = {\n offset : 10,\n method : 'auto',\n target : ''\n }\n\n const DefaultType = {\n offset : 'number',\n method : 'string',\n target : '(string|element)'\n }\n\n const Event = {\n ACTIVATE : `activate${EVENT_KEY}`,\n SCROLL : `scroll${EVENT_KEY}`,\n LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n DROPDOWN_ITEM : 'dropdown-item',\n DROPDOWN_MENU : 'dropdown-menu',\n ACTIVE : 'active'\n }\n\n const Selector = {\n DATA_SPY : '[data-spy=\"scroll\"]',\n ACTIVE : '.active',\n NAV_LIST_GROUP : '.nav, .list-group',\n NAV_LINKS : '.nav-link',\n NAV_ITEMS : '.nav-item',\n LIST_ITEMS : '.list-group-item',\n DROPDOWN : '.dropdown',\n DROPDOWN_ITEMS : '.dropdown-item',\n DROPDOWN_TOGGLE : '.dropdown-toggle'\n }\n\n const OffsetMethod = {\n OFFSET : 'offset',\n POSITION : 'position'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class ScrollSpy {\n constructor(element, config) {\n this._element = element\n this._scrollElement = element.tagName === 'BODY' ? window : element\n this._config = this._getConfig(config)\n this._selector = `${this._config.target} ${Selector.NAV_LINKS},` +\n `${this._config.target} ${Selector.LIST_ITEMS},` +\n `${this._config.target} ${Selector.DROPDOWN_ITEMS}`\n this._offsets = []\n this._targets = []\n this._activeTarget = null\n this._scrollHeight = 0\n\n $(this._scrollElement).on(Event.SCROLL, (event) => this._process(event))\n\n this.refresh()\n this._process()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n refresh() {\n const autoMethod = this._scrollElement === this._scrollElement.window\n ? OffsetMethod.OFFSET : OffsetMethod.POSITION\n\n const offsetMethod = this._config.method === 'auto'\n ? autoMethod : this._config.method\n\n const offsetBase = offsetMethod === OffsetMethod.POSITION\n ? this._getScrollTop() : 0\n\n this._offsets = []\n this._targets = []\n\n this._scrollHeight = this._getScrollHeight()\n\n const targets = [].slice.call(document.querySelectorAll(this._selector))\n\n targets\n .map((element) => {\n let target\n const targetSelector = Util.getSelectorFromElement(element)\n\n if (targetSelector) {\n target = document.querySelector(targetSelector)\n }\n\n if (target) {\n const targetBCR = target.getBoundingClientRect()\n if (targetBCR.width || targetBCR.height) {\n // TODO (fat): remove sketch reliance on jQuery position/offset\n return [\n $(target)[offsetMethod]().top + offsetBase,\n targetSelector\n ]\n }\n }\n return null\n })\n .filter((item) => item)\n .sort((a, b) => a[0] - b[0])\n .forEach((item) => {\n this._offsets.push(item[0])\n this._targets.push(item[1])\n })\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n $(this._scrollElement).off(EVENT_KEY)\n\n this._element = null\n this._scrollElement = null\n this._config = null\n this._selector = null\n this._offsets = null\n this._targets = null\n this._activeTarget = null\n this._scrollHeight = null\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (typeof config.target !== 'string') {\n let id = $(config.target).attr('id')\n if (!id) {\n id = Util.getUID(NAME)\n $(config.target).attr('id', id)\n }\n config.target = `#${id}`\n }\n\n Util.typeCheckConfig(NAME, config, DefaultType)\n\n return config\n }\n\n _getScrollTop() {\n return this._scrollElement === window\n ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop\n }\n\n _getScrollHeight() {\n return this._scrollElement.scrollHeight || Math.max(\n document.body.scrollHeight,\n document.documentElement.scrollHeight\n )\n }\n\n _getOffsetHeight() {\n return this._scrollElement === window\n ? window.innerHeight : this._scrollElement.getBoundingClientRect().height\n }\n\n _process() {\n const scrollTop = this._getScrollTop() + this._config.offset\n const scrollHeight = this._getScrollHeight()\n const maxScroll = this._config.offset +\n scrollHeight -\n this._getOffsetHeight()\n\n if (this._scrollHeight !== scrollHeight) {\n this.refresh()\n }\n\n if (scrollTop >= maxScroll) {\n const target = this._targets[this._targets.length - 1]\n\n if (this._activeTarget !== target) {\n this._activate(target)\n }\n return\n }\n\n if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {\n this._activeTarget = null\n this._clear()\n return\n }\n\n const offsetLength = this._offsets.length\n for (let i = offsetLength; i--;) {\n const isActiveTarget = this._activeTarget !== this._targets[i] &&\n scrollTop >= this._offsets[i] &&\n (typeof this._offsets[i + 1] === 'undefined' ||\n scrollTop < this._offsets[i + 1])\n\n if (isActiveTarget) {\n this._activate(this._targets[i])\n }\n }\n }\n\n _activate(target) {\n this._activeTarget = target\n\n this._clear()\n\n let queries = this._selector.split(',')\n // eslint-disable-next-line arrow-body-style\n queries = queries.map((selector) => {\n return `${selector}[data-target=\"${target}\"],` +\n `${selector}[href=\"${target}\"]`\n })\n\n const $link = $([].slice.call(document.querySelectorAll(queries.join(','))))\n\n if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {\n $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE)\n $link.addClass(ClassName.ACTIVE)\n } else {\n // Set triggered link as active\n $link.addClass(ClassName.ACTIVE)\n // Set triggered links parents as active\n // With both

  7. - Edit + Edit