julija1110 před 3 roky
rodič
revize
f54072bb5b
100 změnil soubory, kde provedl 12435 přidání a 0 odebrání
  1. 13
    0
      MVCTemplate.Business/Dtos/BaseDto.cs
  2. 33
    0
      MVCTemplate.Business/Infrastructure/Extensions/StartupExtensions.cs
  3. 18
    0
      MVCTemplate.Business/Infrastructure/MapperProfile.cs
  4. 13
    0
      MVCTemplate.Business/Infrastructure/Settings/EmailSettings.cs
  5. 29
    0
      MVCTemplate.Business/Infrastructure/StartupConfiguration.cs
  6. 25
    0
      MVCTemplate.Business/MVCTemplate.Business.csproj
  7. 13
    0
      MVCTemplate.Data/Data/BaseEntity.cs
  8. 20
    0
      MVCTemplate.Data/DbContexts/AppDbContext.cs
  9. 26
    0
      MVCTemplate.Data/Extensions/StartupExtensions.cs
  10. 21
    0
      MVCTemplate.Data/MVCTemplate.Data.csproj
  11. 277
    0
      MVCTemplate.Data/Migrations/20220906133332_init.Designer.cs
  12. 219
    0
      MVCTemplate.Data/Migrations/20220906133332_init.cs
  13. 44
    0
      MVCTemplate.sln
  14. 12
    0
      MVCTemplate/.config/dotnet-tools.json
  15. 21
    0
      MVCTemplate/Areas/Identity/IdentityHostingStartup.cs
  16. 85
    0
      MVCTemplate/Areas/Identity/Pages/Account/Login.cshtml
  17. 110
    0
      MVCTemplate/Areas/Identity/Pages/Account/Login.cshtml.cs
  18. 67
    0
      MVCTemplate/Areas/Identity/Pages/Account/Register.cshtml
  19. 114
    0
      MVCTemplate/Areas/Identity/Pages/Account/Register.cshtml.cs
  20. 37
    0
      MVCTemplate/Areas/Identity/Pages/Account/ResetPassword.cshtml
  21. 91
    0
      MVCTemplate/Areas/Identity/Pages/Account/ResetPassword.cshtml.cs
  22. 1
    0
      MVCTemplate/Areas/Identity/Pages/Account/_ViewImports.cshtml
  23. 18
    0
      MVCTemplate/Areas/Identity/Pages/_ValidationScriptsPartial.cshtml
  24. 4
    0
      MVCTemplate/Areas/Identity/Pages/_ViewImports.cshtml
  25. 4
    0
      MVCTemplate/Areas/Identity/Pages/_ViewStart.cshtml
  26. 41
    0
      MVCTemplate/Controllers/HomeController.cs
  27. 11
    0
      MVCTemplate/Infrastructure/IModelFactory.cs
  28. 66
    0
      MVCTemplate/Infrastructure/Middleware/ExceptionHandlingMiddleware.cs
  29. 36
    0
      MVCTemplate/MVCTemplate.csproj
  30. 11
    0
      MVCTemplate/Models/ErrorViewModel.cs
  31. 26
    0
      MVCTemplate/Program.cs
  32. 30
    0
      MVCTemplate/Properties/launchSettings.json
  33. 3
    0
      MVCTemplate/ScaffoldingReadMe.txt
  34. 70
    0
      MVCTemplate/Startup.cs
  35. 3
    0
      MVCTemplate/Views/Home/Index.cshtml
  36. 6
    0
      MVCTemplate/Views/Home/Privacy.cshtml
  37. 25
    0
      MVCTemplate/Views/Shared/Error.cshtml
  38. 111
    0
      MVCTemplate/Views/Shared/_Layout.cshtml
  39. 264
    0
      MVCTemplate/Views/Shared/_LayoutAdmin.cshtml
  40. 28
    0
      MVCTemplate/Views/Shared/_LoginPartial.cshtml
  41. 2
    0
      MVCTemplate/Views/Shared/_ValidationScriptsPartial.cshtml
  42. 3
    0
      MVCTemplate/Views/_ViewImports.cshtml
  43. 3
    0
      MVCTemplate/Views/_ViewStart.cshtml
  44. 9
    0
      MVCTemplate/appsettings.Development.json
  45. 16
    0
      MVCTemplate/appsettings.json
  46. 14
    0
      MVCTemplate/wwwroot/build/config/.eslintrc.json
  47. 17
    0
      MVCTemplate/wwwroot/build/config/postcss.config.js
  48. 32
    0
      MVCTemplate/wwwroot/build/config/rollup.config.js
  49. 33
    0
      MVCTemplate/wwwroot/build/js/AdminLTE.js
  50. 153
    0
      MVCTemplate/wwwroot/build/js/CardRefresh.js
  51. 238
    0
      MVCTemplate/wwwroot/build/js/CardWidget.js
  52. 322
    0
      MVCTemplate/wwwroot/build/js/ControlSidebar.js
  53. 84
    0
      MVCTemplate/wwwroot/build/js/DirectChat.js
  54. 146
    0
      MVCTemplate/wwwroot/build/js/Dropdown.js
  55. 116
    0
      MVCTemplate/wwwroot/build/js/ExpandableTable.js
  56. 117
    0
      MVCTemplate/wwwroot/build/js/Fullscreen.js
  57. 413
    0
      MVCTemplate/wwwroot/build/js/IFrame.js
  58. 257
    0
      MVCTemplate/wwwroot/build/js/Layout.js
  59. 113
    0
      MVCTemplate/wwwroot/build/js/NavbarSearch.js
  60. 223
    0
      MVCTemplate/wwwroot/build/js/PushMenu.js
  61. 298
    0
      MVCTemplate/wwwroot/build/js/SidebarSearch.js
  62. 209
    0
      MVCTemplate/wwwroot/build/js/Toasts.js
  63. 118
    0
      MVCTemplate/wwwroot/build/js/TodoList.js
  64. 175
    0
      MVCTemplate/wwwroot/build/js/Treeview.js
  65. 14
    0
      MVCTemplate/wwwroot/build/npm/.eslintrc.json
  66. 48
    0
      MVCTemplate/wwwroot/build/npm/DocsPlugins.js
  67. 58
    0
      MVCTemplate/wwwroot/build/npm/DocsPublish.js
  68. 449
    0
      MVCTemplate/wwwroot/build/npm/Plugins.js
  69. 59
    0
      MVCTemplate/wwwroot/build/npm/Publish.js
  70. 55
    0
      MVCTemplate/wwwroot/build/npm/vnu-jar.js
  71. 30
    0
      MVCTemplate/wwwroot/build/scss/_adminlte.raw.scss
  72. 52
    0
      MVCTemplate/wwwroot/build/scss/_alerts.scss
  73. 14
    0
      MVCTemplate/wwwroot/build/scss/_animation-effects.scss
  74. 911
    0
      MVCTemplate/wwwroot/build/scss/_bootstrap-variables.scss
  75. 106
    0
      MVCTemplate/wwwroot/build/scss/_brand.scss
  76. 154
    0
      MVCTemplate/wwwroot/build/scss/_buttons.scss
  77. 73
    0
      MVCTemplate/wwwroot/build/scss/_callout.scss
  78. 545
    0
      MVCTemplate/wwwroot/build/scss/_cards.scss
  79. 28
    0
      MVCTemplate/wwwroot/build/scss/_carousel.scss
  80. 44
    0
      MVCTemplate/wwwroot/build/scss/_close.scss
  81. 144
    0
      MVCTemplate/wwwroot/build/scss/_colors.scss
  82. 173
    0
      MVCTemplate/wwwroot/build/scss/_control-sidebar.scss
  83. 259
    0
      MVCTemplate/wwwroot/build/scss/_direct-chat.scss
  84. 295
    0
      MVCTemplate/wwwroot/build/scss/_dropdown.scss
  85. 14
    0
      MVCTemplate/wwwroot/build/scss/_elevation.scss
  86. 431
    0
      MVCTemplate/wwwroot/build/scss/_forms.scss
  87. 165
    0
      MVCTemplate/wwwroot/build/scss/_info-box.scss
  88. 704
    0
      MVCTemplate/wwwroot/build/scss/_layout.scss
  89. 179
    0
      MVCTemplate/wwwroot/build/scss/_main-header.scss
  90. 1176
    0
      MVCTemplate/wwwroot/build/scss/_main-sidebar.scss
  91. 541
    0
      MVCTemplate/wwwroot/build/scss/_miscellaneous.scss
  92. 15
    0
      MVCTemplate/wwwroot/build/scss/_mixins.scss
  93. 76
    0
      MVCTemplate/wwwroot/build/scss/_modals.scss
  94. 168
    0
      MVCTemplate/wwwroot/build/scss/_navs.scss
  95. 82
    0
      MVCTemplate/wwwroot/build/scss/_pagination.scss
  96. 24
    0
      MVCTemplate/wwwroot/build/scss/_preloader.scss
  97. 52
    0
      MVCTemplate/wwwroot/build/scss/_print.scss
  98. 68
    0
      MVCTemplate/wwwroot/build/scss/_products.scss
  99. 72
    0
      MVCTemplate/wwwroot/build/scss/_progress-bars.scss
  100. 0
    0
      MVCTemplate/wwwroot/build/scss/_root.scss

+ 13
- 0
MVCTemplate.Business/Dtos/BaseDto.cs Zobrazit soubor

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MVCTemplate.Business.Dtos
{
public class BaseDto
{
public int Id { get; set; }
}
}

+ 33
- 0
MVCTemplate.Business/Infrastructure/Extensions/StartupExtensions.cs Zobrazit soubor

@@ -0,0 +1,33 @@
using AutoMapper;
using Microsoft.Extensions.DependencyInjection;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MVCTemplate.Business.Infrastructure.Extensions
{
public class StartupExtensions
{
public static void ConfigureServices(IServiceCollection services)
{
Data.Extensions.StartupExtensions.ConfigureServices(services);


// TODO: add all missing services

var mapperConfiguration = new MapperConfiguration(mc =>
{
mc.AddProfile(new MapperProfile());
});

IMapper mapper = mapperConfiguration.CreateMapper();
services.AddSingleton(mapper);

//services.AddLocalization(options => options.ResourcesPath = "Infrastructure/Resources");

}
}
}

+ 18
- 0
MVCTemplate.Business/Infrastructure/MapperProfile.cs Zobrazit soubor

@@ -0,0 +1,18 @@
using AutoMapper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MVCTemplate.Data.Data;
using MVCTemplate.Business.Dtos;

namespace MVCTemplate.Business.Infrastructure
{
public class MapperProfile : Profile
{
public MapperProfile()
{
}
}
}

+ 13
- 0
MVCTemplate.Business/Infrastructure/Settings/EmailSettings.cs Zobrazit soubor

@@ -0,0 +1,13 @@
namespace MVCTemplate.Business.Infrastructure.Settings
{
public class EmailSettings
{
public string SmtpServer { get; set; }
public int SmtpPort { get; set; }
public bool SmtpUseSSL { get; set; }
public string SmtpUsername { get; set; }
public string SmtpPassword { get; set; }
public string SmtpFrom { get; set; }
public string SmtpFromName { get; set; }
}
}

+ 29
- 0
MVCTemplate.Business/Infrastructure/StartupConfiguration.cs Zobrazit soubor

@@ -0,0 +1,29 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;

namespace MVCTemplate.Business.Infrastructure
{
public class StartupConfiguration
{
public static TConfig ConfigureStartupConfig<TConfig>(IServiceCollection services, IConfiguration configuration) where TConfig : class, new()
{
if (services == null)
throw new ArgumentNullException(nameof(services));

if (configuration == null)
throw new ArgumentNullException(nameof(configuration));

//create instance of config
var config = new TConfig();
var classType = typeof(TConfig);
//bind it to the appropriate section of configuration
configuration.Bind(classType.Name, config);

//and register it as a service
services.AddSingleton(config);

return config;
}
}
}

+ 25
- 0
MVCTemplate.Business/MVCTemplate.Business.csproj Zobrazit soubor

@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AutoMapper" Version="11.0.1" />
<PackageReference Include="MailKit" Version="2.13.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Google" Version="5.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.7" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="5.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\MVCTemplate.Data\MVCTemplate.Data.csproj" />
</ItemGroup>

<ItemGroup>
<Folder Include="Interfaces\" />
<Folder Include="Services\" />
</ItemGroup>

</Project>

+ 13
- 0
MVCTemplate.Data/Data/BaseEntity.cs Zobrazit soubor

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MVCTemplate.Data.Data
{
public class BaseEntity
{
public int Id { get; set; }
}
}

+ 20
- 0
MVCTemplate.Data/DbContexts/AppDbContext.cs Zobrazit soubor

@@ -0,0 +1,20 @@
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;

using MVCTemplate.Data.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MVCTemplate.Data.DbContexts
{
public class AppDbContext : IdentityDbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }



}
}

+ 26
- 0
MVCTemplate.Data/Extensions/StartupExtensions.cs Zobrazit soubor

@@ -0,0 +1,26 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MVCTemplate.Data.DbContexts;
using Microsoft.AspNetCore.Identity;

namespace MVCTemplate.Data.Extensions
{
public class StartupExtensions
{
public static void ConfigureServices(IServiceCollection services)
{
var configuration = new ConfigurationBuilder()
.AddJsonFile(path: "appsettings.json")
.Build();
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(
configuration.GetConnectionString("DefaultConnection")));
}
}
}

+ 21
- 0
MVCTemplate.Data/MVCTemplate.Data.csproj Zobrazit soubor

@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AutoMapper" Version="11.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Google" Version="5.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" />
</ItemGroup>

</Project>

+ 277
- 0
MVCTemplate.Data/Migrations/20220906133332_init.Designer.cs Zobrazit soubor

@@ -0,0 +1,277 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using MVCTemplate.Data.DbContexts;

namespace MVCTemplate.Data.Migrations
{
[DbContext(typeof(AppDbContext))]
[Migration("20220906133332_init")]
partial class init
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("ProductVersion", "5.0.7")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);

modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");

b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");

b.Property<string>("Name")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");

b.Property<string>("NormalizedName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");

b.HasKey("Id");

b.HasIndex("NormalizedName")
.IsUnique()
.HasDatabaseName("RoleNameIndex")
.HasFilter("[NormalizedName] IS NOT NULL");

b.ToTable("AspNetRoles");
});

modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);

b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");

b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");

b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("nvarchar(450)");

b.HasKey("Id");

b.HasIndex("RoleId");

b.ToTable("AspNetRoleClaims");
});

modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b =>
{
b.Property<string>("Id")
.HasColumnType("nvarchar(450)");

b.Property<int>("AccessFailedCount")
.HasColumnType("int");

b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("nvarchar(max)");

b.Property<string>("Email")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");

b.Property<bool>("EmailConfirmed")
.HasColumnType("bit");

b.Property<bool>("LockoutEnabled")
.HasColumnType("bit");

b.Property<DateTimeOffset?>("LockoutEnd")
.HasColumnType("datetimeoffset");

b.Property<string>("NormalizedEmail")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");

b.Property<string>("NormalizedUserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");

b.Property<string>("PasswordHash")
.HasColumnType("nvarchar(max)");

b.Property<string>("PhoneNumber")
.HasColumnType("nvarchar(max)");

b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("bit");

b.Property<string>("SecurityStamp")
.HasColumnType("nvarchar(max)");

b.Property<bool>("TwoFactorEnabled")
.HasColumnType("bit");

b.Property<string>("UserName")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");

b.HasKey("Id");

b.HasIndex("NormalizedEmail")
.HasDatabaseName("EmailIndex");

b.HasIndex("NormalizedUserName")
.IsUnique()
.HasDatabaseName("UserNameIndex")
.HasFilter("[NormalizedUserName] IS NOT NULL");

b.ToTable("AspNetUsers");
});

modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);

b.Property<string>("ClaimType")
.HasColumnType("nvarchar(max)");

b.Property<string>("ClaimValue")
.HasColumnType("nvarchar(max)");

b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");

b.HasKey("Id");

b.HasIndex("UserId");

b.ToTable("AspNetUserClaims");
});

modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");

b.Property<string>("ProviderKey")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");

b.Property<string>("ProviderDisplayName")
.HasColumnType("nvarchar(max)");

b.Property<string>("UserId")
.IsRequired()
.HasColumnType("nvarchar(450)");

b.HasKey("LoginProvider", "ProviderKey");

b.HasIndex("UserId");

b.ToTable("AspNetUserLogins");
});

modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");

b.Property<string>("RoleId")
.HasColumnType("nvarchar(450)");

b.HasKey("UserId", "RoleId");

b.HasIndex("RoleId");

b.ToTable("AspNetUserRoles");
});

modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("nvarchar(450)");

b.Property<string>("LoginProvider")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");

b.Property<string>("Name")
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");

b.Property<string>("Value")
.HasColumnType("nvarchar(max)");

b.HasKey("UserId", "LoginProvider", "Name");

b.ToTable("AspNetUserTokens");
});

modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});

modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});

modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});

modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();

b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});

modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
#pragma warning restore 612, 618
}
}
}

+ 219
- 0
MVCTemplate.Data/Migrations/20220906133332_init.cs Zobrazit soubor

@@ -0,0 +1,219 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;

namespace MVCTemplate.Data.Migrations
{
public partial class init : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AspNetRoles",
columns: table => new
{
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
Name = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
NormalizedName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
});

migrationBuilder.CreateTable(
name: "AspNetUsers",
columns: table => new
{
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
UserName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
NormalizedUserName = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
Email = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
NormalizedEmail = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
EmailConfirmed = table.Column<bool>(type: "bit", nullable: false),
PasswordHash = table.Column<string>(type: "nvarchar(max)", nullable: true),
SecurityStamp = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(max)", nullable: true),
PhoneNumber = table.Column<string>(type: "nvarchar(max)", nullable: true),
PhoneNumberConfirmed = table.Column<bool>(type: "bit", nullable: false),
TwoFactorEnabled = table.Column<bool>(type: "bit", nullable: false),
LockoutEnd = table.Column<DateTimeOffset>(type: "datetimeoffset", nullable: true),
LockoutEnabled = table.Column<bool>(type: "bit", nullable: false),
AccessFailedCount = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
});

migrationBuilder.CreateTable(
name: "AspNetRoleClaims",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
RoleId = table.Column<string>(type: "nvarchar(450)", nullable: false),
ClaimType = table.Column<string>(type: "nvarchar(max)", nullable: true),
ClaimValue = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});

migrationBuilder.CreateTable(
name: "AspNetUserClaims",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false),
ClaimType = table.Column<string>(type: "nvarchar(max)", nullable: true),
ClaimValue = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetUserClaims_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});

migrationBuilder.CreateTable(
name: "AspNetUserLogins",
columns: table => new
{
LoginProvider = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
ProviderKey = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
ProviderDisplayName = table.Column<string>(type: "nvarchar(max)", nullable: true),
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
table.ForeignKey(
name: "FK_AspNetUserLogins_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});

migrationBuilder.CreateTable(
name: "AspNetUserRoles",
columns: table => new
{
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false),
RoleId = table.Column<string>(type: "nvarchar(450)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});

migrationBuilder.CreateTable(
name: "AspNetUserTokens",
columns: table => new
{
UserId = table.Column<string>(type: "nvarchar(450)", nullable: false),
LoginProvider = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
Value = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
table.ForeignKey(
name: "FK_AspNetUserTokens_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});

migrationBuilder.CreateIndex(
name: "IX_AspNetRoleClaims_RoleId",
table: "AspNetRoleClaims",
column: "RoleId");

migrationBuilder.CreateIndex(
name: "RoleNameIndex",
table: "AspNetRoles",
column: "NormalizedName",
unique: true,
filter: "[NormalizedName] IS NOT NULL");

migrationBuilder.CreateIndex(
name: "IX_AspNetUserClaims_UserId",
table: "AspNetUserClaims",
column: "UserId");

migrationBuilder.CreateIndex(
name: "IX_AspNetUserLogins_UserId",
table: "AspNetUserLogins",
column: "UserId");

migrationBuilder.CreateIndex(
name: "IX_AspNetUserRoles_RoleId",
table: "AspNetUserRoles",
column: "RoleId");

migrationBuilder.CreateIndex(
name: "EmailIndex",
table: "AspNetUsers",
column: "NormalizedEmail");

migrationBuilder.CreateIndex(
name: "UserNameIndex",
table: "AspNetUsers",
column: "NormalizedUserName",
unique: true,
filter: "[NormalizedUserName] IS NOT NULL");
}

protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AspNetRoleClaims");

migrationBuilder.DropTable(
name: "AspNetUserClaims");

migrationBuilder.DropTable(
name: "AspNetUserLogins");

migrationBuilder.DropTable(
name: "AspNetUserRoles");

migrationBuilder.DropTable(
name: "AspNetUserTokens");

migrationBuilder.DropTable(
name: "AspNetRoles");

migrationBuilder.DropTable(
name: "AspNetUsers");
}
}
}

+ 44
- 0
MVCTemplate.sln Zobrazit soubor

@@ -0,0 +1,44 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31321.278
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVCTemplate", "MVCTemplate\MVCTemplate.csproj", "{495FB586-0B0F-4368-87A3-C13444149D2A}"
ProjectSection(ProjectDependencies) = postProject
{941012BA-66F3-4B72-A735-CC199A3E4E7D} = {941012BA-66F3-4B72-A735-CC199A3E4E7D}
{263779FB-D285-44F3-BE46-81E019A17610} = {263779FB-D285-44F3-BE46-81E019A17610}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVCTemplate.Business", "MVCTemplate.Business\MVCTemplate.Business.csproj", "{263779FB-D285-44F3-BE46-81E019A17610}"
ProjectSection(ProjectDependencies) = postProject
{941012BA-66F3-4B72-A735-CC199A3E4E7D} = {941012BA-66F3-4B72-A735-CC199A3E4E7D}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVCTemplate.Data", "MVCTemplate.Data\MVCTemplate.Data.csproj", "{941012BA-66F3-4B72-A735-CC199A3E4E7D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{495FB586-0B0F-4368-87A3-C13444149D2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{495FB586-0B0F-4368-87A3-C13444149D2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{495FB586-0B0F-4368-87A3-C13444149D2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{495FB586-0B0F-4368-87A3-C13444149D2A}.Release|Any CPU.Build.0 = Release|Any CPU
{263779FB-D285-44F3-BE46-81E019A17610}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{263779FB-D285-44F3-BE46-81E019A17610}.Debug|Any CPU.Build.0 = Debug|Any CPU
{263779FB-D285-44F3-BE46-81E019A17610}.Release|Any CPU.ActiveCfg = Release|Any CPU
{263779FB-D285-44F3-BE46-81E019A17610}.Release|Any CPU.Build.0 = Release|Any CPU
{941012BA-66F3-4B72-A735-CC199A3E4E7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{941012BA-66F3-4B72-A735-CC199A3E4E7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{941012BA-66F3-4B72-A735-CC199A3E4E7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{941012BA-66F3-4B72-A735-CC199A3E4E7D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8D821E45-1525-4207-A292-08C0388BBF06}
EndGlobalSection
EndGlobal

+ 12
- 0
MVCTemplate/.config/dotnet-tools.json Zobrazit soubor

@@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "5.0.7",
"commands": [
"dotnet-ef"
]
}
}
}

+ 21
- 0
MVCTemplate/Areas/Identity/IdentityHostingStartup.cs Zobrazit soubor

@@ -0,0 +1,21 @@
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using MVCTemplate.Data.DbContexts;

[assembly: HostingStartup(typeof(MVCTemplate.Areas.Identity.IdentityHostingStartup))]
namespace MVCTemplate.Areas.Identity
{
public class IdentityHostingStartup : IHostingStartup
{
public void Configure(IWebHostBuilder builder)
{
builder.ConfigureServices((context, services) => {
});
}
}
}

+ 85
- 0
MVCTemplate/Areas/Identity/Pages/Account/Login.cshtml Zobrazit soubor

@@ -0,0 +1,85 @@
@page
@model LoginModel

@{
ViewData["Title"] = "Log in";
}

<h1>@ViewData["Title"]</h1>
<div class="row">
<div class="col-md-4">
<section>
<form id="account" method="post">
<h4>Use a local account to log in.</h4>
<hr />
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Input.Email"></label>
<input asp-for="Input.Email" class="form-control" />
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.Password"></label>
<input asp-for="Input.Password" class="form-control" />
<span asp-validation-for="Input.Password" class="text-danger"></span>
</div>
<div class="form-group">
<div class="checkbox">
<label asp-for="Input.RememberMe">
<input asp-for="Input.RememberMe" />
@Html.DisplayNameFor(m => m.Input.RememberMe)
</label>
</div>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Log in</button>
</div>
<div class="form-group">
<p>
<a id="forgot-password" asp-page="./ForgotPassword">Forgot your password?</a>
</p>
<p>
<a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">Register as a new user</a>
</p>
<p>
<a id="resend-confirmation" asp-page="./ResendEmailConfirmation">Resend email confirmation</a>
</p>
</div>
</form>
</section>
</div>
<div class="col-md-6 col-md-offset-2">
<section>
<h4>Use another service to log in.</h4>
<hr />
@{
if ((Model.ExternalLogins?.Count ?? 0) == 0)
{
<div>
<p>
There are no external authentication services configured. See <a href="https://go.microsoft.com/fwlink/?LinkID=532715">this article</a>
for details on setting up this ASP.NET application to support logging in via external services.
</p>
</div>
}
else
{
<form id="external-account" asp-page="./ExternalLogin" asp-route-returnUrl="@Model.ReturnUrl" method="post" class="form-horizontal">
<div>
<p>
@foreach (var provider in Model.ExternalLogins)
{
<button type="submit" class="btn btn-primary" name="provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">@provider.DisplayName</button>
}
</p>
</div>
</form>
}
}
</section>
</div>
</div>

@section Scripts {
<partial name="_ValidationScriptsPartial" />
}

+ 110
- 0
MVCTemplate/Areas/Identity/Pages/Account/Login.cshtml.cs Zobrazit soubor

@@ -0,0 +1,110 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;

namespace MVCTemplate.Areas.Identity.Pages.Account
{
[AllowAnonymous]
public class LoginModel : PageModel
{
private readonly UserManager<IdentityUser> _userManager;
private readonly SignInManager<IdentityUser> _signInManager;
private readonly ILogger<LoginModel> _logger;

public LoginModel(SignInManager<IdentityUser> signInManager,
ILogger<LoginModel> logger,
UserManager<IdentityUser> userManager)
{
_userManager = userManager;
_signInManager = signInManager;
_logger = logger;
}

[BindProperty]
public InputModel Input { get; set; }

public IList<AuthenticationScheme> ExternalLogins { get; set; }

public string ReturnUrl { get; set; }

[TempData]
public string ErrorMessage { get; set; }

public class InputModel
{
[Required]
[EmailAddress]
public string Email { get; set; }

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }

[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}

public async Task OnGetAsync(string returnUrl = null)
{
if (!string.IsNullOrEmpty(ErrorMessage))
{
ModelState.AddModelError(string.Empty, ErrorMessage);
}

returnUrl ??= Url.Content("~/");

// Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);

ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();

ReturnUrl = returnUrl;
}

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl ??= Url.Content("~/");

ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
_logger.LogInformation("User logged in.");
return LocalRedirect(returnUrl);
}
if (result.RequiresTwoFactor)
{
return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
}
if (result.IsLockedOut)
{
_logger.LogWarning("User account locked out.");
return RedirectToPage("./Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return Page();
}
}

// If we got this far, something failed, redisplay form
return Page();
}
}
}

+ 67
- 0
MVCTemplate/Areas/Identity/Pages/Account/Register.cshtml Zobrazit soubor

@@ -0,0 +1,67 @@
@page
@model RegisterModel
@{
ViewData["Title"] = "Register";
}

<h1>@ViewData["Title"]</h1>

<div class="row">
<div class="col-md-4">
<form asp-route-returnUrl="@Model.ReturnUrl" method="post">
<h4>Create a new account.</h4>
<hr />
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Input.Email"></label>
<input asp-for="Input.Email" class="form-control" />
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.Password"></label>
<input asp-for="Input.Password" class="form-control" />
<span asp-validation-for="Input.Password" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.ConfirmPassword"></label>
<input asp-for="Input.ConfirmPassword" class="form-control" />
<span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
</div>
<div class="col-md-6 col-md-offset-2">
<section>
<h4>Use another service to register.</h4>
<hr />
@{
if ((Model.ExternalLogins?.Count ?? 0) == 0)
{
<div>
<p>
There are no external authentication services configured. See <a href="https://go.microsoft.com/fwlink/?LinkID=532715">this article</a>
for details on setting up this ASP.NET application to support logging in via external services.
</p>
</div>
}
else
{
<form id="external-account" asp-page="./ExternalLogin" asp-route-returnUrl="@Model.ReturnUrl" method="post" class="form-horizontal">
<div>
<p>
@foreach (var provider in Model.ExternalLogins)
{
<button type="submit" class="btn btn-primary" name="provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">@provider.DisplayName</button>
}
</p>
</div>
</form>
}
}
</section>
</div>
</div>

@section Scripts {
<partial name="_ValidationScriptsPartial" />
}

+ 114
- 0
MVCTemplate/Areas/Identity/Pages/Account/Register.cshtml.cs Zobrazit soubor

@@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Logging;

namespace MVCTemplate.Areas.Identity.Pages.Account
{
[AllowAnonymous]
public class RegisterModel : PageModel
{
private readonly SignInManager<IdentityUser> _signInManager;
private readonly UserManager<IdentityUser> _userManager;
private readonly ILogger<RegisterModel> _logger;
private readonly IEmailSender _emailSender;

public RegisterModel(
UserManager<IdentityUser> userManager,
SignInManager<IdentityUser> signInManager,
ILogger<RegisterModel> logger,
IEmailSender emailSender)
{
_userManager = userManager;
_signInManager = signInManager;
_logger = logger;
_emailSender = emailSender;
}

[BindProperty]
public InputModel Input { get; set; }

public string ReturnUrl { get; set; }

public IList<AuthenticationScheme> ExternalLogins { get; set; }

public class InputModel
{
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }

[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }

[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}

public async Task OnGetAsync(string returnUrl = null)
{
ReturnUrl = returnUrl;
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
}

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl ??= Url.Content("~/");
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
if (ModelState.IsValid)
{
var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
var result = await _userManager.CreateAsync(user, Input.Password);
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");

var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { area = "Identity", userId = user.Id, code = code, returnUrl = returnUrl },
protocol: Request.Scheme);

await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");

if (_userManager.Options.SignIn.RequireConfirmedAccount)
{
return RedirectToPage("RegisterConfirmation", new { email = Input.Email, returnUrl = returnUrl });
}
else
{
await _signInManager.SignInAsync(user, isPersistent: false);
return LocalRedirect(returnUrl);
}
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}

// If we got this far, something failed, redisplay form
return Page();
}
}
}

+ 37
- 0
MVCTemplate/Areas/Identity/Pages/Account/ResetPassword.cshtml Zobrazit soubor

@@ -0,0 +1,37 @@
@page
@model ResetPasswordModel
@{
ViewData["Title"] = "Reset password";
}

<h1>@ViewData["Title"]</h1>
<h4>Reset your password.</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input asp-for="Input.Code" type="hidden" />
<div class="form-group">
<label asp-for="Input.Email"></label>
<input asp-for="Input.Email" class="form-control" />
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.Password"></label>
<input asp-for="Input.Password" class="form-control" />
<span asp-validation-for="Input.Password" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.ConfirmPassword"></label>
<input asp-for="Input.ConfirmPassword" class="form-control" />
<span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Reset</button>
</form>
</div>
</div>

@section Scripts {
<partial name="_ValidationScriptsPartial" />
}

+ 91
- 0
MVCTemplate/Areas/Identity/Pages/Account/ResetPassword.cshtml.cs Zobrazit soubor

@@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.WebUtilities;

namespace MVCTemplate.Areas.Identity.Pages.Account
{
[AllowAnonymous]
public class ResetPasswordModel : PageModel
{
private readonly UserManager<IdentityUser> _userManager;

public ResetPasswordModel(UserManager<IdentityUser> userManager)
{
_userManager = userManager;
}

[BindProperty]
public InputModel Input { get; set; }

public class InputModel
{
[Required]
[EmailAddress]
public string Email { get; set; }

[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
public string Password { get; set; }

[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }

public string Code { get; set; }
}

public IActionResult OnGet(string code = null)
{
if (code == null)
{
return BadRequest("A code must be supplied for password reset.");
}
else
{
Input = new InputModel
{
Code = code
};
return Page();
}
}

public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}

var user = await _userManager.FindByEmailAsync(Input.Email);
if (user == null)
{
// Don't reveal that the user does not exist
return RedirectToPage("./ResetPasswordConfirmation");
}

var result = await _userManager.ResetPasswordAsync(user, Input.Code, Input.Password);
if (result.Succeeded)
{
return RedirectToPage("./ResetPasswordConfirmation");
}

foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
return Page();
}
}
}

+ 1
- 0
MVCTemplate/Areas/Identity/Pages/Account/_ViewImports.cshtml Zobrazit soubor

@@ -0,0 +1 @@
@using MVCTemplate.Areas.Identity.Pages.Account

+ 18
- 0
MVCTemplate/Areas/Identity/Pages/_ValidationScriptsPartial.cshtml Zobrazit soubor

@@ -0,0 +1,18 @@
<environment include="Development">
<script src="~/Identity/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/Identity/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
</environment>
<environment exclude="Development">
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.17.0/jquery.validate.min.js"
asp-fallback-src="~/Identity/lib/jquery-validation/dist/jquery.validate.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator"
crossorigin="anonymous"
integrity="sha384-rZfj/ogBloos6wzLGpPkkOr/gpkBNLZ6b6yLy4o+ok+t/SAKlL5mvXLr0OXNi1Hp">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validation.unobtrusive/3.2.9/jquery.validate.unobtrusive.min.js"
asp-fallback-src="~/Identity/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
crossorigin="anonymous"
integrity="sha384-ifv0TYDWxBHzvAk2Z0n8R434FL1Rlv/Av18DXE43N/1rvHyOG4izKst0f2iSLdds">
</script>
</environment>

+ 4
- 0
MVCTemplate/Areas/Identity/Pages/_ViewImports.cshtml Zobrazit soubor

@@ -0,0 +1,4 @@
@using Microsoft.AspNetCore.Identity
@using MVCTemplate.Areas.Identity
@using MVCTemplate.Areas.Identity.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

+ 4
- 0
MVCTemplate/Areas/Identity/Pages/_ViewStart.cshtml Zobrazit soubor

@@ -0,0 +1,4 @@

@{
Layout = "/Views/Shared/_Layout.cshtml";
}

+ 41
- 0
MVCTemplate/Controllers/HomeController.cs Zobrazit soubor

@@ -0,0 +1,41 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using MVCTemplate.Business.Dtos;
using MVCTemplate.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using MVCTemplate.Infrastructure;

namespace MVCTemplate.Controllers
{
[Authorize]
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;

public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}

public IActionResult Index()
{
return View();
}



public IActionResult Privacy()
{
return View();
}
}
}

+ 11
- 0
MVCTemplate/Infrastructure/IModelFactory.cs Zobrazit soubor

@@ -0,0 +1,11 @@
using MVCTemplate.Business.Dtos;
using MVCTemplate.Models;
using System.Threading.Tasks;

namespace MVCTemplate.Infrastructure
{
public interface IModelFactory
{
}
}

+ 66
- 0
MVCTemplate/Infrastructure/Middleware/ExceptionHandlingMiddleware.cs Zobrazit soubor

@@ -0,0 +1,66 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Serilog;

namespace MVCTemplate.Infrastructure.Middleware
{
public class ExceptionHandlingMiddleware
{
private RequestDelegate nextRequestDelegate;
private IWebHostEnvironment environment;

public ExceptionHandlingMiddleware(
RequestDelegate nextRequestDelegate,
IWebHostEnvironment environment
)
{
this.nextRequestDelegate = nextRequestDelegate ?? throw new ArgumentNullException(nameof(nextRequestDelegate));
this.environment = environment ?? throw new ArgumentNullException(nameof(environment));
}

public async Task Invoke(HttpContext context)
{
try
{
context.TraceIdentifier = Guid.NewGuid().ToString();
await this.nextRequestDelegate(context);
}
catch (Exception ex)
{
await this.HandleGlobalExceptionAsync(context, ex);
}
}

private async Task HandleGlobalExceptionAsync(HttpContext context, Exception ex)
{

try
{
await this.WriteResponseAsync(context, HttpStatusCode.InternalServerError, JsonConvert.SerializeObject(ex.Message));
}
catch (Exception e)
{
await this.WriteResponseAsync(context, HttpStatusCode.InternalServerError, JsonConvert.SerializeObject(e.Message));
}

var logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.File(@"AppData\Errors\log-.log", rollingInterval: RollingInterval.Day)
.CreateLogger();
logger.Error(ex, "Unhandled Exception"/* - Detected UserId: {UserId}" /*, context.User.GetUserId()*/);
}

private async Task WriteResponseAsync(HttpContext context, HttpStatusCode code, string jsonResponse)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)code;
await context.Response.WriteAsync(jsonResponse);
}
}
}

+ 36
- 0
MVCTemplate/MVCTemplate.csproj Zobrazit soubor

@@ -0,0 +1,36 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<CopyRefAssembliesToPublishDirectory>false</CopyRefAssembliesToPublishDirectory>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AutoMapper" Version="11.0.1" />
<PackageReference Include="Microsoft.AspNet.Identity.Core" Version="2.2.3" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Google" Version="5.0.7" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="5.0.6" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.6" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="5.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.6">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="5.0.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Quartz" Version="3.4.0" />
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\MVCTemplate.Business\MVCTemplate.Business.csproj" />
<ProjectReference Include="..\MVCTemplate.Data\MVCTemplate.Data.csproj" />
</ItemGroup>

<ItemGroup>
<Folder Include="AppData\Errors\" />
</ItemGroup>

</Project>

+ 11
- 0
MVCTemplate/Models/ErrorViewModel.cs Zobrazit soubor

@@ -0,0 +1,11 @@
using System;

namespace MVCTemplate.Models
{
public class ErrorViewModel
{
public string RequestId { get; set; }

public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
}
}

+ 26
- 0
MVCTemplate/Program.cs Zobrazit soubor

@@ -0,0 +1,26 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace MVCTemplate
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}

+ 30
- 0
MVCTemplate/Properties/launchSettings.json Zobrazit soubor

@@ -0,0 +1,30 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:24744",
"sslPort": 44336
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation"
}
},
"MVCTemplate": {
"commandName": "Project",
"dotnetRunMessages": "true",
"launchBrowser": true,
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation"
}
}
}
}

+ 3
- 0
MVCTemplate/ScaffoldingReadMe.txt Zobrazit soubor

@@ -0,0 +1,3 @@
Support for ASP.NET Core Identity was added to your project.

For setup and configuration information, see https://go.microsoft.com/fwlink/?linkid=2116645.

+ 70
- 0
MVCTemplate/Startup.cs Zobrazit soubor

@@ -0,0 +1,70 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using MVCTemplate.Business.Infrastructure;
using MVCTemplate.Business.Infrastructure.Extensions;
using MVCTemplate.Business.Infrastructure.Settings;
using MVCTemplate.Data.DbContexts;
using MVCTemplate.Infrastructure.Middleware;


namespace MVCTemplate
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
StartupConfiguration.ConfigureStartupConfig<EmailSettings>(services, Configuration);
services.AddControllersWithViews();
services.AddRazorPages();
StartupExtensions.ConfigureServices(services);
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = false)
.AddDefaultUI()
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<AppDbContext>();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// 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.UseStaticFiles();

app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();

app.UseMiddleware(typeof(ExceptionHandlingMiddleware));

app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
}
}
}

+ 3
- 0
MVCTemplate/Views/Home/Index.cshtml Zobrazit soubor

@@ -0,0 +1,3 @@
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}

+ 6
- 0
MVCTemplate/Views/Home/Privacy.cshtml Zobrazit soubor

@@ -0,0 +1,6 @@
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>

<p>Use this page to detail your site's privacy policy.</p>

+ 25
- 0
MVCTemplate/Views/Shared/Error.cshtml Zobrazit soubor

@@ -0,0 +1,25 @@
@model ErrorViewModel
@{
ViewData["Title"] = "Error";
}

<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>

@if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}

<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>

+ 111
- 0
MVCTemplate/Views/Shared/_Layout.cshtml Zobrazit soubor

@@ -0,0 +1,111 @@
@{
var controller = ViewContext.RouteData.Values["Controller"];
var action = ViewContext.RouteData.Values["Action"];
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - MVCTemplate</title>
<!-- Google Font: Source Sans Pro -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700&display=fallback">
<!-- Font Awesome -->
<link rel="stylesheet" href="~/plugins/fontawesome-free/css/all.min.css">
<!-- Ionicons -->
<link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
<!-- Tempusdominus Bootstrap 4 -->
<link rel="stylesheet" href="~/plugins/tempusdominus-bootstrap-4/css/tempusdominus-bootstrap-4.min.css">
<!-- iCheck -->
<link rel="stylesheet" href="~/plugins/icheck-bootstrap/icheck-bootstrap.min.css">
<!-- JQVMap -->
<link rel="stylesheet" href="~/plugins/jqvmap/jqvmap.min.css">
<!-- Theme style -->
<link rel="stylesheet" href="~/dist/css/adminlte.min.css">
<!-- overlayScrollbars -->
<link rel="stylesheet" href="~/plugins/overlayScrollbars/css/OverlayScrollbars.min.css">
<!-- Daterange picker -->
<link rel="stylesheet" href="~/plugins/daterangepicker/daterangepicker.css">
<!-- summernote -->
<link rel="stylesheet" href="~/plugins/summernote/summernote-bs4.min.css">


<link href="~/lib/jquery-confirm/jquery-confirm.min.css" rel="stylesheet" />



<link rel="stylesheet" href="~/css/site.css">
</head>
<body class="hold-transition layout-fixed">
<noscript><p>Your browser does not support JavaScript. You need it enabled to do testing.</p></noscript>

<div class="wrapper">

<div class="content-wrapper default-layout">
<section class="content">
<main role="main" class="pb-3">
<div class="content-fluid">
<div>&nbsp;</div>
<div class="card">
<div class="card-body">
@RenderBody()
</div>
</div>
</div>
</main>
</section>
</div>
<footer class="main-footer ml-0">
<strong>Copyright &copy; 2021 <a href="https://dilig.net/">Diligent Software</a>.</strong>
All rights reserved.
<div class="float-right d-none d-sm-inline-block">
<b>Version</b> 1.0.0-alpha
</div>
</footer>
</div>
<!-- jQuery -->
<script src="~/plugins/jquery/jquery.min.js"></script>
<!-- jQuery UI 1.11.4 -->
<script src="~/plugins/jquery-ui/jquery-ui.min.js"></script>
<!-- Resolve conflict in jQuery UI tooltip with Bootstrap tooltip -->
<script>
$.widget.bridge('uibutton', $.ui.button)
</script>
<!-- Bootstrap 4 -->
<script src="~/plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- ChartJS -->
<script src="~/plugins/chart.js/Chart.min.js"></script>
<!-- Sparkline -->
<script src="~/plugins/sparklines/sparkline.js"></script>
<!-- JQVMap -->
<script src="~/plugins/jqvmap/jquery.vmap.min.js"></script>
<script src="~/plugins/jqvmap/maps/jquery.vmap.usa.js"></script>
<!-- jQuery Knob Chart -->
<script src="~/plugins/jquery-knob/jquery.knob.min.js"></script>
<!-- daterangepicker -->
<script src="~/plugins/moment/moment.min.js"></script>
<script src="~/plugins/daterangepicker/daterangepicker.js"></script>
<!-- Tempusdominus Bootstrap 4 -->
<script src="~/plugins/tempusdominus-bootstrap-4/js/tempusdominus-bootstrap-4.min.js"></script>
<!-- Summernote -->
<script src="~/plugins/summernote/summernote-bs4.min.js"></script>
<!-- overlayScrollbars -->
<script src="~/plugins/overlayScrollbars/js/jquery.overlayScrollbars.min.js"></script>
<!-- AdminLTE App -->
<script src="~/dist/js/adminlte.js"></script>



<!-- JQery Confirm -->

<script src="~/lib/alertifyjs/alertify.min.js"></script>
<script src="~/lib/blockUI/jquery.blockUI.js"></script>


<script src="~/js/site.js" asp-append-version="true"></script>
@await RenderSectionAsync("Scripts", required: false)

</body>
</html>

+ 264
- 0
MVCTemplate/Views/Shared/_LayoutAdmin.cshtml Zobrazit soubor

@@ -0,0 +1,264 @@
@*@{
var controller = ViewContext.RouteData.Values["Controller"];
var action = ViewContext.RouteData.Values["Action"];
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - MVCTemplate</title>
<!-- Google Font: Source Sans Pro -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700&display=fallback">
<!-- Font Awesome -->
<link rel="stylesheet" href="~/plugins/fontawesome-free/css/all.min.css">
<link rel="stylesheet" href="~/css/site.css">
<!-- Ionicons -->
<link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
<!-- Tempusdominus Bootstrap 4 -->
<link rel="stylesheet" href="~/plugins/tempusdominus-bootstrap-4/css/tempusdominus-bootstrap-4.min.css">
<!-- iCheck -->
<link rel="stylesheet" href="~/plugins/icheck-bootstrap/icheck-bootstrap.min.css">
<!-- JQVMap -->
<link rel="stylesheet" href="~/plugins/jqvmap/jqvmap.min.css">
<!-- Theme style -->
<link rel="stylesheet" href="~/dist/css/adminlte.min.css">
<!-- overlayScrollbars -->
<link rel="stylesheet" href="~/plugins/overlayScrollbars/css/OverlayScrollbars.min.css">
<!-- Daterange picker -->
<link rel="stylesheet" href="~/plugins/daterangepicker/daterangepicker.css">
<!-- summernote -->
<link rel="stylesheet" href="~/plugins/summernote/summernote-bs4.min.css">
<!-- summernote -->
<link rel="stylesheet" href="~/plugins/datatables-bs4/css/dataTables.bootstrap4.min.css">
<link rel="stylesheet" href="~/plugins/datatables-responsive/css/responsive.bootstrap4.min.css">
<link rel="stylesheet" href="~/plugins/datatables-buttons/css/buttons.bootstrap4.min.css">
<link rel="stylesheet" href="~/plugins/datatables-rowreorder/css/rowReorder.bootstrap4.min.css">

<link rel="stylesheet" href="~/plugins/select2/css/select2.css">
<link rel="stylesheet" href="~/plugins/select2-bootstrap4-theme/select2-bootstrap4.min.css">


<link href="~/lib/jquery-confirm/jquery-confirm.min.css" rel="stylesheet" />



<link rel="stylesheet" href="~/css/site.css">
</head>
<body class="hold-transition sidebar-mini layout-fixed">
<div class="wrapper">
<header>
<!-- Navbar -->
<nav class="main-header navbar navbar-expand navbar-white navbar-light">
<!-- Left navbar links -->
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" data-widget="pushmenu" href="#" role="button"><i class="fas fa-bars"></i></a>
</li>
</ul>

<!-- Right navbar links -->
<ul class="navbar-nav ml-auto">

<!-- User Dropdown Menu -->
<li class="nav-item dropdown">
<a class="nav-link" data-toggle="dropdown" href="#">
<i class="far fa-user"></i> @User.FindFirst(System.Security.Claims.ClaimTypes.Email).Value
</a>
<div class="dropdown-menu dropdown-menu-right">
<a href="#" class="dropdown-item">
<i class="fas fa-cog mr-2"></i> Profile
</a>
<a href="/Identity/Account/LogOut" class="dropdown-item">
<i class="fas fa-sign-out-alt mr-2"></i> Log Out
</a>
</div>
</li>
</ul>
</nav>
<!-- /.navbar -->
</header>

<!-- Main Sidebar Container -->
<aside class="main-sidebar sidebar-dark-purple elevation-4">
<!-- Brand Logo -->
<a href="#" class="brand-link">
<img src="~/dist/img/AdminLTELogo.png" alt="AdminLTE Logo" class="brand-image img-circle elevation-3" style="opacity: .8">
<span class="brand-text font-weight-light">Screening test</span>
</a>

<!-- Sidebar -->
<div class="sidebar">

<!-- SidebarSearch Form -->
<div class="form-inline">
<div class="input-group" data-widget="sidebar-search">
<input class="form-control form-control-sidebar" type="search" placeholder="Search" aria-label="Search">
<div class="input-group-append">
<button class="btn btn-sidebar">
<i class="fas fa-search fa-fw"></i>
</button>
</div>
</div>
</div>

<!-- Sidebar Menu -->
<nav class="mt-2">
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false">
<!-- Add icons to the links using the .nav-icon class
with font-awesome or any other icon font library -->
<li class="nav-item menu-open">
<a href="#" class='nav-link @(action.ToString() == "Users" || action.ToString() == "Invites" ? "active" : "")'>
<i class="nav-icon fas fa-tachometer-alt"></i>
<p>
Dashboard
<i class="right fas fa-angle-left"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a href="#" class='nav-link @(action.ToString() == "Statistics" ? "active" : "")'>
<i class="far fa-circle nav-icon"></i>
<p>Statistics</p>
</a>
</li>
<li class='nav-item'>
<a asp-controller="Manage" asp-action="Users" class='nav-link @(action.ToString() == "Users" ? "active" : "")'>
<i class="far fa-circle nav-icon"></i>
<p>Users</p>
</a>
</li>
<li class='nav-item'>
<a asp-controller="Manage" asp-action="Invites" class='nav-link @(action.ToString() == "Invites" ? "active" : "")'>
<i class="far fa-circle nav-icon"></i>
<p>Invites</p>
</a>
</li>
</ul>
</li>
<li class="nav-item menu-open">
<a href="#" class='nav-link @(action.ToString() == "Tests" || action.ToString() == "Questions" ? "active" : "")'>
<i class='nav-icon fas fa-scroll'></i>
<p>
Test Management
<i class="right fas fa-angle-left"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a asp-controller="Manage" asp-action="Tests" class='nav-link @(action.ToString() == "Tests" ? "active" : "")'>
<i class="far fa-circle nav-icon"></i>
<p>Tests</p>
</a>
</li>
<li class="nav-item">
<a asp-controller="Manage" asp-action="Questions" class='nav-link @(action.ToString() == "Questions" ? "active" : "")'>
<i class="far fa-circle nav-icon"></i>
<p>Questions</p>
</a>
</li>
</ul>
</li>
<li class="nav-item menu-open">
<a href="#" class='nav-link @(action.ToString() == "Categories" ? "active" : "")'>
<i class="nav-icon fas fa-cog"></i>
<p>
Settings
<i class="right fas fa-angle-left"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a asp-controller="Manage" asp-action="Categories" class='nav-link @(action.ToString() == "Categories" ? "active" : "")'>
<i class="far fa-circle nav-icon"></i>
<p>Categories</p>
</a>
</li>
</ul>
</li>
</ul>
</nav>
<!-- /.sidebar-menu -->
</div>
<!-- /.sidebar -->
</aside>

<div class="content-wrapper">
<section class="content">
<main role="main" class="pb-3">
@RenderBody()
</main>
</section>
</div>
<footer class="main-footer">
<strong>Copyright &copy; 2021 <a href="https://dilig.net/">Diligent Software</a>.</strong>
All rights reserved.
<div class="float-right d-none d-sm-inline-block">
<b>Version</b> 1.0.0-alpha
</div>
</footer>
</div>
<!-- jQuery -->
<script src="~/plugins/jquery/jquery.min.js"></script>
<!-- jQuery UI 1.11.4 -->
<script src="~/plugins/jquery-ui/jquery-ui.min.js"></script>
<!-- Resolve conflict in jQuery UI tooltip with Bootstrap tooltip -->
<script>
$.widget.bridge('uibutton', $.ui.button)
</script>
<!-- Bootstrap 4 -->
<script src="~/plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- ChartJS -->
<script src="~/plugins/chart.js/Chart.min.js"></script>
<!-- Sparkline -->
<script src="~/plugins/sparklines/sparkline.js"></script>
<!-- JQVMap -->
<script src="~/plugins/jqvmap/jquery.vmap.min.js"></script>
<script src="~/plugins/jqvmap/maps/jquery.vmap.usa.js"></script>
<!-- jQuery Knob Chart -->
<script src="~/plugins/jquery-knob/jquery.knob.min.js"></script>
<!-- daterangepicker -->
<script src="~/plugins/moment/moment.min.js"></script>
<script src="~/plugins/daterangepicker/daterangepicker.js"></script>
<!-- Tempusdominus Bootstrap 4 -->
<script src="~/plugins/tempusdominus-bootstrap-4/js/tempusdominus-bootstrap-4.min.js"></script>
<!-- Summernote -->
<script src="~/plugins/summernote/summernote-bs4.min.js"></script>
<!-- overlayScrollbars -->
<script src="~/plugins/overlayScrollbars/js/jquery.overlayScrollbars.min.js"></script>
<!-- AdminLTE App -->
<script src="~/dist/js/adminlte.js"></script>

<script src="~/plugins/datatables/jquery.dataTables.min.js"></script>
<script src="~/plugins/datatables-bs4/js/dataTables.bootstrap4.min.js"></script>
<script src="~/plugins/datatables-responsive/js/dataTables.responsive.min.js"></script>
<script src="~/plugins/datatables-responsive/js/responsive.bootstrap4.min.js"></script>
<script src="~/plugins/datatables-buttons/js/dataTables.buttons.min.js"></script>
<script src="~/plugins/datatables-buttons/js/buttons.bootstrap4.min.js"></script>
<script src="~/plugins/jszip/jszip.min.js"></script>
<script src="~/plugins/pdfmake/pdfmake.min.js"></script>
<script src="~/plugins/pdfmake/vfs_fonts.js"></script>
<script src="~/plugins/datatables-buttons/js/buttons.html5.min.js"></script>
<script src="~/plugins/datatables-buttons/js/buttons.print.min.js"></script>
<script src="~/plugins/datatables-buttons/js/buttons.colVis.min.js"></script>
<script src="~/plugins/datatables-rowreorder/js/dataTables.rowReorder.min.js"></script>
<script src="~/plugins/datatables-rowreorder/js/rowReorder.bootstrap4.min.js"></script>
<script src="~/plugins/select2/js/select2.min.js"></script>



<!-- JQery Confirm -->
<script src="~/lib/jquery-confirm/jquery-confirm.min.js"></script>

<script src="~/lib/alertifyjs/alertify.min.js"></script>
<script src="~/lib/blockUI/jquery.blockUI.js"></script>


<script src="~/js/site.js" asp-append-version="true"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>
*@

+ 28
- 0
MVCTemplate/Views/Shared/_LoginPartial.cshtml Zobrazit soubor

@@ -0,0 +1,28 @@
@*@using Microsoft.AspNetCore.Identity

@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager

<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
<li class="nav-item">
<a id="manage" class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage">Hello @UserManager.GetUserName(User)!</a>
</li>
<li class="nav-item">
<form id="logoutForm" class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="@Url.Action("Index", "Home", new { area = "" })">
<button id="logout" type="submit" class="nav-link btn btn-link text-dark">Logout</button>
</form>
</li>
}
else
{
<li class="nav-item">
<a class="nav-link text-dark" id="register" asp-area="Identity" asp-page="/Account/Register">Register</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" id="login" asp-area="Identity" asp-page="/Account/Login">Login</a>
</li>
}
</ul>
*@

+ 2
- 0
MVCTemplate/Views/Shared/_ValidationScriptsPartial.cshtml Zobrazit soubor

@@ -0,0 +1,2 @@
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>

+ 3
- 0
MVCTemplate/Views/_ViewImports.cshtml Zobrazit soubor

@@ -0,0 +1,3 @@
@using MVCTemplate
@using MVCTemplate.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

+ 3
- 0
MVCTemplate/Views/_ViewStart.cshtml Zobrazit soubor

@@ -0,0 +1,3 @@
@{
Layout = "_Layout";
}

+ 9
- 0
MVCTemplate/appsettings.Development.json Zobrazit soubor

@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}

+ 16
- 0
MVCTemplate/appsettings.json Zobrazit soubor

@@ -0,0 +1,16 @@
{
"AllowedHosts": "*",
"ConnectionStrings": {
"DefaultConnection": "data source=(localdb)\\MSSQLLocalDB; initial catalog=Test;Integrated Security=True"

},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}

}

+ 14
- 0
MVCTemplate/wwwroot/build/config/.eslintrc.json Zobrazit soubor

@@ -0,0 +1,14 @@
{
"env": {
"browser": false,
"node": true
},
"parserOptions": {
"sourceType": "script"
},
"extends": "../../.eslintrc.json",
"rules": {
"no-console": "off",
"strict": "error"
}
}

+ 17
- 0
MVCTemplate/wwwroot/build/config/postcss.config.js Zobrazit soubor

@@ -0,0 +1,17 @@
'use strict'

module.exports = {
map: {
inline: false,
annotation: true,
sourcesContent: true
},
plugins: [
require('postcss-scrollbar')({
edgeAutohide: true
}),
require('autoprefixer')({
cascade: false
})
]
}

+ 32
- 0
MVCTemplate/wwwroot/build/config/rollup.config.js Zobrazit soubor

@@ -0,0 +1,32 @@
'use strict'

const { babel } = require('@rollup/plugin-babel')

const pkg = require('../../package')
const year = new Date().getFullYear()
const banner = `/*!
* AdminLTE v${pkg.version} (${pkg.homepage})
* Copyright 2014-${year} ${pkg.author}
* Licensed under MIT (https://github.com/ColorlibHQ/AdminLTE/blob/master/LICENSE)
*/`

module.exports = {
input: 'build/js/AdminLTE.js',
output: {
banner,
file: 'dist/js/adminlte.js',
format: 'umd',
globals: {
jquery: 'jQuery'
},
name: 'adminlte'
},
external: ['jquery'],
plugins: [
babel({
exclude: 'node_modules/**',
// Include the helpers in the bundle, at most one copy of each
babelHelpers: 'bundled'
})
]
}

+ 33
- 0
MVCTemplate/wwwroot/build/js/AdminLTE.js Zobrazit soubor

@@ -0,0 +1,33 @@
import CardRefresh from './CardRefresh'
import CardWidget from './CardWidget'
import ControlSidebar from './ControlSidebar'
import DirectChat from './DirectChat'
import Dropdown from './Dropdown'
import ExpandableTable from './ExpandableTable'
import Fullscreen from './Fullscreen'
import IFrame from './IFrame'
import Layout from './Layout'
import PushMenu from './PushMenu'
import SidebarSearch from './SidebarSearch'
import NavbarSearch from './NavbarSearch'
import Toasts from './Toasts'
import TodoList from './TodoList'
import Treeview from './Treeview'

export {
CardRefresh,
CardWidget,
ControlSidebar,
DirectChat,
Dropdown,
ExpandableTable,
Fullscreen,
IFrame,
Layout,
PushMenu,
SidebarSearch,
NavbarSearch,
Toasts,
TodoList,
Treeview
}

+ 153
- 0
MVCTemplate/wwwroot/build/js/CardRefresh.js Zobrazit soubor

@@ -0,0 +1,153 @@
/**
* --------------------------------------------
* AdminLTE CardRefresh.js
* License MIT
* --------------------------------------------
*/

import $ from 'jquery'

/**
* Constants
* ====================================================
*/

const NAME = 'CardRefresh'
const DATA_KEY = 'lte.cardrefresh'
const EVENT_KEY = `.${DATA_KEY}`
const JQUERY_NO_CONFLICT = $.fn[NAME]

const EVENT_LOADED = `loaded${EVENT_KEY}`
const EVENT_OVERLAY_ADDED = `overlay.added${EVENT_KEY}`
const EVENT_OVERLAY_REMOVED = `overlay.removed${EVENT_KEY}`

const CLASS_NAME_CARD = 'card'

const SELECTOR_CARD = `.${CLASS_NAME_CARD}`
const SELECTOR_DATA_REFRESH = '[data-card-widget="card-refresh"]'

const Default = {
source: '',
sourceSelector: '',
params: {},
trigger: SELECTOR_DATA_REFRESH,
content: '.card-body',
loadInContent: true,
loadOnInit: true,
responseType: '',
overlayTemplate: '<div class="overlay"><i class="fas fa-2x fa-sync-alt fa-spin"></i></div>',
onLoadStart() {},
onLoadDone(response) {
return response
}
}

class CardRefresh {
constructor(element, settings) {
this._element = element
this._parent = element.parents(SELECTOR_CARD).first()
this._settings = $.extend({}, Default, settings)
this._overlay = $(this._settings.overlayTemplate)

if (element.hasClass(CLASS_NAME_CARD)) {
this._parent = element
}

if (this._settings.source === '') {
throw new Error('Source url was not defined. Please specify a url in your CardRefresh source option.')
}
}

load() {
this._addOverlay()
this._settings.onLoadStart.call($(this))

$.get(this._settings.source, this._settings.params, response => {
if (this._settings.loadInContent) {
if (this._settings.sourceSelector !== '') {
response = $(response).find(this._settings.sourceSelector).html()
}

this._parent.find(this._settings.content).html(response)
}

this._settings.onLoadDone.call($(this), response)
this._removeOverlay()
}, this._settings.responseType !== '' && this._settings.responseType)

$(this._element).trigger($.Event(EVENT_LOADED))
}

_addOverlay() {
this._parent.append(this._overlay)
$(this._element).trigger($.Event(EVENT_OVERLAY_ADDED))
}

_removeOverlay() {
this._parent.find(this._overlay).remove()
$(this._element).trigger($.Event(EVENT_OVERLAY_REMOVED))
}

// Private

_init() {
$(this).find(this._settings.trigger).on('click', () => {
this.load()
})

if (this._settings.loadOnInit) {
this.load()
}
}

// Static

static _jQueryInterface(config) {
let data = $(this).data(DATA_KEY)
const _options = $.extend({}, Default, $(this).data())

if (!data) {
data = new CardRefresh($(this), _options)
$(this).data(DATA_KEY, typeof config === 'string' ? data : config)
}

if (typeof config === 'string' && /load/.test(config)) {
data[config]()
} else {
data._init($(this))
}
}
}

/**
* Data API
* ====================================================
*/

$(document).on('click', SELECTOR_DATA_REFRESH, function (event) {
if (event) {
event.preventDefault()
}

CardRefresh._jQueryInterface.call($(this), 'load')
})

$(() => {
$(SELECTOR_DATA_REFRESH).each(function () {
CardRefresh._jQueryInterface.call($(this))
})
})

/**
* jQuery API
* ====================================================
*/

$.fn[NAME] = CardRefresh._jQueryInterface
$.fn[NAME].Constructor = CardRefresh
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT
return CardRefresh._jQueryInterface
}

export default CardRefresh

+ 238
- 0
MVCTemplate/wwwroot/build/js/CardWidget.js Zobrazit soubor

@@ -0,0 +1,238 @@
/**
* --------------------------------------------
* AdminLTE CardWidget.js
* License MIT
* --------------------------------------------
*/

import $ from 'jquery'

/**
* Constants
* ====================================================
*/

const NAME = 'CardWidget'
const DATA_KEY = 'lte.cardwidget'
const EVENT_KEY = `.${DATA_KEY}`
const JQUERY_NO_CONFLICT = $.fn[NAME]

const EVENT_EXPANDED = `expanded${EVENT_KEY}`
const EVENT_COLLAPSED = `collapsed${EVENT_KEY}`
const EVENT_MAXIMIZED = `maximized${EVENT_KEY}`
const EVENT_MINIMIZED = `minimized${EVENT_KEY}`
const EVENT_REMOVED = `removed${EVENT_KEY}`

const CLASS_NAME_CARD = 'card'
const CLASS_NAME_COLLAPSED = 'collapsed-card'
const CLASS_NAME_COLLAPSING = 'collapsing-card'
const CLASS_NAME_EXPANDING = 'expanding-card'
const CLASS_NAME_WAS_COLLAPSED = 'was-collapsed'
const CLASS_NAME_MAXIMIZED = 'maximized-card'

const SELECTOR_DATA_REMOVE = '[data-card-widget="remove"]'
const SELECTOR_DATA_COLLAPSE = '[data-card-widget="collapse"]'
const SELECTOR_DATA_MAXIMIZE = '[data-card-widget="maximize"]'
const SELECTOR_CARD = `.${CLASS_NAME_CARD}`
const SELECTOR_CARD_HEADER = '.card-header'
const SELECTOR_CARD_BODY = '.card-body'
const SELECTOR_CARD_FOOTER = '.card-footer'

const Default = {
animationSpeed: 'normal',
collapseTrigger: SELECTOR_DATA_COLLAPSE,
removeTrigger: SELECTOR_DATA_REMOVE,
maximizeTrigger: SELECTOR_DATA_MAXIMIZE,
collapseIcon: 'fa-minus',
expandIcon: 'fa-plus',
maximizeIcon: 'fa-expand',
minimizeIcon: 'fa-compress'
}

class CardWidget {
constructor(element, settings) {
this._element = element
this._parent = element.parents(SELECTOR_CARD).first()

if (element.hasClass(CLASS_NAME_CARD)) {
this._parent = element
}

this._settings = $.extend({}, Default, settings)
}

collapse() {
this._parent.addClass(CLASS_NAME_COLLAPSING).children(`${SELECTOR_CARD_BODY}, ${SELECTOR_CARD_FOOTER}`)
.slideUp(this._settings.animationSpeed, () => {
this._parent.addClass(CLASS_NAME_COLLAPSED).removeClass(CLASS_NAME_COLLAPSING)
})

this._parent.find(`> ${SELECTOR_CARD_HEADER} ${this._settings.collapseTrigger} .${this._settings.collapseIcon}`)
.addClass(this._settings.expandIcon)
.removeClass(this._settings.collapseIcon)

this._element.trigger($.Event(EVENT_COLLAPSED), this._parent)
}

expand() {
this._parent.addClass(CLASS_NAME_EXPANDING).children(`${SELECTOR_CARD_BODY}, ${SELECTOR_CARD_FOOTER}`)
.slideDown(this._settings.animationSpeed, () => {
this._parent.removeClass(CLASS_NAME_COLLAPSED).removeClass(CLASS_NAME_EXPANDING)
})

this._parent.find(`> ${SELECTOR_CARD_HEADER} ${this._settings.collapseTrigger} .${this._settings.expandIcon}`)
.addClass(this._settings.collapseIcon)
.removeClass(this._settings.expandIcon)

this._element.trigger($.Event(EVENT_EXPANDED), this._parent)
}

remove() {
this._parent.slideUp()
this._element.trigger($.Event(EVENT_REMOVED), this._parent)
}

toggle() {
if (this._parent.hasClass(CLASS_NAME_COLLAPSED)) {
this.expand()
return
}

this.collapse()
}

maximize() {
this._parent.find(`${this._settings.maximizeTrigger} .${this._settings.maximizeIcon}`)
.addClass(this._settings.minimizeIcon)
.removeClass(this._settings.maximizeIcon)
this._parent.css({
height: this._parent.height(),
width: this._parent.width(),
transition: 'all .15s'
}).delay(150).queue(function () {
const $element = $(this)

$element.addClass(CLASS_NAME_MAXIMIZED)
$('html').addClass(CLASS_NAME_MAXIMIZED)
if ($element.hasClass(CLASS_NAME_COLLAPSED)) {
$element.addClass(CLASS_NAME_WAS_COLLAPSED)
}

$element.dequeue()
})

this._element.trigger($.Event(EVENT_MAXIMIZED), this._parent)
}

minimize() {
this._parent.find(`${this._settings.maximizeTrigger} .${this._settings.minimizeIcon}`)
.addClass(this._settings.maximizeIcon)
.removeClass(this._settings.minimizeIcon)
this._parent.css('cssText', `height: ${this._parent[0].style.height} !important; width: ${this._parent[0].style.width} !important; transition: all .15s;`
).delay(10).queue(function () {
const $element = $(this)

$element.removeClass(CLASS_NAME_MAXIMIZED)
$('html').removeClass(CLASS_NAME_MAXIMIZED)
$element.css({
height: 'inherit',
width: 'inherit'
})
if ($element.hasClass(CLASS_NAME_WAS_COLLAPSED)) {
$element.removeClass(CLASS_NAME_WAS_COLLAPSED)
}

$element.dequeue()
})

this._element.trigger($.Event(EVENT_MINIMIZED), this._parent)
}

toggleMaximize() {
if (this._parent.hasClass(CLASS_NAME_MAXIMIZED)) {
this.minimize()
return
}

this.maximize()
}

// Private

_init(card) {
this._parent = card

$(this).find(this._settings.collapseTrigger).click(() => {
this.toggle()
})

$(this).find(this._settings.maximizeTrigger).click(() => {
this.toggleMaximize()
})

$(this).find(this._settings.removeTrigger).click(() => {
this.remove()
})
}

// Static

static _jQueryInterface(config) {
let data = $(this).data(DATA_KEY)
const _options = $.extend({}, Default, $(this).data())

if (!data) {
data = new CardWidget($(this), _options)
$(this).data(DATA_KEY, typeof config === 'string' ? data : config)
}

if (typeof config === 'string' && /collapse|expand|remove|toggle|maximize|minimize|toggleMaximize/.test(config)) {
data[config]()
} else if (typeof config === 'object') {
data._init($(this))
}
}
}

/**
* Data API
* ====================================================
*/

$(document).on('click', SELECTOR_DATA_COLLAPSE, function (event) {
if (event) {
event.preventDefault()
}

CardWidget._jQueryInterface.call($(this), 'toggle')
})

$(document).on('click', SELECTOR_DATA_REMOVE, function (event) {
if (event) {
event.preventDefault()
}

CardWidget._jQueryInterface.call($(this), 'remove')
})

$(document).on('click', SELECTOR_DATA_MAXIMIZE, function (event) {
if (event) {
event.preventDefault()
}

CardWidget._jQueryInterface.call($(this), 'toggleMaximize')
})

/**
* jQuery API
* ====================================================
*/

$.fn[NAME] = CardWidget._jQueryInterface
$.fn[NAME].Constructor = CardWidget
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT
return CardWidget._jQueryInterface
}

export default CardWidget

+ 322
- 0
MVCTemplate/wwwroot/build/js/ControlSidebar.js Zobrazit soubor

@@ -0,0 +1,322 @@
/**
* --------------------------------------------
* AdminLTE ControlSidebar.js
* License MIT
* --------------------------------------------
*/

import $ from 'jquery'

/**
* Constants
* ====================================================
*/

const NAME = 'ControlSidebar'
const DATA_KEY = 'lte.controlsidebar'
const EVENT_KEY = `.${DATA_KEY}`
const JQUERY_NO_CONFLICT = $.fn[NAME]

const EVENT_COLLAPSED = `collapsed${EVENT_KEY}`
const EVENT_EXPANDED = `expanded${EVENT_KEY}`

const SELECTOR_CONTROL_SIDEBAR = '.control-sidebar'
const SELECTOR_CONTROL_SIDEBAR_CONTENT = '.control-sidebar-content'
const SELECTOR_DATA_TOGGLE = '[data-widget="control-sidebar"]'
const SELECTOR_HEADER = '.main-header'
const SELECTOR_FOOTER = '.main-footer'

const CLASS_NAME_CONTROL_SIDEBAR_ANIMATE = 'control-sidebar-animate'
const CLASS_NAME_CONTROL_SIDEBAR_OPEN = 'control-sidebar-open'
const CLASS_NAME_CONTROL_SIDEBAR_SLIDE = 'control-sidebar-slide-open'
const CLASS_NAME_LAYOUT_FIXED = 'layout-fixed'
const CLASS_NAME_NAVBAR_FIXED = 'layout-navbar-fixed'
const CLASS_NAME_NAVBAR_SM_FIXED = 'layout-sm-navbar-fixed'
const CLASS_NAME_NAVBAR_MD_FIXED = 'layout-md-navbar-fixed'
const CLASS_NAME_NAVBAR_LG_FIXED = 'layout-lg-navbar-fixed'
const CLASS_NAME_NAVBAR_XL_FIXED = 'layout-xl-navbar-fixed'
const CLASS_NAME_FOOTER_FIXED = 'layout-footer-fixed'
const CLASS_NAME_FOOTER_SM_FIXED = 'layout-sm-footer-fixed'
const CLASS_NAME_FOOTER_MD_FIXED = 'layout-md-footer-fixed'
const CLASS_NAME_FOOTER_LG_FIXED = 'layout-lg-footer-fixed'
const CLASS_NAME_FOOTER_XL_FIXED = 'layout-xl-footer-fixed'

const Default = {
controlsidebarSlide: true,
scrollbarTheme: 'os-theme-light',
scrollbarAutoHide: 'l',
target: SELECTOR_CONTROL_SIDEBAR
}

/**
* Class Definition
* ====================================================
*/

class ControlSidebar {
constructor(element, config) {
this._element = element
this._config = config
}

// Public

collapse() {
const $body = $('body')
const $html = $('html')
const { target } = this._config

// Show the control sidebar
if (this._config.controlsidebarSlide) {
$html.addClass(CLASS_NAME_CONTROL_SIDEBAR_ANIMATE)
$body.removeClass(CLASS_NAME_CONTROL_SIDEBAR_SLIDE).delay(300).queue(function () {
$(target).hide()
$html.removeClass(CLASS_NAME_CONTROL_SIDEBAR_ANIMATE)
$(this).dequeue()
})
} else {
$body.removeClass(CLASS_NAME_CONTROL_SIDEBAR_OPEN)
}

$(this._element).trigger($.Event(EVENT_COLLAPSED))
}

show() {
const $body = $('body')
const $html = $('html')

// Collapse the control sidebar
if (this._config.controlsidebarSlide) {
$html.addClass(CLASS_NAME_CONTROL_SIDEBAR_ANIMATE)
$(this._config.target).show().delay(10).queue(function () {
$body.addClass(CLASS_NAME_CONTROL_SIDEBAR_SLIDE).delay(300).queue(function () {
$html.removeClass(CLASS_NAME_CONTROL_SIDEBAR_ANIMATE)
$(this).dequeue()
})
$(this).dequeue()
})
} else {
$body.addClass(CLASS_NAME_CONTROL_SIDEBAR_OPEN)
}

this._fixHeight()
this._fixScrollHeight()

$(this._element).trigger($.Event(EVENT_EXPANDED))
}

toggle() {
const $body = $('body')
const shouldClose = $body.hasClass(CLASS_NAME_CONTROL_SIDEBAR_OPEN) ||
$body.hasClass(CLASS_NAME_CONTROL_SIDEBAR_SLIDE)

if (shouldClose) {
// Close the control sidebar
this.collapse()
} else {
// Open the control sidebar
this.show()
}
}

// Private

_init() {
const $body = $('body')
const shouldNotHideAll = $body.hasClass(CLASS_NAME_CONTROL_SIDEBAR_OPEN) ||
$body.hasClass(CLASS_NAME_CONTROL_SIDEBAR_SLIDE)

if (shouldNotHideAll) {
$(SELECTOR_CONTROL_SIDEBAR).not(this._config.target).hide()
$(this._config.target).css('display', 'block')
} else {
$(SELECTOR_CONTROL_SIDEBAR).hide()
}

this._fixHeight()
this._fixScrollHeight()

$(window).resize(() => {
this._fixHeight()
this._fixScrollHeight()
})

$(window).scroll(() => {
const $body = $('body')
const shouldFixHeight = $body.hasClass(CLASS_NAME_CONTROL_SIDEBAR_OPEN) ||
$body.hasClass(CLASS_NAME_CONTROL_SIDEBAR_SLIDE)

if (shouldFixHeight) {
this._fixScrollHeight()
}
})
}

_isNavbarFixed() {
const $body = $('body')
return (
$body.hasClass(CLASS_NAME_NAVBAR_FIXED) ||
$body.hasClass(CLASS_NAME_NAVBAR_SM_FIXED) ||
$body.hasClass(CLASS_NAME_NAVBAR_MD_FIXED) ||
$body.hasClass(CLASS_NAME_NAVBAR_LG_FIXED) ||
$body.hasClass(CLASS_NAME_NAVBAR_XL_FIXED)
)
}

_isFooterFixed() {
const $body = $('body')
return (
$body.hasClass(CLASS_NAME_FOOTER_FIXED) ||
$body.hasClass(CLASS_NAME_FOOTER_SM_FIXED) ||
$body.hasClass(CLASS_NAME_FOOTER_MD_FIXED) ||
$body.hasClass(CLASS_NAME_FOOTER_LG_FIXED) ||
$body.hasClass(CLASS_NAME_FOOTER_XL_FIXED)
)
}

_fixScrollHeight() {
const $body = $('body')
const $controlSidebar = $(this._config.target)

if (!$body.hasClass(CLASS_NAME_LAYOUT_FIXED)) {
return
}

const heights = {
scroll: $(document).height(),
window: $(window).height(),
header: $(SELECTOR_HEADER).outerHeight(),
footer: $(SELECTOR_FOOTER).outerHeight()
}
const positions = {
bottom: Math.abs((heights.window + $(window).scrollTop()) - heights.scroll),
top: $(window).scrollTop()
}

const navbarFixed = this._isNavbarFixed() && $(SELECTOR_HEADER).css('position') === 'fixed'

const footerFixed = this._isFooterFixed() && $(SELECTOR_FOOTER).css('position') === 'fixed'

const $controlsidebarContent = $(`${this._config.target}, ${this._config.target} ${SELECTOR_CONTROL_SIDEBAR_CONTENT}`)

if (positions.top === 0 && positions.bottom === 0) {
$controlSidebar.css({
bottom: heights.footer,
top: heights.header
})
$controlsidebarContent.css('height', heights.window - (heights.header + heights.footer))
} else if (positions.bottom <= heights.footer) {
if (footerFixed === false) {
const top = heights.header - positions.top
$controlSidebar.css('bottom', heights.footer - positions.bottom).css('top', top >= 0 ? top : 0)
$controlsidebarContent.css('height', heights.window - (heights.footer - positions.bottom))
} else {
$controlSidebar.css('bottom', heights.footer)
}
} else if (positions.top <= heights.header) {
if (navbarFixed === false) {
$controlSidebar.css('top', heights.header - positions.top)
$controlsidebarContent.css('height', heights.window - (heights.header - positions.top))
} else {
$controlSidebar.css('top', heights.header)
}
} else if (navbarFixed === false) {
$controlSidebar.css('top', 0)
$controlsidebarContent.css('height', heights.window)
} else {
$controlSidebar.css('top', heights.header)
}

if (footerFixed && navbarFixed) {
$controlsidebarContent.css('height', '100%')
$controlSidebar.css('height', '')
} else if (footerFixed || navbarFixed) {
$controlsidebarContent.css('height', '100%')
$controlsidebarContent.css('height', '')
}
}

_fixHeight() {
const $body = $('body')
const $controlSidebar = $(`${this._config.target} ${SELECTOR_CONTROL_SIDEBAR_CONTENT}`)

if (!$body.hasClass(CLASS_NAME_LAYOUT_FIXED)) {
$controlSidebar.attr('style', '')
return
}

const heights = {
window: $(window).height(),
header: $(SELECTOR_HEADER).outerHeight(),
footer: $(SELECTOR_FOOTER).outerHeight()
}

let sidebarHeight = heights.window - heights.header

if (this._isFooterFixed() && $(SELECTOR_FOOTER).css('position') === 'fixed') {
sidebarHeight = heights.window - heights.header - heights.footer
}

$controlSidebar.css('height', sidebarHeight)

if (typeof $.fn.overlayScrollbars !== 'undefined') {
$controlSidebar.overlayScrollbars({
className: this._config.scrollbarTheme,
sizeAutoCapable: true,
scrollbars: {
autoHide: this._config.scrollbarAutoHide,
clickScrolling: true
}
})
}
}

// Static

static _jQueryInterface(operation) {
return this.each(function () {
let data = $(this).data(DATA_KEY)
const _options = $.extend({}, Default, $(this).data())

if (!data) {
data = new ControlSidebar(this, _options)
$(this).data(DATA_KEY, data)
}

if (data[operation] === 'undefined') {
throw new Error(`${operation} is not a function`)
}

data[operation]()
})
}
}

/**
*
* Data Api implementation
* ====================================================
*/
$(document).on('click', SELECTOR_DATA_TOGGLE, function (event) {
event.preventDefault()

ControlSidebar._jQueryInterface.call($(this), 'toggle')
})

$(document).ready(() => {
ControlSidebar._jQueryInterface.call($(SELECTOR_DATA_TOGGLE), '_init')
})

/**
* jQuery API
* ====================================================
*/

$.fn[NAME] = ControlSidebar._jQueryInterface
$.fn[NAME].Constructor = ControlSidebar
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT
return ControlSidebar._jQueryInterface
}

export default ControlSidebar

+ 84
- 0
MVCTemplate/wwwroot/build/js/DirectChat.js Zobrazit soubor

@@ -0,0 +1,84 @@
/**
* --------------------------------------------
* AdminLTE DirectChat.js
* License MIT
* --------------------------------------------
*/

import $ from 'jquery'

/**
* Constants
* ====================================================
*/

const NAME = 'DirectChat'
const DATA_KEY = 'lte.directchat'
const EVENT_KEY = `.${DATA_KEY}`
const JQUERY_NO_CONFLICT = $.fn[NAME]

const EVENT_TOGGLED = `toggled${EVENT_KEY}`

const SELECTOR_DATA_TOGGLE = '[data-widget="chat-pane-toggle"]'
const SELECTOR_DIRECT_CHAT = '.direct-chat'

const CLASS_NAME_DIRECT_CHAT_OPEN = 'direct-chat-contacts-open'

/**
* Class Definition
* ====================================================
*/

class DirectChat {
constructor(element) {
this._element = element
}

toggle() {
$(this._element).parents(SELECTOR_DIRECT_CHAT).first().toggleClass(CLASS_NAME_DIRECT_CHAT_OPEN)
$(this._element).trigger($.Event(EVENT_TOGGLED))
}

// Static

static _jQueryInterface(config) {
return this.each(function () {
let data = $(this).data(DATA_KEY)

if (!data) {
data = new DirectChat($(this))
$(this).data(DATA_KEY, data)
}

data[config]()
})
}
}

/**
*
* Data Api implementation
* ====================================================
*/

$(document).on('click', SELECTOR_DATA_TOGGLE, function (event) {
if (event) {
event.preventDefault()
}

DirectChat._jQueryInterface.call($(this), 'toggle')
})

/**
* jQuery API
* ====================================================
*/

$.fn[NAME] = DirectChat._jQueryInterface
$.fn[NAME].Constructor = DirectChat
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT
return DirectChat._jQueryInterface
}

export default DirectChat

+ 146
- 0
MVCTemplate/wwwroot/build/js/Dropdown.js Zobrazit soubor

@@ -0,0 +1,146 @@
/**
* --------------------------------------------
* AdminLTE Dropdown.js
* License MIT
* --------------------------------------------
*/

import $ from 'jquery'

/**
* Constants
* ====================================================
*/

const NAME = 'Dropdown'
const DATA_KEY = 'lte.dropdown'
const JQUERY_NO_CONFLICT = $.fn[NAME]

const SELECTOR_NAVBAR = '.navbar'
const SELECTOR_DROPDOWN_MENU = '.dropdown-menu'
const SELECTOR_DROPDOWN_MENU_ACTIVE = '.dropdown-menu.show'
const SELECTOR_DROPDOWN_TOGGLE = '[data-toggle="dropdown"]'

const CLASS_NAME_DROPDOWN_RIGHT = 'dropdown-menu-right'
const CLASS_NAME_DROPDOWN_SUBMENU = 'dropdown-submenu'

// TODO: this is unused; should be removed along with the extend?
const Default = {}

/**
* Class Definition
* ====================================================
*/

class Dropdown {
constructor(element, config) {
this._config = config
this._element = element
}

// Public

toggleSubmenu() {
this._element.siblings().show().toggleClass('show')

if (!this._element.next().hasClass('show')) {
this._element.parents(SELECTOR_DROPDOWN_MENU).first().find('.show').removeClass('show').hide()
}

this._element.parents('li.nav-item.dropdown.show').on('hidden.bs.dropdown', () => {
$('.dropdown-submenu .show').removeClass('show').hide()
})
}

fixPosition() {
const $element = $(SELECTOR_DROPDOWN_MENU_ACTIVE)

if ($element.length === 0) {
return
}

if ($element.hasClass(CLASS_NAME_DROPDOWN_RIGHT)) {
$element.css({
left: 'inherit',
right: 0
})
} else {
$element.css({
left: 0,
right: 'inherit'
})
}

const offset = $element.offset()
const width = $element.width()
const visiblePart = $(window).width() - offset.left

if (offset.left < 0) {
$element.css({
left: 'inherit',
right: offset.left - 5
})
} else if (visiblePart < width) {
$element.css({
left: 'inherit',
right: 0
})
}
}

// Static

static _jQueryInterface(config) {
return this.each(function () {
let data = $(this).data(DATA_KEY)
const _config = $.extend({}, Default, $(this).data())

if (!data) {
data = new Dropdown($(this), _config)
$(this).data(DATA_KEY, data)
}

if (config === 'toggleSubmenu' || config === 'fixPosition') {
data[config]()
}
})
}
}

/**
* Data API
* ====================================================
*/

$(`${SELECTOR_DROPDOWN_MENU} ${SELECTOR_DROPDOWN_TOGGLE}`).on('click', function (event) {
event.preventDefault()
event.stopPropagation()

Dropdown._jQueryInterface.call($(this), 'toggleSubmenu')
})

$(`${SELECTOR_NAVBAR} ${SELECTOR_DROPDOWN_TOGGLE}`).on('click', event => {
event.preventDefault()

if ($(event.target).parent().hasClass(CLASS_NAME_DROPDOWN_SUBMENU)) {
return
}

setTimeout(function () {
Dropdown._jQueryInterface.call($(this), 'fixPosition')
}, 1)
})

/**
* jQuery API
* ====================================================
*/

$.fn[NAME] = Dropdown._jQueryInterface
$.fn[NAME].Constructor = Dropdown
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT
return Dropdown._jQueryInterface
}

export default Dropdown

+ 116
- 0
MVCTemplate/wwwroot/build/js/ExpandableTable.js Zobrazit soubor

@@ -0,0 +1,116 @@
/**
* --------------------------------------------
* AdminLTE ExpandableTable.js
* License MIT
* --------------------------------------------
*/

import $ from 'jquery'

/**
* Constants
* ====================================================
*/

const NAME = 'ExpandableTable'
const DATA_KEY = 'lte.expandableTable'
const EVENT_KEY = `.${DATA_KEY}`
const JQUERY_NO_CONFLICT = $.fn[NAME]

const EVENT_EXPANDED = `expanded${EVENT_KEY}`
const EVENT_COLLAPSED = `collapsed${EVENT_KEY}`

const SELECTOR_TABLE = '.expandable-table'
const SELECTOR_EXPANDABLE_BODY = '.expandable-body'
const SELECTOR_DATA_TOGGLE = '[data-widget="expandable-table"]'
const SELECTOR_ARIA_ATTR = 'aria-expanded'

/**
* Class Definition
* ====================================================
*/
class ExpandableTable {
constructor(element, options) {
this._options = options
this._element = element
}

// Public

init() {
$(SELECTOR_DATA_TOGGLE).each((_, $header) => {
const $type = $($header).attr(SELECTOR_ARIA_ATTR)
const $body = $($header).next(SELECTOR_EXPANDABLE_BODY).children().first().children()
if ($type === 'true') {
$body.show()
} else if ($type === 'false') {
$body.hide()
$body.parent().parent().addClass('d-none')
}
})
}

toggleRow() {
const $element = this._element
const time = 500
const $type = $element.attr(SELECTOR_ARIA_ATTR)
const $body = $element.next(SELECTOR_EXPANDABLE_BODY).children().first().children()

$body.stop()
if ($type === 'true') {
$body.slideUp(time, () => {
$element.next(SELECTOR_EXPANDABLE_BODY).addClass('d-none')
})
$element.attr(SELECTOR_ARIA_ATTR, 'false')
$element.trigger($.Event(EVENT_COLLAPSED))
} else if ($type === 'false') {
$element.next(SELECTOR_EXPANDABLE_BODY).removeClass('d-none')
$body.slideDown(time)
$element.attr(SELECTOR_ARIA_ATTR, 'true')
$element.trigger($.Event(EVENT_EXPANDED))
}
}

// Static

static _jQueryInterface(operation) {
return this.each(function () {
let data = $(this).data(DATA_KEY)

if (!data) {
data = new ExpandableTable($(this))
$(this).data(DATA_KEY, data)
}

if (typeof operation === 'string' && /init|toggleRow/.test(operation)) {
data[operation]()
}
})
}
}

/**
* Data API
* ====================================================
*/
$(SELECTOR_TABLE).ready(function () {
ExpandableTable._jQueryInterface.call($(this), 'init')
})

$(document).on('click', SELECTOR_DATA_TOGGLE, function () {
ExpandableTable._jQueryInterface.call($(this), 'toggleRow')
})

/**
* jQuery API
* ====================================================
*/

$.fn[NAME] = ExpandableTable._jQueryInterface
$.fn[NAME].Constructor = ExpandableTable
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT
return ExpandableTable._jQueryInterface
}

export default ExpandableTable

+ 117
- 0
MVCTemplate/wwwroot/build/js/Fullscreen.js Zobrazit soubor

@@ -0,0 +1,117 @@
/**
* --------------------------------------------
* AdminLTE Fullscreen.js
* License MIT
* --------------------------------------------
*/

import $ from 'jquery'

/**
* Constants
* ====================================================
*/

const NAME = 'Fullscreen'
const DATA_KEY = 'lte.fullscreen'
const JQUERY_NO_CONFLICT = $.fn[NAME]

const SELECTOR_DATA_WIDGET = '[data-widget="fullscreen"]'
const SELECTOR_ICON = `${SELECTOR_DATA_WIDGET} i`

const Default = {
minimizeIcon: 'fa-compress-arrows-alt',
maximizeIcon: 'fa-expand-arrows-alt'
}

/**
* Class Definition
* ====================================================
*/

class Fullscreen {
constructor(_element, _options) {
this.element = _element
this.options = $.extend({}, Default, _options)
}

// Public

toggle() {
if (document.fullscreenElement ||
document.mozFullScreenElement ||
document.webkitFullscreenElement ||
document.msFullscreenElement) {
this.windowed()
} else {
this.fullscreen()
}
}

fullscreen() {
if (document.documentElement.requestFullscreen) {
document.documentElement.requestFullscreen()
} else if (document.documentElement.webkitRequestFullscreen) {
document.documentElement.webkitRequestFullscreen()
} else if (document.documentElement.msRequestFullscreen) {
document.documentElement.msRequestFullscreen()
}

$(SELECTOR_ICON).removeClass(this.options.maximizeIcon).addClass(this.options.minimizeIcon)
}

windowed() {
if (document.exitFullscreen) {
document.exitFullscreen()
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen()
} else if (document.msExitFullscreen) {
document.msExitFullscreen()
}

$(SELECTOR_ICON).removeClass(this.options.minimizeIcon).addClass(this.options.maximizeIcon)
}

// Static

static _jQueryInterface(config) {
let data = $(this).data(DATA_KEY)

if (!data) {
data = $(this).data()
}

const _options = $.extend({}, Default, typeof config === 'object' ? config : data)
const plugin = new Fullscreen($(this), _options)

$(this).data(DATA_KEY, typeof config === 'object' ? config : data)

if (typeof config === 'string' && /toggle|fullscreen|windowed/.test(config)) {
plugin[config]()
} else {
plugin.init()
}
}
}

/**
* Data API
* ====================================================
*/
$(document).on('click', SELECTOR_DATA_WIDGET, function () {
Fullscreen._jQueryInterface.call($(this), 'toggle')
})

/**
* jQuery API
* ====================================================
*/

$.fn[NAME] = Fullscreen._jQueryInterface
$.fn[NAME].Constructor = Fullscreen
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT
return Fullscreen._jQueryInterface
}

export default Fullscreen

+ 413
- 0
MVCTemplate/wwwroot/build/js/IFrame.js Zobrazit soubor

@@ -0,0 +1,413 @@
/**
* --------------------------------------------
* AdminLTE IFrame.js
* License MIT
* --------------------------------------------
*/

import $ from 'jquery'

/**
* Constants
* ====================================================
*/

const NAME = 'IFrame'
const DATA_KEY = 'lte.iframe'
const JQUERY_NO_CONFLICT = $.fn[NAME]

const SELECTOR_DATA_TOGGLE = '[data-widget="iframe"]'
const SELECTOR_DATA_TOGGLE_CLOSE = '[data-widget="iframe-close"]'
const SELECTOR_DATA_TOGGLE_SCROLL_LEFT = '[data-widget="iframe-scrollleft"]'
const SELECTOR_DATA_TOGGLE_SCROLL_RIGHT = '[data-widget="iframe-scrollright"]'
const SELECTOR_DATA_TOGGLE_FULLSCREEN = '[data-widget="iframe-fullscreen"]'
const SELECTOR_CONTENT_WRAPPER = '.content-wrapper'
const SELECTOR_CONTENT_IFRAME = `${SELECTOR_CONTENT_WRAPPER} iframe`
const SELECTOR_TAB_NAV = `${SELECTOR_DATA_TOGGLE}.iframe-mode .nav`
const SELECTOR_TAB_NAVBAR_NAV = `${SELECTOR_DATA_TOGGLE}.iframe-mode .navbar-nav`
const SELECTOR_TAB_NAVBAR_NAV_ITEM = `${SELECTOR_TAB_NAVBAR_NAV} .nav-item`
const SELECTOR_TAB_NAVBAR_NAV_LINK = `${SELECTOR_TAB_NAVBAR_NAV} .nav-link`
const SELECTOR_TAB_CONTENT = `${SELECTOR_DATA_TOGGLE}.iframe-mode .tab-content`
const SELECTOR_TAB_EMPTY = `${SELECTOR_TAB_CONTENT} .tab-empty`
const SELECTOR_TAB_LOADING = `${SELECTOR_TAB_CONTENT} .tab-loading`
const SELECTOR_TAB_PANE = `${SELECTOR_TAB_CONTENT} .tab-pane`
const SELECTOR_SIDEBAR_MENU_ITEM = '.main-sidebar .nav-item > a.nav-link'
const SELECTOR_SIDEBAR_SEARCH_ITEM = '.sidebar-search-results .list-group-item'
const SELECTOR_HEADER_MENU_ITEM = '.main-header .nav-item a.nav-link'
const SELECTOR_HEADER_DROPDOWN_ITEM = '.main-header a.dropdown-item'
const CLASS_NAME_IFRAME_MODE = 'iframe-mode'
const CLASS_NAME_FULLSCREEN_MODE = 'iframe-mode-fullscreen'

const Default = {
onTabClick(item) {
return item
},
onTabChanged(item) {
return item
},
onTabCreated(item) {
return item
},
autoIframeMode: true,
autoItemActive: true,
autoShowNewTab: true,
allowDuplicates: false,
loadingScreen: true,
useNavbarItems: true,
scrollOffset: 40,
scrollBehaviorSwap: false,
iconMaximize: 'fa-expand',
iconMinimize: 'fa-compress'
}

/**
* Class Definition
* ====================================================
*/

class IFrame {
constructor(element, config) {
this._config = config
this._element = element

this._init()
}

// Public

onTabClick(item) {
this._config.onTabClick(item)
}

onTabChanged(item) {
this._config.onTabChanged(item)
}

onTabCreated(item) {
this._config.onTabCreated(item)
}

createTab(title, link, uniqueName, autoOpen) {
let tabId = `panel-${uniqueName}`
let navId = `tab-${uniqueName}`

if (this._config.allowDuplicates) {
tabId += `-${Math.floor(Math.random() * 1000)}`
navId += `-${Math.floor(Math.random() * 1000)}`
}

const newNavItem = `<li class="nav-item" role="presentation"><a href="#" class="btn-iframe-close" data-widget="iframe-close" data-type="only-this"><i class="fas fa-times"></i></a><a class="nav-link" data-toggle="row" id="${navId}" href="#${tabId}" role="tab" aria-controls="${tabId}" aria-selected="false">${title}</a></li>`
$(SELECTOR_TAB_NAVBAR_NAV).append(unescape(escape(newNavItem)))

const newTabItem = `<div class="tab-pane fade" id="${tabId}" role="tabpanel" aria-labelledby="${navId}"><iframe src="${link}"></iframe></div>`
$(SELECTOR_TAB_CONTENT).append(unescape(escape(newTabItem)))

if (autoOpen) {
if (this._config.loadingScreen) {
const $loadingScreen = $(SELECTOR_TAB_LOADING)
$loadingScreen.fadeIn()
$(`${tabId} iframe`).ready(() => {
if (typeof this._config.loadingScreen === 'number') {
this.switchTab(`#${navId}`)
setTimeout(() => {
$loadingScreen.fadeOut()
}, this._config.loadingScreen)
} else {
this.switchTab(`#${navId}`)
$loadingScreen.fadeOut()
}
})
} else {
this.switchTab(`#${navId}`)
}
}

this.onTabCreated($(`#${navId}`))
}

openTabSidebar(item, autoOpen = this._config.autoShowNewTab) {
let $item = $(item).clone()
if ($item.attr('href') === undefined) {
$item = $(item).parent('a').clone()
}

$item.find('.right, .search-path').remove()
let title = $item.find('p').text()
if (title === '') {
title = $item.text()
}

const link = $item.attr('href')
if (link === '#' || link === '' || link === undefined) {
return
}

const uniqueName = link.replace('./', '').replace(/["&'./:=?[\]]/gi, '-').replace(/(--)/gi, '')
const navId = `tab-${uniqueName}`

if (!this._config.allowDuplicates && $(`#${navId}`).length > 0) {
return this.switchTab(`#${navId}`)
}

if ((!this._config.allowDuplicates && $(`#${navId}`).length === 0) || this._config.allowDuplicates) {
this.createTab(title, link, uniqueName, autoOpen)
}
}

switchTab(item) {
const $item = $(item)
const tabId = $item.attr('href')

$(SELECTOR_TAB_EMPTY).hide()
$(`${SELECTOR_TAB_NAVBAR_NAV} .active`).tab('dispose').removeClass('active')
this._fixHeight()

$item.tab('show')
$item.parents('li').addClass('active')
this.onTabChanged($item)

if (this._config.autoItemActive) {
this._setItemActive($(`${tabId} iframe`).attr('src'))
}
}

removeActiveTab(type, element) {
if (type == 'all') {
$(SELECTOR_TAB_NAVBAR_NAV_ITEM).remove()
$(SELECTOR_TAB_PANE).remove()
$(SELECTOR_TAB_EMPTY).show()
} else if (type == 'all-other') {
$(`${SELECTOR_TAB_NAVBAR_NAV_ITEM}:not(.active)`).remove()
$(`${SELECTOR_TAB_PANE}:not(.active)`).remove()
} else if (type == 'only-this') {
const $navClose = $(element)
const $navItem = $navClose.parent('.nav-item')
const $navItemParent = $navItem.parent()
const navItemIndex = $navItem.index()
const tabId = $navClose.siblings('.nav-link').attr('aria-controls')
$navItem.remove()
$(`#${tabId}`).remove()
if ($(SELECTOR_TAB_CONTENT).children().length == $(`${SELECTOR_TAB_EMPTY}, ${SELECTOR_TAB_LOADING}`).length) {
$(SELECTOR_TAB_EMPTY).show()
} else {
const prevNavItemIndex = navItemIndex - 1
this.switchTab($navItemParent.children().eq(prevNavItemIndex).find('a.nav-link'))
}
} else {
const $navItem = $(`${SELECTOR_TAB_NAVBAR_NAV_ITEM}.active`)
const $navItemParent = $navItem.parent()
const navItemIndex = $navItem.index()
$navItem.remove()
$(`${SELECTOR_TAB_PANE}.active`).remove()
if ($(SELECTOR_TAB_CONTENT).children().length == $(`${SELECTOR_TAB_EMPTY}, ${SELECTOR_TAB_LOADING}`).length) {
$(SELECTOR_TAB_EMPTY).show()
} else {
const prevNavItemIndex = navItemIndex - 1
this.switchTab($navItemParent.children().eq(prevNavItemIndex).find('a.nav-link'))
}
}
}

toggleFullscreen() {
if ($('body').hasClass(CLASS_NAME_FULLSCREEN_MODE)) {
$(`${SELECTOR_DATA_TOGGLE_FULLSCREEN} i`).removeClass(this._config.iconMinimize).addClass(this._config.iconMaximize)
$('body').removeClass(CLASS_NAME_FULLSCREEN_MODE)
$(`${SELECTOR_TAB_EMPTY}, ${SELECTOR_TAB_LOADING}`).height('auto')
$(SELECTOR_CONTENT_WRAPPER).height('auto')
$(SELECTOR_CONTENT_IFRAME).height('auto')
} else {
$(`${SELECTOR_DATA_TOGGLE_FULLSCREEN} i`).removeClass(this._config.iconMaximize).addClass(this._config.iconMinimize)
$('body').addClass(CLASS_NAME_FULLSCREEN_MODE)
}

$(window).trigger('resize')
this._fixHeight(true)
}

// Private

_init() {
if (window.frameElement && this._config.autoIframeMode) {
$('body').addClass(CLASS_NAME_IFRAME_MODE)
} else if ($(SELECTOR_CONTENT_WRAPPER).hasClass(CLASS_NAME_IFRAME_MODE)) {
if ($(SELECTOR_TAB_CONTENT).children().length > 2) {
const $el = $(`${SELECTOR_TAB_PANE}:first-child`)
$el.show()
this._setItemActive($el.find('iframe').attr('src'))
}

this._setupListeners()
this._fixHeight(true)
}
}

_navScroll(offset) {
const leftPos = $(SELECTOR_TAB_NAVBAR_NAV).scrollLeft()
$(SELECTOR_TAB_NAVBAR_NAV).animate({ scrollLeft: (leftPos + offset) }, 250, 'linear')
}

_setupListeners() {
$(window).on('resize', () => {
setTimeout(() => {
this._fixHeight()
}, 1)
})
$(document).on('click', `${SELECTOR_SIDEBAR_MENU_ITEM}, ${SELECTOR_SIDEBAR_SEARCH_ITEM}`, e => {
e.preventDefault()
this.openTabSidebar(e.target)
})

if (this._config.useNavbarItems) {
$(document).on('click', `${SELECTOR_HEADER_MENU_ITEM}, ${SELECTOR_HEADER_DROPDOWN_ITEM}`, e => {
e.preventDefault()
this.openTabSidebar(e.target)
})
}

$(document).on('click', SELECTOR_TAB_NAVBAR_NAV_LINK, e => {
e.preventDefault()
this.onTabClick(e.target)
this.switchTab(e.target)
})
$(document).on('click', SELECTOR_TAB_NAVBAR_NAV_LINK, e => {
e.preventDefault()
this.onTabClick(e.target)
this.switchTab(e.target)
})
$(document).on('click', SELECTOR_DATA_TOGGLE_CLOSE, e => {
e.preventDefault()
let { target } = e

if (target.nodeName == 'I') {
target = e.target.offsetParent
}

this.removeActiveTab(target.attributes['data-type'] ? target.attributes['data-type'].nodeValue : null, target)
})
$(document).on('click', SELECTOR_DATA_TOGGLE_FULLSCREEN, e => {
e.preventDefault()
this.toggleFullscreen()
})
let mousedown = false
let mousedownInterval = null
$(document).on('mousedown', SELECTOR_DATA_TOGGLE_SCROLL_LEFT, e => {
e.preventDefault()
clearInterval(mousedownInterval)

let { scrollOffset } = this._config

if (!this._config.scrollBehaviorSwap) {
scrollOffset = -scrollOffset
}

mousedown = true
this._navScroll(scrollOffset)

mousedownInterval = setInterval(() => {
this._navScroll(scrollOffset)
}, 250)
})
$(document).on('mousedown', SELECTOR_DATA_TOGGLE_SCROLL_RIGHT, e => {
e.preventDefault()
clearInterval(mousedownInterval)

let { scrollOffset } = this._config

if (this._config.scrollBehaviorSwap) {
scrollOffset = -scrollOffset
}

mousedown = true
this._navScroll(scrollOffset)

mousedownInterval = setInterval(() => {
this._navScroll(scrollOffset)
}, 250)
})
$(document).on('mouseup', () => {
if (mousedown) {
mousedown = false
clearInterval(mousedownInterval)
mousedownInterval = null
}
})
}

_setItemActive(href) {
$(`${SELECTOR_SIDEBAR_MENU_ITEM}, ${SELECTOR_HEADER_DROPDOWN_ITEM}`).removeClass('active')
$(SELECTOR_HEADER_MENU_ITEM).parent().removeClass('active')

const $headerMenuItem = $(`${SELECTOR_HEADER_MENU_ITEM}[href$="${href}"]`)
const $headerDropdownItem = $(`${SELECTOR_HEADER_DROPDOWN_ITEM}[href$="${href}"]`)
const $sidebarMenuItem = $(`${SELECTOR_SIDEBAR_MENU_ITEM}[href$="${href}"]`)

$headerMenuItem.each((i, e) => {
$(e).parent().addClass('active')
})
$headerDropdownItem.each((i, e) => {
$(e).addClass('active')
})
$sidebarMenuItem.each((i, e) => {
$(e).addClass('active')
$(e).parents('.nav-treeview').prevAll('.nav-link').addClass('active')
})
}

_fixHeight(tabEmpty = false) {
if ($('body').hasClass(CLASS_NAME_FULLSCREEN_MODE)) {
const windowHeight = $(window).height()
const navbarHeight = $(SELECTOR_TAB_NAV).outerHeight()
$(`${SELECTOR_TAB_EMPTY}, ${SELECTOR_TAB_LOADING}, ${SELECTOR_CONTENT_IFRAME}`).height(windowHeight - navbarHeight)
$(SELECTOR_CONTENT_WRAPPER).height(windowHeight)
} else {
const contentWrapperHeight = parseFloat($(SELECTOR_CONTENT_WRAPPER).css('height'))
const navbarHeight = $(SELECTOR_TAB_NAV).outerHeight()
if (tabEmpty == true) {
setTimeout(() => {
$(`${SELECTOR_TAB_EMPTY}, ${SELECTOR_TAB_LOADING}`).height(contentWrapperHeight - navbarHeight)
}, 50)
} else {
$(SELECTOR_CONTENT_IFRAME).height(contentWrapperHeight - navbarHeight)
}
}
}

// Static

static _jQueryInterface(operation, ...args) {
let data = $(this).data(DATA_KEY)
const _options = $.extend({}, Default, $(this).data())

if (!data) {
data = new IFrame(this, _options)
$(this).data(DATA_KEY, data)
}

if (typeof operation === 'string' && /createTab|openTabSidebar|switchTab|removeActiveTab/.test(operation)) {
data[operation](...args)
}
}
}

/**
* Data API
* ====================================================
*/

$(window).on('load', () => {
IFrame._jQueryInterface.call($(SELECTOR_DATA_TOGGLE))
})

/**
* jQuery API
* ====================================================
*/

$.fn[NAME] = IFrame._jQueryInterface
$.fn[NAME].Constructor = IFrame
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT
return IFrame._jQueryInterface
}

export default IFrame

+ 257
- 0
MVCTemplate/wwwroot/build/js/Layout.js Zobrazit soubor

@@ -0,0 +1,257 @@
/**
* --------------------------------------------
* AdminLTE Layout.js
* License MIT
* --------------------------------------------
*/

import $ from 'jquery'

/**
* Constants
* ====================================================
*/

const NAME = 'Layout'
const DATA_KEY = 'lte.layout'
const JQUERY_NO_CONFLICT = $.fn[NAME]

const SELECTOR_HEADER = '.main-header'
const SELECTOR_MAIN_SIDEBAR = '.main-sidebar'
const SELECTOR_SIDEBAR = '.main-sidebar .sidebar'
const SELECTOR_CONTENT = '.content-wrapper'
const SELECTOR_CONTROL_SIDEBAR_CONTENT = '.control-sidebar-content'
const SELECTOR_CONTROL_SIDEBAR_BTN = '[data-widget="control-sidebar"]'
const SELECTOR_FOOTER = '.main-footer'
const SELECTOR_PUSHMENU_BTN = '[data-widget="pushmenu"]'
const SELECTOR_LOGIN_BOX = '.login-box'
const SELECTOR_REGISTER_BOX = '.register-box'
const SELECTOR_PRELOADER = '.preloader'

const CLASS_NAME_SIDEBAR_COLLAPSED = 'sidebar-collapse'
const CLASS_NAME_SIDEBAR_FOCUSED = 'sidebar-focused'
const CLASS_NAME_LAYOUT_FIXED = 'layout-fixed'
const CLASS_NAME_CONTROL_SIDEBAR_SLIDE_OPEN = 'control-sidebar-slide-open'
const CLASS_NAME_CONTROL_SIDEBAR_OPEN = 'control-sidebar-open'

const Default = {
scrollbarTheme: 'os-theme-light',
scrollbarAutoHide: 'l',
panelAutoHeight: true,
panelAutoHeightMode: 'min-height',
preloadDuration: 200,
loginRegisterAutoHeight: true
}

/**
* Class Definition
* ====================================================
*/

class Layout {
constructor(element, config) {
this._config = config
this._element = element
}

// Public

fixLayoutHeight(extra = null) {
const $body = $('body')
let controlSidebar = 0

if ($body.hasClass(CLASS_NAME_CONTROL_SIDEBAR_SLIDE_OPEN) || $body.hasClass(CLASS_NAME_CONTROL_SIDEBAR_OPEN) || extra === 'control_sidebar') {
controlSidebar = $(SELECTOR_CONTROL_SIDEBAR_CONTENT).outerHeight()
}

const heights = {
window: $(window).height(),
header: $(SELECTOR_HEADER).length > 0 ? $(SELECTOR_HEADER).outerHeight() : 0,
footer: $(SELECTOR_FOOTER).length > 0 ? $(SELECTOR_FOOTER).outerHeight() : 0,
sidebar: $(SELECTOR_SIDEBAR).length > 0 ? $(SELECTOR_SIDEBAR).height() : 0,
controlSidebar
}

const max = this._max(heights)
let offset = this._config.panelAutoHeight

if (offset === true) {
offset = 0
}

const $contentSelector = $(SELECTOR_CONTENT)

if (offset !== false) {
if (max === heights.controlSidebar) {
$contentSelector.css(this._config.panelAutoHeightMode, (max + offset))
} else if (max === heights.window) {
$contentSelector.css(this._config.panelAutoHeightMode, (max + offset) - heights.header - heights.footer)
} else {
$contentSelector.css(this._config.panelAutoHeightMode, (max + offset) - heights.header)
}

if (this._isFooterFixed()) {
$contentSelector.css(this._config.panelAutoHeightMode, parseFloat($contentSelector.css(this._config.panelAutoHeightMode)) + heights.footer)
}
}

if (!$body.hasClass(CLASS_NAME_LAYOUT_FIXED)) {
return
}

if (typeof $.fn.overlayScrollbars !== 'undefined') {
$(SELECTOR_SIDEBAR).overlayScrollbars({
className: this._config.scrollbarTheme,
sizeAutoCapable: true,
scrollbars: {
autoHide: this._config.scrollbarAutoHide,
clickScrolling: true
}
})
} else {
$(SELECTOR_SIDEBAR).css('overflow-y', 'auto')
}
}

fixLoginRegisterHeight() {
const $body = $('body')
const $selector = $(`${SELECTOR_LOGIN_BOX}, ${SELECTOR_REGISTER_BOX}`)

if ($selector.length === 0) {
$body.css('height', 'auto')
$('html').css('height', 'auto')
} else {
const boxHeight = $selector.height()

if ($body.css(this._config.panelAutoHeightMode) !== boxHeight) {
$body.css(this._config.panelAutoHeightMode, boxHeight)
}
}
}

// Private

_init() {
// Activate layout height watcher
this.fixLayoutHeight()

if (this._config.loginRegisterAutoHeight === true) {
this.fixLoginRegisterHeight()
} else if (this._config.loginRegisterAutoHeight === parseInt(this._config.loginRegisterAutoHeight, 10)) {
setInterval(this.fixLoginRegisterHeight, this._config.loginRegisterAutoHeight)
}

$(SELECTOR_SIDEBAR)
.on('collapsed.lte.treeview expanded.lte.treeview', () => {
this.fixLayoutHeight()
})

$(SELECTOR_MAIN_SIDEBAR)
.on('mouseenter mouseleave', () => {
if ($('body').hasClass(CLASS_NAME_SIDEBAR_COLLAPSED)) {
this.fixLayoutHeight()
}
})

$(SELECTOR_PUSHMENU_BTN)
.on('collapsed.lte.pushmenu shown.lte.pushmenu', () => {
setTimeout(() => {
this.fixLayoutHeight()
}, 300)
})

$(SELECTOR_CONTROL_SIDEBAR_BTN)
.on('collapsed.lte.controlsidebar', () => {
this.fixLayoutHeight()
})
.on('expanded.lte.controlsidebar', () => {
this.fixLayoutHeight('control_sidebar')
})

$(window).resize(() => {
this.fixLayoutHeight()
})

setTimeout(() => {
$('body.hold-transition').removeClass('hold-transition')
}, 50)

setTimeout(() => {
const $preloader = $(SELECTOR_PRELOADER)
if ($preloader) {
$preloader.css('height', 0)
setTimeout(() => {
$preloader.children().hide()
}, 200)
}
}, this._config.preloadDuration)
}

_max(numbers) {
// Calculate the maximum number in a list
let max = 0

Object.keys(numbers).forEach(key => {
if (numbers[key] > max) {
max = numbers[key]
}
})

return max
}

_isFooterFixed() {
return $(SELECTOR_FOOTER).css('position') === 'fixed'
}

// Static

static _jQueryInterface(config = '') {
return this.each(function () {
let data = $(this).data(DATA_KEY)
const _options = $.extend({}, Default, $(this).data())

if (!data) {
data = new Layout($(this), _options)
$(this).data(DATA_KEY, data)
}

if (config === 'init' || config === '') {
data._init()
} else if (config === 'fixLayoutHeight' || config === 'fixLoginRegisterHeight') {
data[config]()
}
})
}
}

/**
* Data API
* ====================================================
*/

$(window).on('load', () => {
Layout._jQueryInterface.call($('body'))
})

$(`${SELECTOR_SIDEBAR} a`)
.on('focusin', () => {
$(SELECTOR_MAIN_SIDEBAR).addClass(CLASS_NAME_SIDEBAR_FOCUSED)
})
.on('focusout', () => {
$(SELECTOR_MAIN_SIDEBAR).removeClass(CLASS_NAME_SIDEBAR_FOCUSED)
})

/**
* jQuery API
* ====================================================
*/

$.fn[NAME] = Layout._jQueryInterface
$.fn[NAME].Constructor = Layout
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT
return Layout._jQueryInterface
}

export default Layout

+ 113
- 0
MVCTemplate/wwwroot/build/js/NavbarSearch.js Zobrazit soubor

@@ -0,0 +1,113 @@
/**
* --------------------------------------------
* AdminLTE NavbarSearch.js
* License MIT
* --------------------------------------------
*/

import $ from 'jquery'

/**
* Constants
* ====================================================
*/

const NAME = 'NavbarSearch'
const DATA_KEY = 'lte.navbar-search'
const JQUERY_NO_CONFLICT = $.fn[NAME]

const SELECTOR_TOGGLE_BUTTON = '[data-widget="navbar-search"]'
const SELECTOR_SEARCH_BLOCK = '.navbar-search-block'
const SELECTOR_SEARCH_INPUT = '.form-control'

const CLASS_NAME_OPEN = 'navbar-search-open'

const Default = {
resetOnClose: true,
target: SELECTOR_SEARCH_BLOCK
}

/**
* Class Definition
* ====================================================
*/

class NavbarSearch {
constructor(_element, _options) {
this._element = _element
this._config = $.extend({}, Default, _options)
}

// Public

open() {
$(this._config.target).css('display', 'flex').hide().fadeIn().addClass(CLASS_NAME_OPEN)
$(`${this._config.target} ${SELECTOR_SEARCH_INPUT}`).focus()
}

close() {
$(this._config.target).fadeOut().removeClass(CLASS_NAME_OPEN)

if (this._config.resetOnClose) {
$(`${this._config.target} ${SELECTOR_SEARCH_INPUT}`).val('')
}
}

toggle() {
if ($(this._config.target).hasClass(CLASS_NAME_OPEN)) {
this.close()
} else {
this.open()
}
}

// Static

static _jQueryInterface(options) {
return this.each(function () {
let data = $(this).data(DATA_KEY)
const _options = $.extend({}, Default, $(this).data())

if (!data) {
data = new NavbarSearch(this, _options)
$(this).data(DATA_KEY, data)
}

if (!/toggle|close|open/.test(options)) {
throw new Error(`Undefined method ${options}`)
}

data[options]()
})
}
}

/**
* Data API
* ====================================================
*/
$(document).on('click', SELECTOR_TOGGLE_BUTTON, event => {
event.preventDefault()

let button = $(event.currentTarget)

if (button.data('widget') !== 'navbar-search') {
button = button.closest(SELECTOR_TOGGLE_BUTTON)
}

NavbarSearch._jQueryInterface.call(button, 'toggle')
})

/**
* jQuery API
* ====================================================
*/

$.fn[NAME] = NavbarSearch._jQueryInterface
$.fn[NAME].Constructor = NavbarSearch
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT
return NavbarSearch._jQueryInterface
}

export default NavbarSearch

+ 223
- 0
MVCTemplate/wwwroot/build/js/PushMenu.js Zobrazit soubor

@@ -0,0 +1,223 @@
/**
* --------------------------------------------
* AdminLTE PushMenu.js
* License MIT
* --------------------------------------------
*/

import $ from 'jquery'

/**
* Constants
* ====================================================
*/

const NAME = 'PushMenu'
const DATA_KEY = 'lte.pushmenu'
const EVENT_KEY = `.${DATA_KEY}`
const JQUERY_NO_CONFLICT = $.fn[NAME]

const EVENT_COLLAPSED = `collapsed${EVENT_KEY}`
const EVENT_SHOWN = `shown${EVENT_KEY}`

const SELECTOR_TOGGLE_BUTTON = '[data-widget="pushmenu"]'
const SELECTOR_BODY = 'body'
const SELECTOR_OVERLAY = '#sidebar-overlay'
const SELECTOR_WRAPPER = '.wrapper'

const CLASS_NAME_COLLAPSED = 'sidebar-collapse'
const CLASS_NAME_OPEN = 'sidebar-open'
const CLASS_NAME_IS_OPENING = 'sidebar-is-opening'
const CLASS_NAME_CLOSED = 'sidebar-closed'

const Default = {
autoCollapseSize: 992,
enableRemember: false,
noTransitionAfterReload: true
}

/**
* Class Definition
* ====================================================
*/

class PushMenu {
constructor(element, options) {
this._element = element
this._options = $.extend({}, Default, options)

if ($(SELECTOR_OVERLAY).length === 0) {
this._addOverlay()
}

this._init()
}

// Public

expand() {
const $bodySelector = $(SELECTOR_BODY)

if (this._options.autoCollapseSize && $(window).width() <= this._options.autoCollapseSize) {
$bodySelector.addClass(CLASS_NAME_OPEN)
}

$bodySelector.addClass(CLASS_NAME_IS_OPENING).removeClass(`${CLASS_NAME_COLLAPSED} ${CLASS_NAME_CLOSED}`).delay(50).queue(function () {
$bodySelector.removeClass(CLASS_NAME_IS_OPENING)
$(this).dequeue()
})

if (this._options.enableRemember) {
localStorage.setItem(`remember${EVENT_KEY}`, CLASS_NAME_OPEN)
}

$(this._element).trigger($.Event(EVENT_SHOWN))
}

collapse() {
const $bodySelector = $(SELECTOR_BODY)

if (this._options.autoCollapseSize && $(window).width() <= this._options.autoCollapseSize) {
$bodySelector.removeClass(CLASS_NAME_OPEN).addClass(CLASS_NAME_CLOSED)
}

$bodySelector.addClass(CLASS_NAME_COLLAPSED)

if (this._options.enableRemember) {
localStorage.setItem(`remember${EVENT_KEY}`, CLASS_NAME_COLLAPSED)
}

$(this._element).trigger($.Event(EVENT_COLLAPSED))
}

toggle() {
if ($(SELECTOR_BODY).hasClass(CLASS_NAME_COLLAPSED)) {
this.expand()
} else {
this.collapse()
}
}

autoCollapse(resize = false) {
if (!this._options.autoCollapseSize) {
return
}

const $bodySelector = $(SELECTOR_BODY)

if ($(window).width() <= this._options.autoCollapseSize) {
if (!$bodySelector.hasClass(CLASS_NAME_OPEN)) {
this.collapse()
}
} else if (resize === true) {
if ($bodySelector.hasClass(CLASS_NAME_OPEN)) {
$bodySelector.removeClass(CLASS_NAME_OPEN)
} else if ($bodySelector.hasClass(CLASS_NAME_CLOSED)) {
this.expand()
}
}
}

remember() {
if (!this._options.enableRemember) {
return
}

const $body = $('body')
const toggleState = localStorage.getItem(`remember${EVENT_KEY}`)

if (toggleState === CLASS_NAME_COLLAPSED) {
if (this._options.noTransitionAfterReload) {
$body.addClass('hold-transition').addClass(CLASS_NAME_COLLAPSED).delay(50).queue(function () {
$(this).removeClass('hold-transition')
$(this).dequeue()
})
} else {
$body.addClass(CLASS_NAME_COLLAPSED)
}
} else if (this._options.noTransitionAfterReload) {
$body.addClass('hold-transition').removeClass(CLASS_NAME_COLLAPSED).delay(50).queue(function () {
$(this).removeClass('hold-transition')
$(this).dequeue()
})
} else {
$body.removeClass(CLASS_NAME_COLLAPSED)
}
}

// Private

_init() {
this.remember()
this.autoCollapse()

$(window).resize(() => {
this.autoCollapse(true)
})
}

_addOverlay() {
const overlay = $('<div />', {
id: 'sidebar-overlay'
})

overlay.on('click', () => {
this.collapse()
})

$(SELECTOR_WRAPPER).append(overlay)
}

// Static

static _jQueryInterface(operation) {
return this.each(function () {
let data = $(this).data(DATA_KEY)
const _options = $.extend({}, Default, $(this).data())

if (!data) {
data = new PushMenu(this, _options)
$(this).data(DATA_KEY, data)
}

if (typeof operation === 'string' && /collapse|expand|toggle/.test(operation)) {
data[operation]()
}
})
}
}

/**
* Data API
* ====================================================
*/

$(document).on('click', SELECTOR_TOGGLE_BUTTON, event => {
event.preventDefault()

let button = event.currentTarget

if ($(button).data('widget') !== 'pushmenu') {
button = $(button).closest(SELECTOR_TOGGLE_BUTTON)
}

PushMenu._jQueryInterface.call($(button), 'toggle')
})

$(window).on('load', () => {
PushMenu._jQueryInterface.call($(SELECTOR_TOGGLE_BUTTON))
})

/**
* jQuery API
* ====================================================
*/

$.fn[NAME] = PushMenu._jQueryInterface
$.fn[NAME].Constructor = PushMenu
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT
return PushMenu._jQueryInterface
}

export default PushMenu

+ 298
- 0
MVCTemplate/wwwroot/build/js/SidebarSearch.js Zobrazit soubor

@@ -0,0 +1,298 @@
/**
* --------------------------------------------
* AdminLTE SidebarSearch.js
* License MIT
* --------------------------------------------
*/

import $, { trim } from 'jquery'

/**
* Constants
* ====================================================
*/

const NAME = 'SidebarSearch'
const DATA_KEY = 'lte.sidebar-search'
const JQUERY_NO_CONFLICT = $.fn[NAME]

const CLASS_NAME_OPEN = 'sidebar-search-open'
const CLASS_NAME_ICON_SEARCH = 'fa-search'
const CLASS_NAME_ICON_CLOSE = 'fa-times'
const CLASS_NAME_HEADER = 'nav-header'
const CLASS_NAME_SEARCH_RESULTS = 'sidebar-search-results'
const CLASS_NAME_LIST_GROUP = 'list-group'

const SELECTOR_DATA_WIDGET = '[data-widget="sidebar-search"]'
const SELECTOR_SIDEBAR = '.main-sidebar .nav-sidebar'
const SELECTOR_NAV_LINK = '.nav-link'
const SELECTOR_NAV_TREEVIEW = '.nav-treeview'
const SELECTOR_SEARCH_INPUT = `${SELECTOR_DATA_WIDGET} .form-control`
const SELECTOR_SEARCH_BUTTON = `${SELECTOR_DATA_WIDGET} .btn`
const SELECTOR_SEARCH_ICON = `${SELECTOR_SEARCH_BUTTON} i`
const SELECTOR_SEARCH_LIST_GROUP = `.${CLASS_NAME_LIST_GROUP}`
const SELECTOR_SEARCH_RESULTS = `.${CLASS_NAME_SEARCH_RESULTS}`
const SELECTOR_SEARCH_RESULTS_GROUP = `${SELECTOR_SEARCH_RESULTS} .${CLASS_NAME_LIST_GROUP}`

const Default = {
arrowSign: '->',
minLength: 3,
maxResults: 7,
highlightName: true,
highlightPath: false,
highlightClass: 'text-light',
notFoundText: 'No element found!'
}

const SearchItems = []

/**
* Class Definition
* ====================================================
*/

class SidebarSearch {
constructor(_element, _options) {
this.element = _element
this.options = $.extend({}, Default, _options)
this.items = []
}

// Public

init() {
if ($(SELECTOR_DATA_WIDGET).length === 0) {
return
}

if ($(SELECTOR_DATA_WIDGET).next(SELECTOR_SEARCH_RESULTS).length === 0) {
$(SELECTOR_DATA_WIDGET).after(
$('<div />', { class: CLASS_NAME_SEARCH_RESULTS })
)
}

if ($(SELECTOR_SEARCH_RESULTS).children(SELECTOR_SEARCH_LIST_GROUP).length === 0) {
$(SELECTOR_SEARCH_RESULTS).append(
$('<div />', { class: CLASS_NAME_LIST_GROUP })
)
}

this._addNotFound()

$(SELECTOR_SIDEBAR).children().each((i, child) => {
this._parseItem(child)
})
}

search() {
const searchValue = $(SELECTOR_SEARCH_INPUT).val().toLowerCase()
if (searchValue.length < this.options.minLength) {
$(SELECTOR_SEARCH_RESULTS_GROUP).empty()
this._addNotFound()
this.close()
return
}

const searchResults = SearchItems.filter(item => (item.name).toLowerCase().includes(searchValue))
const endResults = $(searchResults.slice(0, this.options.maxResults))
$(SELECTOR_SEARCH_RESULTS_GROUP).empty()

if (endResults.length === 0) {
this._addNotFound()
} else {
endResults.each((i, result) => {
$(SELECTOR_SEARCH_RESULTS_GROUP).append(this._renderItem(escape(result.name), escape(result.link), result.path))
})
}

this.open()
}

open() {
$(SELECTOR_DATA_WIDGET).parent().addClass(CLASS_NAME_OPEN)
$(SELECTOR_SEARCH_ICON).removeClass(CLASS_NAME_ICON_SEARCH).addClass(CLASS_NAME_ICON_CLOSE)
}

close() {
$(SELECTOR_DATA_WIDGET).parent().removeClass(CLASS_NAME_OPEN)
$(SELECTOR_SEARCH_ICON).removeClass(CLASS_NAME_ICON_CLOSE).addClass(CLASS_NAME_ICON_SEARCH)
}

toggle() {
if ($(SELECTOR_DATA_WIDGET).parent().hasClass(CLASS_NAME_OPEN)) {
this.close()
} else {
this.open()
}
}

// Private

_parseItem(item, path = []) {
if ($(item).hasClass(CLASS_NAME_HEADER)) {
return
}

const itemObject = {}
const navLink = $(item).clone().find(`> ${SELECTOR_NAV_LINK}`)
const navTreeview = $(item).clone().find(`> ${SELECTOR_NAV_TREEVIEW}`)

const link = navLink.attr('href')
const name = navLink.find('p').children().remove().end().text()

itemObject.name = this._trimText(name)
itemObject.link = link
itemObject.path = path

if (navTreeview.length === 0) {
SearchItems.push(itemObject)
} else {
const newPath = itemObject.path.concat([itemObject.name])
navTreeview.children().each((i, child) => {
this._parseItem(child, newPath)
})
}
}

_trimText(text) {
return trim(text.replace(/(\r\n|\n|\r)/gm, ' '))
}

_renderItem(name, link, path) {
path = path.join(` ${this.options.arrowSign} `)
name = unescape(name)

if (this.options.highlightName || this.options.highlightPath) {
const searchValue = $(SELECTOR_SEARCH_INPUT).val().toLowerCase()
const regExp = new RegExp(searchValue, 'gi')

if (this.options.highlightName) {
name = name.replace(
regExp,
str => {
return `<strong class="${this.options.highlightClass}">${str}</strong>`
}
)
}

if (this.options.highlightPath) {
path = path.replace(
regExp,
str => {
return `<strong class="${this.options.highlightClass}">${str}</strong>`
}
)
}
}

const groupItemElement = $('<a/>', {
href: link,
class: 'list-group-item'
})
const searchTitleElement = $('<div/>', {
class: 'search-title'
}).html(name)
const searchPathElement = $('<div/>', {
class: 'search-path'
}).html(path)

groupItemElement.append(searchTitleElement).append(searchPathElement)

return groupItemElement
}

_addNotFound() {
$(SELECTOR_SEARCH_RESULTS_GROUP).append(this._renderItem(this.options.notFoundText, '#', []))
}

// Static

static _jQueryInterface(config) {
let data = $(this).data(DATA_KEY)

if (!data) {
data = $(this).data()
}

const _options = $.extend({}, Default, typeof config === 'object' ? config : data)
const plugin = new SidebarSearch($(this), _options)

$(this).data(DATA_KEY, typeof config === 'object' ? config : data)

if (typeof config === 'string' && /init|toggle|close|open|search/.test(config)) {
plugin[config]()
} else {
plugin.init()
}
}
}

/**
* Data API
* ====================================================
*/
$(document).on('click', SELECTOR_SEARCH_BUTTON, event => {
event.preventDefault()

SidebarSearch._jQueryInterface.call($(SELECTOR_DATA_WIDGET), 'toggle')
})

$(document).on('keyup', SELECTOR_SEARCH_INPUT, event => {
if (event.keyCode == 38) {
event.preventDefault()
$(SELECTOR_SEARCH_RESULTS_GROUP).children().last().focus()
return
}

if (event.keyCode == 40) {
event.preventDefault()
$(SELECTOR_SEARCH_RESULTS_GROUP).children().first().focus()
return
}

setTimeout(() => {
SidebarSearch._jQueryInterface.call($(SELECTOR_DATA_WIDGET), 'search')
}, 100)
})

$(document).on('keydown', SELECTOR_SEARCH_RESULTS_GROUP, event => {
const $focused = $(':focus')

if (event.keyCode == 38) {
event.preventDefault()

if ($focused.is(':first-child')) {
$focused.siblings().last().focus()
} else {
$focused.prev().focus()
}
}

if (event.keyCode == 40) {
event.preventDefault()

if ($focused.is(':last-child')) {
$focused.siblings().first().focus()
} else {
$focused.next().focus()
}
}
})

$(window).on('load', () => {
SidebarSearch._jQueryInterface.call($(SELECTOR_DATA_WIDGET), 'init')
})

/**
* jQuery API
* ====================================================
*/

$.fn[NAME] = SidebarSearch._jQueryInterface
$.fn[NAME].Constructor = SidebarSearch
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT
return SidebarSearch._jQueryInterface
}

export default SidebarSearch

+ 209
- 0
MVCTemplate/wwwroot/build/js/Toasts.js Zobrazit soubor

@@ -0,0 +1,209 @@
/**
* --------------------------------------------
* AdminLTE Toasts.js
* License MIT
* --------------------------------------------
*/

import $ from 'jquery'

/**
* Constants
* ====================================================
*/

const NAME = 'Toasts'
const DATA_KEY = 'lte.toasts'
const EVENT_KEY = `.${DATA_KEY}`
const JQUERY_NO_CONFLICT = $.fn[NAME]

const EVENT_INIT = `init${EVENT_KEY}`
const EVENT_CREATED = `created${EVENT_KEY}`
const EVENT_REMOVED = `removed${EVENT_KEY}`

const SELECTOR_CONTAINER_TOP_RIGHT = '#toastsContainerTopRight'
const SELECTOR_CONTAINER_TOP_LEFT = '#toastsContainerTopLeft'
const SELECTOR_CONTAINER_BOTTOM_RIGHT = '#toastsContainerBottomRight'
const SELECTOR_CONTAINER_BOTTOM_LEFT = '#toastsContainerBottomLeft'

const CLASS_NAME_TOP_RIGHT = 'toasts-top-right'
const CLASS_NAME_TOP_LEFT = 'toasts-top-left'
const CLASS_NAME_BOTTOM_RIGHT = 'toasts-bottom-right'
const CLASS_NAME_BOTTOM_LEFT = 'toasts-bottom-left'

const POSITION_TOP_RIGHT = 'topRight'
const POSITION_TOP_LEFT = 'topLeft'
const POSITION_BOTTOM_RIGHT = 'bottomRight'
const POSITION_BOTTOM_LEFT = 'bottomLeft'

const Default = {
position: POSITION_TOP_RIGHT,
fixed: true,
autohide: false,
autoremove: true,
delay: 1000,
fade: true,
icon: null,
image: null,
imageAlt: null,
imageHeight: '25px',
title: null,
subtitle: null,
close: true,
body: null,
class: null
}

/**
* Class Definition
* ====================================================
*/
class Toasts {
constructor(element, config) {
this._config = config
this._prepareContainer()

$('body').trigger($.Event(EVENT_INIT))
}

// Public

create() {
const toast = $('<div class="toast" role="alert" aria-live="assertive" aria-atomic="true"/>')

toast.data('autohide', this._config.autohide)
toast.data('animation', this._config.fade)

if (this._config.class) {
toast.addClass(this._config.class)
}

if (this._config.delay && this._config.delay != 500) {
toast.data('delay', this._config.delay)
}

const toastHeader = $('<div class="toast-header">')

if (this._config.image != null) {
const toastImage = $('<img />').addClass('rounded mr-2').attr('src', this._config.image).attr('alt', this._config.imageAlt)

if (this._config.imageHeight != null) {
toastImage.height(this._config.imageHeight).width('auto')
}

toastHeader.append(toastImage)
}

if (this._config.icon != null) {
toastHeader.append($('<i />').addClass('mr-2').addClass(this._config.icon))
}

if (this._config.title != null) {
toastHeader.append($('<strong />').addClass('mr-auto').html(this._config.title))
}

if (this._config.subtitle != null) {
toastHeader.append($('<small />').html(this._config.subtitle))
}

if (this._config.close == true) {
const toastClose = $('<button data-dismiss="toast" />').attr('type', 'button').addClass('ml-2 mb-1 close').attr('aria-label', 'Close').append('<span aria-hidden="true">&times;</span>')

if (this._config.title == null) {
toastClose.toggleClass('ml-2 ml-auto')
}

toastHeader.append(toastClose)
}

toast.append(toastHeader)

if (this._config.body != null) {
toast.append($('<div class="toast-body" />').html(this._config.body))
}

$(this._getContainerId()).prepend(toast)

const $body = $('body')

$body.trigger($.Event(EVENT_CREATED))
toast.toast('show')

if (this._config.autoremove) {
toast.on('hidden.bs.toast', function () {
$(this).delay(200).remove()
$body.trigger($.Event(EVENT_REMOVED))
})
}
}

// Static

_getContainerId() {
if (this._config.position == POSITION_TOP_RIGHT) {
return SELECTOR_CONTAINER_TOP_RIGHT
}

if (this._config.position == POSITION_TOP_LEFT) {
return SELECTOR_CONTAINER_TOP_LEFT
}

if (this._config.position == POSITION_BOTTOM_RIGHT) {
return SELECTOR_CONTAINER_BOTTOM_RIGHT
}

if (this._config.position == POSITION_BOTTOM_LEFT) {
return SELECTOR_CONTAINER_BOTTOM_LEFT
}
}

_prepareContainer() {
if ($(this._getContainerId()).length === 0) {
const container = $('<div />').attr('id', this._getContainerId().replace('#', ''))
if (this._config.position == POSITION_TOP_RIGHT) {
container.addClass(CLASS_NAME_TOP_RIGHT)
} else if (this._config.position == POSITION_TOP_LEFT) {
container.addClass(CLASS_NAME_TOP_LEFT)
} else if (this._config.position == POSITION_BOTTOM_RIGHT) {
container.addClass(CLASS_NAME_BOTTOM_RIGHT)
} else if (this._config.position == POSITION_BOTTOM_LEFT) {
container.addClass(CLASS_NAME_BOTTOM_LEFT)
}

$('body').append(container)
}

if (this._config.fixed) {
$(this._getContainerId()).addClass('fixed')
} else {
$(this._getContainerId()).removeClass('fixed')
}
}

// Static

static _jQueryInterface(option, config) {
return this.each(function () {
const _options = $.extend({}, Default, config)
const toast = new Toasts($(this), _options)

if (option === 'create') {
toast[option]()
}
})
}
}

/**
* jQuery API
* ====================================================
*/

$.fn[NAME] = Toasts._jQueryInterface
$.fn[NAME].Constructor = Toasts
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT
return Toasts._jQueryInterface
}

export default Toasts

+ 118
- 0
MVCTemplate/wwwroot/build/js/TodoList.js Zobrazit soubor

@@ -0,0 +1,118 @@
/**
* --------------------------------------------
* AdminLTE TodoList.js
* License MIT
* --------------------------------------------
*/

import $ from 'jquery'

/**
* Constants
* ====================================================
*/

const NAME = 'TodoList'
const DATA_KEY = 'lte.todolist'
const JQUERY_NO_CONFLICT = $.fn[NAME]

const SELECTOR_DATA_TOGGLE = '[data-widget="todo-list"]'
const CLASS_NAME_TODO_LIST_DONE = 'done'

const Default = {
onCheck(item) {
return item
},
onUnCheck(item) {
return item
}
}

/**
* Class Definition
* ====================================================
*/

class TodoList {
constructor(element, config) {
this._config = config
this._element = element

this._init()
}

// Public

toggle(item) {
item.parents('li').toggleClass(CLASS_NAME_TODO_LIST_DONE)
if (!$(item).prop('checked')) {
this.unCheck($(item))
return
}

this.check(item)
}

check(item) {
this._config.onCheck.call(item)
}

unCheck(item) {
this._config.onUnCheck.call(item)
}

// Private

_init() {
const $toggleSelector = this._element

$toggleSelector.find('input:checkbox:checked').parents('li').toggleClass(CLASS_NAME_TODO_LIST_DONE)
$toggleSelector.on('change', 'input:checkbox', event => {
this.toggle($(event.target))
})
}

// Static

static _jQueryInterface(config) {
return this.each(function () {
let data = $(this).data(DATA_KEY)

if (!data) {
data = $(this).data()
}

const _options = $.extend({}, Default, typeof config === 'object' ? config : data)
const plugin = new TodoList($(this), _options)

$(this).data(DATA_KEY, typeof config === 'object' ? config : data)

if (config === 'init') {
plugin[config]()
}
})
}
}

/**
* Data API
* ====================================================
*/

$(window).on('load', () => {
TodoList._jQueryInterface.call($(SELECTOR_DATA_TOGGLE))
})

/**
* jQuery API
* ====================================================
*/

$.fn[NAME] = TodoList._jQueryInterface
$.fn[NAME].Constructor = TodoList
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT
return TodoList._jQueryInterface
}

export default TodoList

+ 175
- 0
MVCTemplate/wwwroot/build/js/Treeview.js Zobrazit soubor

@@ -0,0 +1,175 @@
/**
* --------------------------------------------
* AdminLTE Treeview.js
* License MIT
* --------------------------------------------
*/

import $ from 'jquery'

/**
* Constants
* ====================================================
*/

const NAME = 'Treeview'
const DATA_KEY = 'lte.treeview'
const EVENT_KEY = `.${DATA_KEY}`
const JQUERY_NO_CONFLICT = $.fn[NAME]

const EVENT_EXPANDED = `expanded${EVENT_KEY}`
const EVENT_COLLAPSED = `collapsed${EVENT_KEY}`
const EVENT_LOAD_DATA_API = `load${EVENT_KEY}`

const SELECTOR_LI = '.nav-item'
const SELECTOR_LINK = '.nav-link'
const SELECTOR_TREEVIEW_MENU = '.nav-treeview'
const SELECTOR_OPEN = '.menu-open'
const SELECTOR_DATA_WIDGET = '[data-widget="treeview"]'

const CLASS_NAME_OPEN = 'menu-open'
const CLASS_NAME_IS_OPENING = 'menu-is-opening'
const CLASS_NAME_SIDEBAR_COLLAPSED = 'sidebar-collapse'

const Default = {
trigger: `${SELECTOR_DATA_WIDGET} ${SELECTOR_LINK}`,
animationSpeed: 300,
accordion: true,
expandSidebar: false,
sidebarButtonSelector: '[data-widget="pushmenu"]'
}

/**
* Class Definition
* ====================================================
*/
class Treeview {
constructor(element, config) {
this._config = config
this._element = element
}

// Public

init() {
$(`${SELECTOR_LI}${SELECTOR_OPEN} ${SELECTOR_TREEVIEW_MENU}${SELECTOR_OPEN}`).css('display', 'block')
this._setupListeners()
}

expand(treeviewMenu, parentLi) {
const expandedEvent = $.Event(EVENT_EXPANDED)

if (this._config.accordion) {
const openMenuLi = parentLi.siblings(SELECTOR_OPEN).first()
const openTreeview = openMenuLi.find(SELECTOR_TREEVIEW_MENU).first()
this.collapse(openTreeview, openMenuLi)
}

parentLi.addClass(CLASS_NAME_IS_OPENING)
treeviewMenu.stop().slideDown(this._config.animationSpeed, () => {
parentLi.addClass(CLASS_NAME_OPEN)
$(this._element).trigger(expandedEvent)
})

if (this._config.expandSidebar) {
this._expandSidebar()
}
}

collapse(treeviewMenu, parentLi) {
const collapsedEvent = $.Event(EVENT_COLLAPSED)

parentLi.removeClass(`${CLASS_NAME_IS_OPENING} ${CLASS_NAME_OPEN}`)
treeviewMenu.stop().slideUp(this._config.animationSpeed, () => {
$(this._element).trigger(collapsedEvent)
treeviewMenu.find(`${SELECTOR_OPEN} > ${SELECTOR_TREEVIEW_MENU}`).slideUp()
treeviewMenu.find(SELECTOR_OPEN).removeClass(CLASS_NAME_OPEN)
})
}

toggle(event) {
const $relativeTarget = $(event.currentTarget)
const $parent = $relativeTarget.parent()

let treeviewMenu = $parent.find(`> ${SELECTOR_TREEVIEW_MENU}`)

if (!treeviewMenu.is(SELECTOR_TREEVIEW_MENU)) {
if (!$parent.is(SELECTOR_LI)) {
treeviewMenu = $parent.parent().find(`> ${SELECTOR_TREEVIEW_MENU}`)
}

if (!treeviewMenu.is(SELECTOR_TREEVIEW_MENU)) {
return
}
}

event.preventDefault()

const parentLi = $relativeTarget.parents(SELECTOR_LI).first()
const isOpen = parentLi.hasClass(CLASS_NAME_OPEN)

if (isOpen) {
this.collapse($(treeviewMenu), parentLi)
} else {
this.expand($(treeviewMenu), parentLi)
}
}

// Private

_setupListeners() {
const elementId = this._element.attr('id') !== undefined ? `#${this._element.attr('id')}` : ''
$(document).on('click', `${elementId}${this._config.trigger}`, event => {
this.toggle(event)
})
}

_expandSidebar() {
if ($('body').hasClass(CLASS_NAME_SIDEBAR_COLLAPSED)) {
$(this._config.sidebarButtonSelector).PushMenu('expand')
}
}

// Static

static _jQueryInterface(config) {
return this.each(function () {
let data = $(this).data(DATA_KEY)
const _options = $.extend({}, Default, $(this).data())

if (!data) {
data = new Treeview($(this), _options)
$(this).data(DATA_KEY, data)
}

if (config === 'init') {
data[config]()
}
})
}
}

/**
* Data API
* ====================================================
*/

$(window).on(EVENT_LOAD_DATA_API, () => {
$(SELECTOR_DATA_WIDGET).each(function () {
Treeview._jQueryInterface.call($(this), 'init')
})
})

/**
* jQuery API
* ====================================================
*/

$.fn[NAME] = Treeview._jQueryInterface
$.fn[NAME].Constructor = Treeview
$.fn[NAME].noConflict = function () {
$.fn[NAME] = JQUERY_NO_CONFLICT
return Treeview._jQueryInterface
}

export default Treeview

+ 14
- 0
MVCTemplate/wwwroot/build/npm/.eslintrc.json Zobrazit soubor

@@ -0,0 +1,14 @@
{
"env": {
"browser": false,
"node": true
},
"parserOptions": {
"sourceType": "script"
},
"extends": "../../.eslintrc.json",
"rules": {
"no-console": "off",
"strict": "error"
}
}

+ 48
- 0
MVCTemplate/wwwroot/build/npm/DocsPlugins.js Zobrazit soubor

@@ -0,0 +1,48 @@
'use strict'

const Plugins = [
// AdminLTE Dist
{
from: 'dist/css/',
to: 'docs/assets/css/'
},
{
from: 'dist/js/',
to: 'docs/assets/js/'
},
// jQuery
{
from: 'node_modules/jquery/dist/',
to: 'docs/assets/plugins/jquery/'
},
// Popper
{
from: 'node_modules/popper.js/dist/',
to: 'docs/assets/plugins/popper/'
},
// Bootstrap
{
from: 'node_modules/bootstrap/dist/js/',
to: 'docs/assets/plugins/bootstrap/js/'
},
// Font Awesome
{
from: 'node_modules/@fortawesome/fontawesome-free/css/',
to: 'docs/assets/plugins/fontawesome-free/css/'
},
{
from: 'node_modules/@fortawesome/fontawesome-free/webfonts/',
to: 'docs/assets/plugins/fontawesome-free/webfonts/'
},
// overlayScrollbars
{
from: 'node_modules/overlayscrollbars/js/',
to: 'docs/assets/plugins/overlayScrollbars/js/'
},
{
from: 'node_modules/overlayscrollbars/css/',
to: 'docs/assets/plugins/overlayScrollbars/css/'
}
]

module.exports = Plugins

+ 58
- 0
MVCTemplate/wwwroot/build/npm/DocsPublish.js Zobrazit soubor

@@ -0,0 +1,58 @@
#!/usr/bin/env node

'use strict'

const path = require('path')
const fse = require('fs-extra')
const fs = require('fs')
const Plugins = require('./DocsPlugins')

class Publish {
constructor() {
this.options = {
verbose: false
}

this.getArguments()
}

getArguments() {
if (process.argv.length > 2) {
const arg = process.argv[2]
switch (arg) {
case '-v':
case '--verbose':
this.options.verbose = true
break
default:
throw new Error(`Unknown option ${arg}`)
}
}
}

run() {
// Publish files
Plugins.forEach(module => {
try {
fse.copySync(module.from, module.to, {
// Skip copying dot files
filter(src) {
return !path.basename(src).startsWith('.')
}
})

if (this.options.verbose) {
console.log(`Copied ${module.from} to ${module.to}`)
}
} catch (error) {
console.error(`Error: ${error}`)
}
})

const insertText = '---\r\nlayout: page\r\ntitle: \r\n---\r\n'

fs.writeFileSync('docs/how-to-contribute.md', insertText + fs.readFileSync('.github/CONTRIBUTING.md', 'utf8'))
}
}

(new Publish()).run()

+ 449
- 0
MVCTemplate/wwwroot/build/npm/Plugins.js Zobrazit soubor

@@ -0,0 +1,449 @@
'use strict'

const Plugins = [
// jQuery
{
from: 'node_modules/jquery/dist',
to: 'plugins/jquery'
},
// Popper
{
from: 'node_modules/popper.js/dist',
to: 'plugins/popper'
},
// Bootstrap
{
from: 'node_modules/bootstrap/dist/js',
to: 'plugins/bootstrap/js'
},
// Font Awesome
{
from: 'node_modules/@fortawesome/fontawesome-free/css',
to: 'plugins/fontawesome-free/css'
},
{
from: 'node_modules/@fortawesome/fontawesome-free/webfonts',
to: 'plugins/fontawesome-free/webfonts'
},
// overlayScrollbars
{
from: 'node_modules/overlayscrollbars/js',
to: 'plugins/overlayScrollbars/js'
},
{
from: 'node_modules/overlayscrollbars/css',
to: 'plugins/overlayScrollbars/css'
},
// Chart.js
{
from: 'node_modules/chart.js/dist/',
to: 'plugins/chart.js'
},
// jQuery UI
{
from: 'node_modules/jquery-ui-dist/',
to: 'plugins/jquery-ui'
},
// Flot
{
from: 'node_modules/flot/dist/es5/',
to: 'plugins/flot'
},
{
from: 'node_modules/flot/source/',
to: 'plugins/flot/plugins'
},
// Summernote
{
from: 'node_modules/summernote/dist/',
to: 'plugins/summernote'
},
// Bootstrap Slider
{
from: 'node_modules/bootstrap-slider/dist/',
to: 'plugins/bootstrap-slider'
},
{
from: 'node_modules/bootstrap-slider/dist/css',
to: 'plugins/bootstrap-slider/css'
},
// Bootstrap Colorpicker
{
from: 'node_modules/bootstrap-colorpicker/dist/js',
to: 'plugins/bootstrap-colorpicker/js'
},
{
from: 'node_modules/bootstrap-colorpicker/dist/css',
to: 'plugins/bootstrap-colorpicker/css'
},
// Tempusdominus Bootstrap 4
{
from: 'node_modules/tempusdominus-bootstrap-4/build/js',
to: 'plugins/tempusdominus-bootstrap-4/js'
},
{
from: 'node_modules/tempusdominus-bootstrap-4/build/css',
to: 'plugins/tempusdominus-bootstrap-4/css'
},
// Moment
{
from: 'node_modules/moment/min',
to: 'plugins/moment'
},
{
from: 'node_modules/moment/locale',
to: 'plugins/moment/locale'
},
// FastClick
{
from: 'node_modules/fastclick/lib',
to: 'plugins/fastclick'
},
// Date Range Picker
{
from: 'node_modules/daterangepicker/',
to: 'plugins/daterangepicker'
},
// DataTables
{
from: 'node_modules/pdfmake/build',
to: 'plugins/pdfmake'
},
{
from: 'node_modules/jszip/dist',
to: 'plugins/jszip'
},
{
from: 'node_modules/datatables.net/js',
to: 'plugins/datatables'
},
{
from: 'node_modules/datatables.net-bs4/js',
to: 'plugins/datatables-bs4/js'
},
{
from: 'node_modules/datatables.net-bs4/css',
to: 'plugins/datatables-bs4/css'
},
{
from: 'node_modules/datatables.net-autofill/js',
to: 'plugins/datatables-autofill/js'
},
{
from: 'node_modules/datatables.net-autofill-bs4/js',
to: 'plugins/datatables-autofill/js'
},
{
from: 'node_modules/datatables.net-autofill-bs4/css',
to: 'plugins/datatables-autofill/css'
},
{
from: 'node_modules/datatables.net-buttons/js',
to: 'plugins/datatables-buttons/js'
},
{
from: 'node_modules/datatables.net-buttons-bs4/js',
to: 'plugins/datatables-buttons/js'
},
{
from: 'node_modules/datatables.net-buttons-bs4/css',
to: 'plugins/datatables-buttons/css'
},
{
from: 'node_modules/datatables.net-colreorder/js',
to: 'plugins/datatables-colreorder/js'
},
{
from: 'node_modules/datatables.net-colreorder-bs4/js',
to: 'plugins/datatables-colreorder/js'
},
{
from: 'node_modules/datatables.net-colreorder-bs4/css',
to: 'plugins/datatables-colreorder/css'
},
{
from: 'node_modules/datatables.net-fixedcolumns/js',
to: 'plugins/datatables-fixedcolumns/js'
},
{
from: 'node_modules/datatables.net-fixedcolumns-bs4/js',
to: 'plugins/datatables-fixedcolumns/js'
},
{
from: 'node_modules/datatables.net-fixedcolumns-bs4/css',
to: 'plugins/datatables-fixedcolumns/css'
},
{
from: 'node_modules/datatables.net-fixedheader/js',
to: 'plugins/datatables-fixedheader/js'
},
{
from: 'node_modules/datatables.net-fixedheader-bs4/js',
to: 'plugins/datatables-fixedheader/js'
},
{
from: 'node_modules/datatables.net-fixedheader-bs4/css',
to: 'plugins/datatables-fixedheader/css'
},
{
from: 'node_modules/datatables.net-keytable/js',
to: 'plugins/datatables-keytable/js'
},
{
from: 'node_modules/datatables.net-keytable-bs4/js',
to: 'plugins/datatables-keytable/js'
},
{
from: 'node_modules/datatables.net-keytable-bs4/css',
to: 'plugins/datatables-keytable/css'
},
{
from: 'node_modules/datatables.net-responsive/js',
to: 'plugins/datatables-responsive/js'
},
{
from: 'node_modules/datatables.net-responsive-bs4/js',
to: 'plugins/datatables-responsive/js'
},
{
from: 'node_modules/datatables.net-responsive-bs4/css',
to: 'plugins/datatables-responsive/css'
},
{
from: 'node_modules/datatables.net-rowgroup/js',
to: 'plugins/datatables-rowgroup/js'
},
{
from: 'node_modules/datatables.net-rowgroup-bs4/js',
to: 'plugins/datatables-rowgroup/js'
},
{
from: 'node_modules/datatables.net-rowgroup-bs4/css',
to: 'plugins/datatables-rowgroup/css'
},
{
from: 'node_modules/datatables.net-rowreorder/js',
to: 'plugins/datatables-rowreorder/js'
},
{
from: 'node_modules/datatables.net-rowreorder-bs4/js',
to: 'plugins/datatables-rowreorder/js'
},
{
from: 'node_modules/datatables.net-rowreorder-bs4/css',
to: 'plugins/datatables-rowreorder/css'
},
{
from: 'node_modules/datatables.net-scroller/js',
to: 'plugins/datatables-scroller/js'
},
{
from: 'node_modules/datatables.net-scroller-bs4/js',
to: 'plugins/datatables-scroller/js'
},
{
from: 'node_modules/datatables.net-scroller-bs4/css',
to: 'plugins/datatables-scroller/css'
},
{
from: 'node_modules/datatables.net-searchbuilder/js',
to: 'plugins/datatables-searchbuilder/js'
},
{
from: 'node_modules/datatables.net-searchbuilder-bs4/js',
to: 'plugins/datatables-searchbuilder/js'
},
{
from: 'node_modules/datatables.net-searchbuilder-bs4/css',
to: 'plugins/datatables-searchbuilder/css'
},
{
from: 'node_modules/datatables.net-searchpanes/js',
to: 'plugins/datatables-searchpanes/js'
},
{
from: 'node_modules/datatables.net-searchpanes-bs4/js',
to: 'plugins/datatables-searchpanes/js'
},
{
from: 'node_modules/datatables.net-searchpanes-bs4/css',
to: 'plugins/datatables-searchpanes/css'
},
{
from: 'node_modules/datatables.net-select/js',
to: 'plugins/datatables-select/js'
},
{
from: 'node_modules/datatables.net-select-bs4/js',
to: 'plugins/datatables-select/js'
},
{
from: 'node_modules/datatables.net-select-bs4/css',
to: 'plugins/datatables-select/css'
},

// Fullcalendar
{
from: 'node_modules/fullcalendar/',
to: 'plugins/fullcalendar'
},
// icheck bootstrap
{
from: 'node_modules/icheck-bootstrap/',
to: 'plugins/icheck-bootstrap'
},
// inputmask
{
from: 'node_modules/inputmask/dist/',
to: 'plugins/inputmask'
},
// ion-rangeslider
{
from: 'node_modules/ion-rangeslider/',
to: 'plugins/ion-rangeslider'
},
// JQVMap (jqvmap-novulnerability)
{
from: 'node_modules/jqvmap-novulnerability/dist/',
to: 'plugins/jqvmap'
},
// jQuery Mapael
{
from: 'node_modules/jquery-mapael/js/',
to: 'plugins/jquery-mapael'
},
// Raphael
{
from: 'node_modules/raphael/',
to: 'plugins/raphael'
},
// jQuery Mousewheel
{
from: 'node_modules/jquery-mousewheel/',
to: 'plugins/jquery-mousewheel'
},
// jQuery Knob
{
from: 'node_modules/jquery-knob-chif/dist/',
to: 'plugins/jquery-knob'
},
// pace-progress
{
from: 'node_modules/@lgaitan/pace-progress/dist/',
to: 'plugins/pace-progress'
},
// Select2
{
from: 'node_modules/select2/dist/',
to: 'plugins/select2'
},
{
from: 'node_modules/@ttskch/select2-bootstrap4-theme/dist/',
to: 'plugins/select2-bootstrap4-theme'
},
// Sparklines
{
from: 'node_modules/sparklines/source/',
to: 'plugins/sparklines'
},
// SweetAlert2
{
from: 'node_modules/sweetalert2/dist/',
to: 'plugins/sweetalert2'
},
{
from: 'node_modules/@sweetalert2/theme-bootstrap-4/',
to: 'plugins/sweetalert2-theme-bootstrap-4'
},
// Toastr
{
from: 'node_modules/toastr/build/',
to: 'plugins/toastr'
},
// jsGrid
{
from: 'node_modules/jsgrid/dist',
to: 'plugins/jsgrid'
},
{
from: 'node_modules/jsgrid/demos/db.js',
to: 'plugins/jsgrid/demos/db.js'
},
// flag-icon-css
{
from: 'node_modules/flag-icon-css/css',
to: 'plugins/flag-icon-css/css'
},
{
from: 'node_modules/flag-icon-css/flags',
to: 'plugins/flag-icon-css/flags'
},
// bootstrap4-duallistbox
{
from: 'node_modules/bootstrap4-duallistbox/dist',
to: 'plugins/bootstrap4-duallistbox/'
},
// filterizr
{
from: 'node_modules/filterizr/dist',
to: 'plugins/filterizr/'
},
// ekko-lightbox
{
from: 'node_modules/ekko-lightbox/dist',
to: 'plugins/ekko-lightbox/'
},
// bootstrap-switch
{
from: 'node_modules/bootstrap-switch/dist',
to: 'plugins/bootstrap-switch/'
},
// jQuery Validate
{
from: 'node_modules/jquery-validation/dist/',
to: 'plugins/jquery-validation'
},
// bs-custom-file-input
{
from: 'node_modules/bs-custom-file-input/dist/',
to: 'plugins/bs-custom-file-input'
},
// bs-stepper
{
from: 'node_modules/bs-stepper/dist/',
to: 'plugins/bs-stepper'
},
// CodeMirror
{
from: 'node_modules/codemirror/lib/',
to: 'plugins/codemirror'
},
{
from: 'node_modules/codemirror/addon/',
to: 'plugins/codemirror/addon'
},
{
from: 'node_modules/codemirror/keymap/',
to: 'plugins/codemirror/keymap'
},
{
from: 'node_modules/codemirror/mode/',
to: 'plugins/codemirror/mode'
},
{
from: 'node_modules/codemirror/theme/',
to: 'plugins/codemirror/theme'
},
// dropzonejs
{
from: 'node_modules/dropzone/dist/',
to: 'plugins/dropzone'
},
// uPlot
{
from: 'node_modules/uplot/dist/',
to: 'plugins/uplot'
}
]

module.exports = Plugins

+ 59
- 0
MVCTemplate/wwwroot/build/npm/Publish.js Zobrazit soubor

@@ -0,0 +1,59 @@
#!/usr/bin/env node

'use strict'

const path = require('path')
const fse = require('fs-extra')
const Plugins = require('./Plugins')

class Publish {
constructor() {
this.options = {
verbose: false
}

this.getArguments()
}

getArguments() {
if (process.argv.length > 2) {
const arg = process.argv[2]
switch (arg) {
case '-v':
case '--verbose':
this.options.verbose = true
break
default:
throw new Error(`Unknown option ${arg}`)
}
}
}

run() {
// Publish files
Plugins.forEach(module => {
const fseOptions = {
// Skip copying dot files
filter(src) {
return !path.basename(src).startsWith('.')
}
}

try {
if (fse.existsSync(module.from)) {
fse.copySync(module.from, module.to, fseOptions)
} else {
fse.copySync(module.from.replace('node_modules/', '../'), module.to, fseOptions)
}

if (this.options.verbose) {
console.log(`Copied ${module.from} to ${module.to}`)
}
} catch (error) {
console.error(`Error: ${error}`)
}
})
}
}

(new Publish()).run()

+ 55
- 0
MVCTemplate/wwwroot/build/npm/vnu-jar.js Zobrazit soubor

@@ -0,0 +1,55 @@
#!/usr/bin/env node

/*!
* Script to run vnu-jar if Java is available.
* Copyright 2017-2021 The Bootstrap Authors
* Copyright 2017-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/

'use strict'

const childProcess = require('child_process')
const vnu = require('vnu-jar')

childProcess.exec('java -version', (error, stdout, stderr) => {
if (error) {
console.error('Skipping vnu-jar test; Java is missing.')
return
}

const is32bitJava = !/64-Bit/.test(stderr)

// vnu-jar accepts multiple ignores joined with a `|`.
// Also note that the ignores are regular expressions.
const ignores = [
// "autocomplete" is included in <button> and checkboxes and radio <input>s due to
// Firefox's non-standard autocomplete behavior - see https://bugzilla.mozilla.org/show_bug.cgi?id=654072
'Attribute “autocomplete” is only allowed when the input type is.*'
].join('|')

const args = [
'-jar',
vnu,
'--asciiquotes',
'--skip-non-html',
// Ignore the language code warnings
'--no-langdetect',
'--Werror',
`--filterpattern "${ignores}"`,
'./*.html',
'docs_html/',
'pages/'
]

// For the 32-bit Java we need to pass `-Xss512k`
if (is32bitJava) {
args.splice(0, 0, '-Xss512k')
}

return childProcess.spawn('java', args, {
shell: true,
stdio: 'inherit'
})
.on('exit', process.exit)
})

+ 30
- 0
MVCTemplate/wwwroot/build/scss/_adminlte.raw.scss Zobrazit soubor

@@ -0,0 +1,30 @@
/*!
* AdminLTE v3.1.0
* Author: Colorlib
* Website: AdminLTE.io <https://adminlte.io>
* License: Open source - MIT <https://opensource.org/licenses/MIT>
*/

//
// ------------------------------------------------------------------
// This file is to be included in your custom SCSS. Before importing
// this file, you should include your custom AdminLTE and Bootstrap
// variables followed by bootstrap.scss and then this file. It's
// ok to import this file without custom variables too!
// NOTE: be sure to keep the license notice in the generated css.
// ------------------------------------------------------------------

//
// Variables and Mixins
// ---------------------------------------------------
@import "bootstrap-variables";
@import "variables";
@import "variables-alt";
@import "mixins";

@import "parts/core";
@import "parts/components";
@import "parts/extra-components";
@import "parts/pages";
@import "parts/plugins";
@import "parts/miscellaneous";

+ 52
- 0
MVCTemplate/wwwroot/build/scss/_alerts.scss Zobrazit soubor

@@ -0,0 +1,52 @@
//
// Component: Alert
//

.alert {
.icon {
margin-right: 10px;
}

.close {
color: $black;
opacity: .2;

&:hover {
opacity: .5;
}
}

a {
color: $white;
text-decoration: underline;
}
}

//Alert Variants
@each $color, $value in $theme-colors {
.alert-#{$color} {
color: color-yiq($value);
background-color: $value;
border-color: darken($value, 5%);
}

.alert-default-#{$color} {
@include alert-variant(theme-color-level($color, $alert-bg-level), theme-color-level($color, $alert-border-level), theme-color-level($color, $alert-color-level));
}
}

.dark-mode {
@each $color, $value in $theme-colors-alt {
.alert-#{$color} {
color: color-yiq($value);
background-color: $value;
border-color: darken($value, 5%);
}

.alert-default-#{$color} {
@include alert-variant(theme-color-level($color, $alert-bg-level), theme-color-level($color, $alert-border-level), theme-color-level($color, $alert-color-level));
}
}
}

//

+ 14
- 0
MVCTemplate/wwwroot/build/scss/_animation-effects.scss Zobrazit soubor

@@ -0,0 +1,14 @@
//
// Component: Animation
//

.animation {
&__shake {
animation: shake 1500ms;
}
&__wobble {
animation: wobble 1500ms;
}
}

//

+ 911
- 0
MVCTemplate/wwwroot/build/scss/_bootstrap-variables.scss Zobrazit soubor

@@ -0,0 +1,911 @@
// Variables
//
// Variables should follow the `$component-state-property-size` formula for
// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs.


//
// Color system
//

// stylelint-disable
$white: #fff !default;
$gray-100: #f8f9fa !default;
$gray-200: #e9ecef !default;
$gray-300: #dee2e6 !default;
$gray-400: #ced4da !default;
$gray-500: #adb5bd !default;
$gray-600: #6c757d !default;
$gray-700: #495057 !default;
$gray-800: #343a40 !default;
$gray-900: #212529 !default;
$black: #000 !default;

$grays: () !default;
$grays: map-merge((
"100": $gray-100,
"200": $gray-200,
"300": $gray-300,
"400": $gray-400,
"500": $gray-500,
"600": $gray-600,
"700": $gray-700,
"800": $gray-800,
"900": $gray-900
), $grays);

$blue: #007bff !default;
$indigo: #6610f2 !default;
$purple: #6f42c1 !default;
$pink: #e83e8c !default;
$red: #dc3545 !default;
$orange: #fd7e14 !default;
$yellow: #ffc107 !default;
$green: #28a745 !default;
$teal: #20c997 !default;
$cyan: #17a2b8 !default;

$colors: () !default;
$colors: map-merge((
"blue": $blue,
"indigo": $indigo,
"purple": $purple,
"pink": $pink,
"red": $red,
"orange": $orange,
"yellow": $yellow,
"green": $green,
"teal": $teal,
"cyan": $cyan,
"white": $white,
"gray": $gray-600,
"gray-dark": $gray-800
), $colors);

$primary: $blue !default;
$secondary: $gray-600 !default;
$success: $green !default;
$info: $cyan !default;
$warning: $yellow !default;
$danger: $red !default;
$light: $gray-100 !default;
$dark: $gray-800 !default;

$theme-colors: () !default;
$theme-colors: map-merge((
"primary": $primary,
"secondary": $secondary,
"success": $success,
"info": $info,
"warning": $warning,
"danger": $danger,
"light": $light,
"dark": $dark
), $theme-colors);
// stylelint-enable

// Set a specific jump point for requesting color jumps
$theme-color-interval: 8% !default;

// The yiq lightness value that determines when the lightness of color changes from "dark" to "light". Acceptable values are between 0 and 255.
$yiq-contrasted-threshold: 150 !default;

// Customize the light and dark text colors for use in our YIQ color contrast function.
$yiq-text-dark: #1f2d3d !default;
$yiq-text-light: $white !default;

// Options
//
// Quickly modify global styling by enabling or disabling optional features.

$enable-caret: true !default;
$enable-rounded: true !default;
$enable-shadows: true !default;
$enable-gradients: false !default;
$enable-transitions: true !default;
$enable-prefers-reduced-motion-media-query: true !default;
$enable-hover-media-query: false !default; // Deprecated, no longer affects any compiled CSS
$enable-grid-classes: true !default;
$enable-pointer-cursor-for-buttons: true !default;
$enable-print-styles: true !default;
$enable-responsive-font-sizes: false !default;
$enable-validation-icons: true !default;
$enable-deprecation-messages: true !default;

// Spacing
//
// Control the default styling of most Bootstrap elements by modifying these
// variables. Mostly focused on spacing.
// You can add more entries to the $spacers map, should you need more variation.

// stylelint-disable
$spacer: 1rem !default;
$spacers: () !default;
$spacers: map-merge((
0: 0,
1: ($spacer * .25),
2: ($spacer * .5),
3: $spacer,
4: ($spacer * 1.5),
5: ($spacer * 3)
), $spacers);

// This variable affects the `.h-*` and `.w-*` classes.
$sizes: () !default;
$sizes: map-merge((
25: 25%,
50: 50%,
75: 75%,
100: 100%
), $sizes);
// stylelint-enable

// Body
//
// Settings for the `<body>` element.

$body-bg: $white !default;
$body-color: $gray-900 !default;

// Links
//
// Style anchor elements.

$link-color: theme-color("primary") !default;
$link-decoration: none !default;
$link-hover-color: darken($link-color, 15%) !default;
$link-hover-decoration: none !default;

// Paragraphs
//
// Style p element.

$paragraph-margin-bottom: 1rem !default;


// Grid breakpoints
//
// Define the minimum dimensions at which your layout will change,
// adapting to different screen sizes, for use in media queries.

$grid-breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
) !default;

@include _assert-ascending($grid-breakpoints, "$grid-breakpoints");
@include _assert-starts-at-zero($grid-breakpoints);


// Grid containers
//
// Define the maximum width of `.container` for different screen sizes.

$container-max-widths: (
sm: 540px,
md: 720px,
lg: 960px,
xl: 1140px
) !default;

@include _assert-ascending($container-max-widths, "$container-max-widths");


// Grid columns
//
// Set the number of columns and specify the width of the gutters.

$grid-columns: 12 !default;
$grid-gutter-width: 15px !default;

// Components
//
// Define common padding and border radius sizes and more.

$line-height-lg: 1.5 !default;
$line-height-sm: 1.5 !default;

$border-width: 1px !default;
$border-color: $gray-300 !default;

$border-radius: .25rem !default;
$border-radius-lg: .3rem !default;
$border-radius-sm: .2rem !default;

$component-active-color: $white !default;
$component-active-bg: theme-color("primary") !default;

$caret-width: .3em !default;

$transition-base: all .2s ease-in-out !default;
$transition-fade: opacity .15s linear !default;
$transition-collapse: height .35s ease !default;


// Fonts
//
// Font, line-height, and color for body text, headings, and more.

// stylelint-disable value-keyword-case
$font-family-sans-serif: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !default;
$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !default;
$font-family-base: $font-family-sans-serif !default;
// stylelint-enable value-keyword-case

$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`
$font-size-lg: ($font-size-base * 1.25) !default;
$font-size-sm: ($font-size-base * .875) !default;

$font-weight-light: 300 !default;
$font-weight-normal: 400 !default;
$font-weight-bold: 700 !default;

$font-weight-base: $font-weight-normal !default;
$line-height-base: 1.5 !default;

$h1-font-size: $font-size-base * 2.5 !default;
$h2-font-size: $font-size-base * 2 !default;
$h3-font-size: $font-size-base * 1.75 !default;
$h4-font-size: $font-size-base * 1.5 !default;
$h5-font-size: $font-size-base * 1.25 !default;
$h6-font-size: $font-size-base !default;

$headings-margin-bottom: ($spacer / 2) !default;
$headings-font-family: inherit !default;
$headings-font-weight: 500 !default;
$headings-line-height: 1.2 !default;
$headings-color: inherit !default;

$display1-size: 6rem !default;
$display2-size: 5.5rem !default;
$display3-size: 4.5rem !default;
$display4-size: 3.5rem !default;

$display1-weight: 300 !default;
$display2-weight: 300 !default;
$display3-weight: 300 !default;
$display4-weight: 300 !default;
$display-line-height: $headings-line-height !default;

$lead-font-size: ($font-size-base * 1.25) !default;
$lead-font-weight: 300 !default;

$small-font-size: 80% !default;

$text-muted: $gray-600 !default;

$blockquote-small-color: $gray-600 !default;
$blockquote-font-size: ($font-size-base * 1.25) !default;

$hr-border-color: rgba($black, .1) !default;
$hr-border-width: $border-width !default;

$mark-padding: .2em !default;

$dt-font-weight: $font-weight-bold !default;

$kbd-box-shadow: inset 0 -.1rem 0 rgba($black, .25) !default;
$nested-kbd-font-weight: $font-weight-bold !default;

$list-inline-padding: .5rem !default;

$mark-bg: #fcf8e3 !default;

$hr-margin-y: $spacer !default;


// Tables
//
// Customizes the `.table` component with basic values, each used across all table variations.

$table-cell-padding: .75rem !default;
$table-cell-padding-sm: .3rem !default;

$table-bg: transparent !default;
$table-accent-bg: rgba($black, .05) !default;
$table-hover-bg: rgba($black, .075) !default;
$table-active-bg: $table-hover-bg !default;

$table-border-width: $border-width !default;
$table-border-color: $gray-300 !default;

$table-head-bg: $gray-200 !default;
$table-head-color: $gray-700 !default;

$table-dark-bg: $gray-900 !default;
$table-dark-accent-bg: rgba($white, .05) !default;
$table-dark-hover-bg: rgba($white, .075) !default;
$table-dark-border-color: lighten($gray-900, 10%) !default;
$table-dark-color: $body-bg !default;


// Buttons + Forms
//
// Shared variables that are reassigned to `$input-` and `$btn-` specific variables.

$input-btn-padding-y: .375rem !default;
$input-btn-padding-x: .75rem !default;
$input-btn-line-height: $line-height-base !default;

$input-btn-focus-width: .2rem !default;
$input-btn-focus-color: rgba($component-active-bg, .25) !default;
$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default;

$input-btn-padding-y-sm: .25rem !default;
$input-btn-padding-x-sm: .5rem !default;
$input-btn-line-height-sm: $line-height-sm !default;

$input-btn-padding-y-lg: .5rem !default;
$input-btn-padding-x-lg: 1rem !default;
$input-btn-line-height-lg: $line-height-lg !default;

$input-btn-border-width: $border-width !default;


// Buttons
//
// For each of Bootstrap's buttons, define text, background, and border color.

$btn-padding-y: $input-btn-padding-y !default;
$btn-padding-x: $input-btn-padding-x !default;
$btn-line-height: $input-btn-line-height !default;

$btn-padding-y-sm: $input-btn-padding-y-sm !default;
$btn-padding-x-sm: $input-btn-padding-x-sm !default;
$btn-line-height-sm: $input-btn-line-height-sm !default;

$btn-padding-y-lg: $input-btn-padding-y-lg !default;
$btn-padding-x-lg: $input-btn-padding-x-lg !default;
$btn-line-height-lg: $input-btn-line-height-lg !default;

$btn-border-width: $input-btn-border-width !default;

$btn-font-weight: $font-weight-normal !default;
$btn-box-shadow: none !default;
$btn-focus-width: 0 !default;
$btn-focus-box-shadow: none !default;
$btn-disabled-opacity: .65 !default;
$btn-active-box-shadow: none !default;

$btn-link-disabled-color: $gray-600 !default;

$btn-block-spacing-y: .5rem !default;

// Allows for customizing button radius independently from global border radius
$btn-border-radius: $border-radius !default;
$btn-border-radius-lg: $border-radius-lg !default;
$btn-border-radius-sm: $border-radius-sm !default;

$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;


// Forms

$input-padding-y: $input-btn-padding-y !default;
$input-padding-x: $input-btn-padding-x !default;
$input-line-height: $input-btn-line-height !default;

$input-padding-y-sm: $input-btn-padding-y-sm !default;
$input-padding-x-sm: $input-btn-padding-x-sm !default;
$input-line-height-sm: $input-btn-line-height-sm !default;

$input-padding-y-lg: $input-btn-padding-y-lg !default;
$input-padding-x-lg: $input-btn-padding-x-lg !default;
$input-line-height-lg: $input-btn-line-height-lg !default;

$input-bg: $white !default;
$input-disabled-bg: $gray-200 !default;

$input-color: $gray-700 !default;
$input-border-color: $gray-400 !default;
$input-border-width: $input-btn-border-width !default;
$input-box-shadow: inset 0 0 0 rgba($black, 0) !default;

$input-border-radius: $border-radius !default;
$input-border-radius-lg: $border-radius-lg !default;
$input-border-radius-sm: $border-radius-sm !default;

$input-focus-bg: $input-bg !default;
$input-focus-border-color: lighten($component-active-bg, 25%) !default;
$input-focus-color: $input-color !default;
$input-focus-width: 0 !default;
$input-focus-box-shadow: none !default;

$input-placeholder-color: lighten($gray-600, 15%) !default;

$input-height-border: $input-border-width * 2 !default;

$input-height-inner: ($font-size-base * $input-btn-line-height) + ($input-btn-padding-y * 2) !default;
$input-height-inner-half: calc(#{$input-line-height * .5em} + #{$input-padding-y}) !default;
$input-height-inner-quarter: calc(#{$input-line-height * .25em} + #{$input-padding-y / 2}) !default;

$input-height: calc(#{$input-height-inner} + #{$input-height-border}) !default;

$input-height-inner-sm: ($font-size-sm * $input-btn-line-height-sm) + ($input-btn-padding-y-sm * 2) !default;
$input-height-sm: calc(#{$input-height-inner-sm} + #{$input-height-border}) !default;

$input-height-inner-lg: ($font-size-lg * $input-btn-line-height-lg) + ($input-btn-padding-y-lg * 2) !default;
$input-height-lg: calc(#{$input-height-inner-lg} + #{$input-height-border}) !default;

$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;

$form-text-margin-top: .25rem !default;

$form-check-input-gutter: 1.25rem !default;
$form-check-input-margin-y: .3rem !default;
$form-check-input-margin-x: .25rem !default;

$form-check-inline-margin-x: .75rem !default;
$form-check-inline-input-margin-x: .3125rem !default;

$form-group-margin-bottom: 1rem !default;

$input-group-addon-color: $input-color !default;
$input-group-addon-bg: $gray-200 !default;
$input-group-addon-border-color: $input-border-color !default;

$custom-control-gutter: .5rem !default;
$custom-control-spacer-x: 1rem !default;

$custom-control-indicator-size: 1rem !default;
$custom-control-indicator-bg: $gray-300 !default;
$custom-control-indicator-bg-size: 50% 50% !default;
$custom-control-indicator-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;

$custom-control-indicator-disabled-bg: $gray-200 !default;
$custom-control-label-disabled-color: $gray-600 !default;

$custom-control-indicator-checked-color: $component-active-color !default;
$custom-control-indicator-checked-bg: $component-active-bg !default;
$custom-control-indicator-checked-disabled-bg: rgba(theme-color("primary"), .5) !default;
$custom-control-indicator-checked-box-shadow: none !default;

$custom-control-indicator-focus-box-shadow: 0 0 0 1px $body-bg, $input-btn-focus-box-shadow !default;

$custom-control-indicator-active-color: $component-active-color !default;
$custom-control-indicator-active-bg: lighten($component-active-bg, 35%) !default;
$custom-control-indicator-active-box-shadow: none !default;

$custom-checkbox-indicator-border-radius: $border-radius !default;
$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;

$custom-checkbox-indicator-indeterminate-bg: $component-active-bg !default;
$custom-checkbox-indicator-indeterminate-color: $custom-control-indicator-checked-color !default;
$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;
$custom-checkbox-indicator-indeterminate-box-shadow: none !default;

$custom-radio-indicator-border-radius: 50% !default;
$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;

$custom-select-padding-y: .375rem !default;
$custom-select-padding-x: .75rem !default;
$custom-select-height: $input-height !default;
$custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator
$custom-select-line-height: $input-btn-line-height !default;
$custom-select-color: $input-color !default;
$custom-select-disabled-color: $gray-600 !default;
$custom-select-bg: $white !default;
$custom-select-disabled-bg: $gray-200 !default;
$custom-select-bg-size: 8px 10px !default; // In pixels because image dimensions
$custom-select-indicator-color: $gray-800 !default;
$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;
$custom-select-border-width: $input-btn-border-width !default;
$custom-select-border-color: $input-border-color !default;
$custom-select-border-radius: $border-radius !default;

$custom-select-focus-border-color: $input-focus-border-color !default;
$custom-select-focus-box-shadow: none !default;

$custom-select-font-size-sm: 75% !default;
$custom-select-height-sm: $input-height-sm !default;

$custom-select-font-size-lg: 125% !default;
$custom-select-height-lg: $input-height-lg !default;

$custom-file-height: $input-height !default;
$custom-file-focus-border-color: $input-focus-border-color !default;
$custom-file-focus-box-shadow: $custom-select-focus-box-shadow !default;

$custom-file-padding-y: $input-btn-padding-y !default;
$custom-file-padding-x: $input-btn-padding-x !default;
$custom-file-line-height: $input-btn-line-height !default;
$custom-file-color: $input-color !default;
$custom-file-bg: $input-bg !default;
$custom-file-border-width: $input-btn-border-width !default;
$custom-file-border-color: $input-border-color !default;
$custom-file-border-radius: $input-border-radius !default;
$custom-file-box-shadow: $custom-select-focus-box-shadow !default;
$custom-file-button-color: $custom-file-color !default;
$custom-file-button-bg: $input-group-addon-bg !default;
$custom-file-text: (
en: "Browse"
) !default;

$custom-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-btn-focus-box-shadow !default;


// Form validation
$form-feedback-margin-top: $form-text-margin-top !default;
$form-feedback-font-size: $small-font-size !default;
$form-feedback-valid-color: theme-color("success") !default;
$form-feedback-invalid-color: theme-color("danger") !default;


// Dropdowns
//
// Dropdown menu container and contents.

$dropdown-min-width: 10rem !default;
$dropdown-padding-y: .5rem !default;
$dropdown-spacer: .125rem !default;
$dropdown-bg: $white !default;
$dropdown-border-color: rgba($black, .15) !default;
$dropdown-border-radius: $border-radius !default;
$dropdown-border-width: $border-width !default;
$dropdown-divider-bg: $gray-200 !default;
$dropdown-box-shadow: 0 .5rem 1rem rgba($black, .175) !default;

$dropdown-link-color: $gray-900 !default;
$dropdown-link-hover-color: darken($gray-900, 5%) !default;
$dropdown-link-hover-bg: $gray-100 !default;

$dropdown-link-active-color: $component-active-color !default;
$dropdown-link-active-bg: $component-active-bg !default;

$dropdown-link-disabled-color: $gray-600 !default;

$dropdown-item-padding-y: .25rem !default;
$dropdown-item-padding-x: 1rem !default;

$dropdown-header-color: $gray-600 !default;


// Z-index master list
//
// Warning: Avoid customizing these values. They're used for a bird's eye view
// of components dependent on the z-axis and are designed to all work together.

$zindex-dropdown: 1000 !default;
$zindex-sticky: 1020 !default;
$zindex-fixed: 1030 !default;
$zindex-modal-backdrop: 1040 !default;
$zindex-modal: 1050 !default;
$zindex-popover: 1060 !default;
$zindex-tooltip: 1070 !default;

// Navs

$nav-link-padding-y: .5rem !default;
$nav-link-padding-x: 1rem !default;
$nav-link-disabled-color: $gray-600 !default;

$nav-tabs-border-color: $gray-300 !default;
$nav-tabs-border-width: $border-width !default;
$nav-tabs-border-radius: $border-radius !default;
$nav-tabs-link-hover-border-color: $gray-200 $gray-200 $nav-tabs-border-color !default;
$nav-tabs-link-active-color: $gray-700 !default;
$nav-tabs-link-active-bg: $body-bg !default;
$nav-tabs-link-active-border-color: $gray-300 $gray-300 $nav-tabs-link-active-bg !default;

$nav-pills-border-radius: $border-radius !default;
$nav-pills-link-active-color: $component-active-color !default;
$nav-pills-link-active-bg: $component-active-bg !default;

// Navbar

$navbar-padding-y: ($spacer / 2) !default;
$navbar-padding-x: ($spacer / 2) !default;

$navbar-nav-link-padding-x: 1rem !default;

$navbar-brand-font-size: $font-size-lg !default;
// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link
$nav-link-height: ($font-size-base * $line-height-base + $nav-link-padding-y * 2) !default;
$navbar-brand-height: $navbar-brand-font-size * $line-height-base !default;
$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) / 2 !default;

$navbar-toggler-padding-y: .25rem !default;
$navbar-toggler-padding-x: .75rem !default;
$navbar-toggler-font-size: $font-size-lg !default;
$navbar-toggler-border-radius: $btn-border-radius !default;

$navbar-dark-color: rgba($white, .75) !default;
$navbar-dark-hover-color: rgba($white, 1) !default;
$navbar-dark-active-color: $white !default;
$navbar-dark-disabled-color: rgba($white, .25) !default;
$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;
$navbar-dark-toggler-border-color: rgba($white, .1) !default;

$navbar-light-color: rgba($black, .5) !default;
$navbar-light-hover-color: rgba($black, .7) !default;
$navbar-light-active-color: rgba($black, .9) !default;
$navbar-light-disabled-color: rgba($black, .3) !default;
$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;
$navbar-light-toggler-border-color: rgba($black, .1) !default;

// Pagination

$pagination-padding-y: .5rem !default;
$pagination-padding-x: .75rem !default;
$pagination-padding-y-sm: .25rem !default;
$pagination-padding-x-sm: .5rem !default;
$pagination-padding-y-lg: .75rem !default;
$pagination-padding-x-lg: 1.5rem !default;
$pagination-line-height: 1.25 !default;

$pagination-color: $link-color !default;
$pagination-bg: $white !default;
$pagination-border-width: $border-width !default;
$pagination-border-color: $gray-300 !default;

$pagination-focus-box-shadow: $input-btn-focus-box-shadow !default;

$pagination-hover-color: $link-hover-color !default;
$pagination-hover-bg: $gray-200 !default;
$pagination-hover-border-color: $gray-300 !default;

$pagination-active-color: $component-active-color !default;
$pagination-active-bg: $component-active-bg !default;
$pagination-active-border-color: $pagination-active-bg !default;

$pagination-disabled-color: $gray-600 !default;
$pagination-disabled-bg: $white !default;
$pagination-disabled-border-color: $gray-300 !default;


// Jumbotron

$jumbotron-padding: 2rem !default;
$jumbotron-bg: $gray-200 !default;


// Cards

$card-spacer-y: .75rem !default;
$card-spacer-x: 1.25rem !default;
$card-border-width: 0 !default; //$border-width !default;
$card-border-radius: $border-radius !default;
$card-border-color: rgba($black, .125) !default;
$card-inner-border-radius: calc(#{$card-border-radius} - #{$card-border-width}) !default;
$card-cap-bg: rgba($black, .03) !default;
$card-bg: $white !default;

$card-img-overlay-padding: 1.25rem !default;

$card-group-margin: ($grid-gutter-width / 2) !default;
$card-deck-margin: $card-group-margin !default;

$card-columns-count: 3 !default;
$card-columns-gap: 1.25rem !default;
$card-columns-margin: $card-spacer-y !default;


// Tooltips

$tooltip-font-size: $font-size-sm !default;
$tooltip-max-width: 200px !default;
$tooltip-color: $white !default;
$tooltip-bg: $black !default;
$tooltip-border-radius: $border-radius !default;
$tooltip-opacity: .9 !default;
$tooltip-padding-y: .25rem !default;
$tooltip-padding-x: .5rem !default;
$tooltip-margin: 0 !default;

$tooltip-arrow-width: .8rem !default;
$tooltip-arrow-height: .4rem !default;
$tooltip-arrow-color: $tooltip-bg !default;

// Form tooltips must come after regular tooltips
$form-feedback-tooltip-padding-y: $tooltip-padding-y !default;
$form-feedback-tooltip-padding-x: $tooltip-padding-x !default;
$form-feedback-tooltip-font-size: $tooltip-font-size !default;
$form-feedback-tooltip-line-height: $line-height-base !default;
$form-feedback-tooltip-opacity: $tooltip-opacity !default;
$form-feedback-tooltip-border-radius: $tooltip-border-radius !default;

// Popovers

$popover-font-size: $font-size-sm !default;
$popover-bg: $white !default;
$popover-max-width: 276px !default;
$popover-border-width: $border-width !default;
$popover-border-color: rgba($black, .2) !default;
$popover-border-radius: $border-radius-lg !default;
$popover-box-shadow: 0 .25rem .5rem rgba($black, .2) !default;

$popover-header-bg: darken($popover-bg, 3%) !default;
$popover-header-color: $headings-color !default;
$popover-header-padding-y: .5rem !default;
$popover-header-padding-x: .75rem !default;

$popover-body-color: $body-color !default;
$popover-body-padding-y: $popover-header-padding-y !default;
$popover-body-padding-x: $popover-header-padding-x !default;

$popover-arrow-width: 1rem !default;
$popover-arrow-height: .5rem !default;
$popover-arrow-color: $popover-bg !default;

$popover-arrow-outer-color: fade-in($popover-border-color, .05) !default;


// Badges

$badge-font-size: 75% !default;
$badge-font-weight: $font-weight-bold !default;
$badge-padding-y: .25em !default;
$badge-padding-x: .4em !default;
$badge-border-radius: $border-radius !default;

$badge-pill-padding-x: .6em !default;
// Use a higher than normal value to ensure completely rounded edges when
// customizing padding or font-size on labels.
$badge-pill-border-radius: 10rem !default;


// Modals

// Padding applied to the modal body
$modal-inner-padding: 1rem !default;

$modal-dialog-margin: .5rem !default;
$modal-dialog-margin-y-sm-up: 1.75rem !default;

$modal-title-line-height: $line-height-base !default;

$modal-content-bg: $white !default;
$modal-content-border-color: rgba($black, .2) !default;
$modal-content-border-width: $border-width !default;
$modal-content-border-radius: $border-radius-lg !default;
$modal-content-box-shadow-xs: 0 .25rem .5rem rgba($black, .5) !default;
$modal-content-box-shadow-sm-up: 0 .5rem 1rem rgba($black, .5) !default;

$modal-backdrop-bg: $black !default;
$modal-backdrop-opacity: .5 !default;
$modal-header-border-color: $gray-200 !default;
$modal-footer-border-color: $modal-header-border-color !default;
$modal-header-border-width: $modal-content-border-width !default;
$modal-footer-border-width: $modal-header-border-width !default;
$modal-header-padding: 1rem !default;

$modal-lg: 800px !default;
$modal-md: 500px !default;
$modal-sm: 300px !default;

$modal-transition: transform .3s ease-out !default;


// Alerts
//
// Define alert colors, border radius, and padding.

$alert-padding-y: .75rem !default;
$alert-padding-x: 1.25rem !default;
$alert-margin-bottom: 1rem !default;
$alert-border-radius: $border-radius !default;
$alert-link-font-weight: $font-weight-bold !default;
$alert-border-width: $border-width !default;

$alert-bg-level: -10 !default;
$alert-border-level: -9 !default;
$alert-color-level: 6 !default;


// Progress bars

$progress-height: 1rem !default;
$progress-font-size: ($font-size-base * .75) !default;
$progress-bg: $gray-200 !default;
$progress-border-radius: $border-radius !default;
$progress-box-shadow: inset 0 .1rem .1rem rgba($black, .1) !default;
$progress-bar-color: $white !default;
$progress-bar-bg: theme-color("primary") !default;
$progress-bar-animation-timing: 1s linear infinite !default;
$progress-bar-transition: width .6s ease !default;

// List group

$list-group-bg: $white !default;
$list-group-border-color: rgba($black, .125) !default;
$list-group-border-width: $border-width !default;
$list-group-border-radius: $border-radius !default;

$list-group-item-padding-y: .75rem !default;
$list-group-item-padding-x: 1.25rem !default;

$list-group-hover-bg: $gray-100 !default;
$list-group-active-color: $component-active-color !default;
$list-group-active-bg: $component-active-bg !default;
$list-group-active-border-color: $list-group-active-bg !default;

$list-group-disabled-color: $gray-600 !default;
$list-group-disabled-bg: $list-group-bg !default;

$list-group-action-color: $gray-700 !default;
$list-group-action-hover-color: $list-group-action-color !default;

$list-group-action-active-color: $body-color !default;
$list-group-action-active-bg: $gray-200 !default;


// Image thumbnails

$thumbnail-padding: .25rem !default;
$thumbnail-bg: $body-bg !default;
$thumbnail-border-width: $border-width !default;
$thumbnail-border-color: $gray-300 !default;
$thumbnail-border-radius: $border-radius !default;
$thumbnail-box-shadow: 0 1px 2px rgba($black, .075) !default;


// Figures

$figure-caption-font-size: 90% !default;
$figure-caption-color: $gray-600 !default;


// Breadcrumbs

$breadcrumb-padding-y: .75rem !default;
$breadcrumb-padding-x: 1rem !default;
$breadcrumb-item-padding: .5rem !default;

$breadcrumb-margin-bottom: 1rem !default;

$breadcrumb-bg: $gray-200 !default;
$breadcrumb-divider-color: $gray-600 !default;
$breadcrumb-active-color: $gray-600 !default;
$breadcrumb-divider: "/" !default;


// Carousel

$carousel-control-color: $white !default;
$carousel-control-width: 15% !default;
$carousel-control-opacity: .5 !default;

$carousel-indicator-width: 30px !default;
$carousel-indicator-height: 3px !default;
$carousel-indicator-spacer: 3px !default;
$carousel-indicator-active-bg: $white !default;

$carousel-caption-width: 70% !default;
$carousel-caption-color: $white !default;

$carousel-control-icon-width: 20px !default;

$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;
$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;

$carousel-transition: transform .6s ease !default;


// Close

$close-font-size: $font-size-base * 1.5 !default;
$close-font-weight: $font-weight-bold !default;
$close-color: $black !default;
$close-text-shadow: 0 1px 0 $white !default;

// Code

$code-font-size: 87.5% !default;
$code-color: $pink !default;

$kbd-padding-y: .2rem !default;
$kbd-padding-x: .4rem !default;
$kbd-font-size: $code-font-size !default;
$kbd-color: $white !default;
$kbd-bg: $gray-900 !default;

$pre-color: $gray-900 !default;
$pre-scrollable-max-height: 340px !default;


// Printing
$print-page-size: a3 !default;
$print-body-min-width: map-get($grid-breakpoints, "lg") !default;

+ 106
- 0
MVCTemplate/wwwroot/build/scss/_brand.scss Zobrazit soubor

@@ -0,0 +1,106 @@
//
// Component: Brand
//

.brand-link {
$brand-link-padding-y: $navbar-brand-padding-y + $navbar-padding-y;
display: block;
font-size: $navbar-brand-font-size;
line-height: $line-height-lg;
padding: $brand-link-padding-y $sidebar-padding-x;
transition: width $transition-speed $transition-fn;
white-space: nowrap;

&:hover {
color: $white;
text-decoration: none;
}

.text-sm & {
font-size: inherit;
}

[class*="sidebar-dark"] & {
border-bottom: 1px solid lighten($dark, 10%);

&,
.pushmenu {
color: rgba($white, .8);

&:hover {
color: $white;
}
}
}

[class*="sidebar-light"] & {
border-bottom: 1px solid $gray-300;

&,
.pushmenu {
color: rgba($black, .8);

&:hover {
color: $black;
}
}
}

.pushmenu {
margin-right: $sidebar-padding-x;
font-size: $font-size-base;
}

.brand-link {
padding: 0;
border-bottom: none;
}

.brand-image {
float: left;
line-height: .8;
margin-left: .8rem;
margin-right: .5rem;
margin-top: -3px;
max-height: 33px;
width: auto;
}

.brand-image-xs {
float: left;
line-height: .8;
margin-top: -.1rem;
max-height: 33px;
width: auto;
}

.brand-image-xl {
line-height: .8;
max-height: 40px;
width: auto;

&.single {
margin-top: -.3rem;
}
}

&.text-sm,
.text-sm & {
.brand-image {
height: 29px;
margin-bottom: -.25rem;
margin-left: .95rem;
margin-top: -.25rem;
}

.brand-image-xs {
margin-top: -.2rem;
max-height: 29px;
}

.brand-image-xl {
margin-top: -.225rem;
max-height: 38px;
}
}
}

+ 154
- 0
MVCTemplate/wwwroot/build/scss/_buttons.scss Zobrazit soubor

@@ -0,0 +1,154 @@
//
// Component: Button
//

.btn {
&.disabled,
&:disabled {
cursor: not-allowed;
}

// Flat buttons
&.btn-flat {
@include border-radius(0);
border-width: 1px;
box-shadow: none;
}

// input file btn
&.btn-file {
overflow: hidden;
position: relative;

> input[type="file"] {
background-color: $white;
cursor: inherit;
display: block;
font-size: 100px;
min-height: 100%;
min-width: 100%;
opacity: 0;
outline: none;
position: absolute;
right: 0;
text-align: right;
top: 0;
}
}

.text-sm & {
font-size: $font-size-sm !important;
}
}

// Button color variations
.btn-default {
background-color: $button-default-background-color;
border-color: $button-default-border-color;
color: $button-default-color;

&:hover,
&:active,
&.hover {
background-color: darken($button-default-background-color, 5%);
color: darken($button-default-color, 10%);
}
}

// Application buttons
.btn-app {
@include border-radius(3px);
background-color: $button-default-background-color;
border: 1px solid $button-default-border-color;
color: $gray-600;
font-size: 12px;
height: 60px;
margin: 0 0 10px 10px;
min-width: 80px;
padding: 15px 5px;
position: relative;
text-align: center;

// Icons within the btn
> .fa,
> .fas,
> .far,
> .fab,
> .fal,
> .fad,
> .svg-inline--fa,
> .ion {
display: block;
font-size: 20px;
}

> .svg-inline--fa {
margin: 0 auto;
}

&:hover {
background-color: $button-default-background-color;
border-color: darken($button-default-border-color, 20%);
color: $button-default-color;
}

&:active,
&:focus {
@include box-shadow(inset 0 3px 5px rgba($black, .125));
}

// The badge
> .badge {
font-size: 10px;
font-weight: 400;
position: absolute;
right: -10px;
top: -3px;
}
}

// Extra Button Size

.btn-xs {
@include button-size($button-padding-y-xs, $button-padding-x-xs, $button-font-size-xs, $button-line-height-xs, $button-border-radius-xs);
}

.dark-mode {
.btn-default,
.btn-app {
background-color: lighten($dark, 2.5%);
color: $white;
border-color: $gray-600;

&:hover,
&:focus {
background-color: lighten($dark, 5%);
color: $gray-300;
border-color: lighten($gray-600, 2.5%);
}
}
.btn-light {
background-color: lighten($dark, 7.5%);
color: $white;
border-color: $gray-600;

&:hover,
&:focus {
background-color: lighten($dark, 10%);
color: $gray-300;
border-color: lighten($gray-600, 5%);
}
}

@each $color, $value in $theme-colors-alt {
.btn-#{$color} {
@include button-variant($value, $value);
}
}

@each $color, $value in $theme-colors-alt {
.btn-outline-#{$color} {
@include button-outline-variant($value);
}
}
}

+ 73
- 0
MVCTemplate/wwwroot/build/scss/_callout.scss Zobrazit soubor

@@ -0,0 +1,73 @@
//
// Component: Callout
//

// Base styles (regardless of theme)
.callout {
@if $enable-rounded {
@include border-radius($border-radius);
}

@if $enable-shadows {
box-shadow: map-get($elevations, 1);
} @else {
border: 1px solid $gray-300;
}

background-color: $white;
border-left: 5px solid $gray-200;
margin-bottom: map-get($spacers, 3);
padding: 1rem;

a {
color: $gray-700;
text-decoration: underline;

&:hover {
color: $gray-200;
}
}

p:last-child {
margin-bottom: 0;
}

// Themes for different contexts
&.callout-danger {
border-left-color: darken(theme-color("danger"), 10%);
}

&.callout-warning {
border-left-color: darken(theme-color("warning"), 10%);
}

&.callout-info {
border-left-color: darken(theme-color("info"), 10%);
}

&.callout-success {
border-left-color: darken(theme-color("success"), 10%);
}
}

.dark-mode {
.callout {
background-color: lighten($dark, 5%);

&.callout-danger {
border-left-color: lighten($danger-alt, 10%);
}

&.callout-warning {
border-left-color: lighten($warning-alt, 10%);
}

&.callout-info {
border-left-color: lighten($info-alt, 10%);
}

&.callout-success {
border-left-color: lighten($success-alt, 10%);
}
}
}

+ 545
- 0
MVCTemplate/wwwroot/build/scss/_cards.scss Zobrazit soubor

@@ -0,0 +1,545 @@
//
// Component: Cards
//

// Color variants
@each $name, $color in $theme-colors {
@include cards-variant($name, $color);
}

@each $name, $color in $colors {
@include cards-variant($name, $color);
}

.card {
@include box-shadow($card-shadow);
margin-bottom: map-get($spacers, 3);

&.bg-dark {
.card-header {
border-color: $card-dark-border-color;
}

&,
.card-body {
color: $white;
}
}

&.maximized-card {
height: 100% !important;
left: 0;
max-height: 100% !important;
max-width: 100% !important;
position: fixed;
top: 0;
width: 100% !important;
z-index: $zindex-modal-backdrop;

&.was-collapsed .card-body {
display: block !important;
}

.card-body {
overflow: auto;
}

[data-card-widgett="collapse"] {
display: none;
}

.card-header,
.card-footer {
@include border-radius(0 !important);
}
}

// collapsed mode
&.collapsed-card {
.card-body,
.card-footer {
display: none;
}
}

.nav.flex-column {
> li {
border-bottom: 1px solid $card-border-color;
margin: 0;

&:last-of-type {
border-bottom: 0;
}
}
}

// fixed height to 300px
&.height-control {
.card-body {
max-height: 300px;
overflow: auto;
}
}

.border-right {
border-right: 1px solid $card-border-color;
}

.border-left {
border-left: 1px solid $card-border-color;
}

&.card-tabs {
&:not(.card-outline) {
> .card-header {
border-bottom: 0;

.nav-item {
&:first-child .nav-link {
border-left-color: transparent;
}
}
}
}

&.card-outline {
.nav-item {
border-bottom: 0;

&:first-child .nav-link {
border-left: 0;
margin-left: 0;
}
}
}

.card-tools {
margin: .3rem .5rem;
}

&:not(.expanding-card).collapsed-card {
.card-header {
border-bottom: 0;

.nav-tabs {
border-bottom: 0;

.nav-item {
margin-bottom: 0;
}
}
}
}

&.expanding-card {
.card-header {
.nav-tabs {
.nav-item {
margin-bottom: -1px;
}
}
}
}
}

&.card-outline-tabs {
border-top: 0;

.card-header {
.nav-item {
&:first-child .nav-link {
border-left: 0;
margin-left: 0;
}
}

a {
border-top: 3px solid transparent;

&:hover {
border-top: 3px solid $nav-tabs-border-color;
}

&.active {
&:hover {
margin-top: 0;
}
}
}
}

.card-tools {
margin: .5rem .5rem .3rem;
}

&:not(.expanding-card).collapsed-card .card-header {
border-bottom: 0;

.nav-tabs {
border-bottom: 0;

.nav-item {
margin-bottom: 0;
}
}
}

&.expanding-card {
.card-header {
.nav-tabs {
.nav-item {
margin-bottom: -1px;
}
}
}
}
}

}

// Maximized Card Body Scroll fix
html.maximized-card {
overflow: hidden;
}

// Add clearfix to header, body and footer
.card-header,
.card-body,
.card-footer {
@include clearfix ();
}

// Box header
.card-header {
background-color: transparent;
border-bottom: 1px solid $card-border-color;
padding: (($card-spacer-y / 2) * 2) $card-spacer-x;
position: relative;

@if $enable-rounded {
@include border-top-radius($border-radius);
}

.collapsed-card & {
border-bottom: 0;
}

> .card-tools {
float: right;
margin-right: -$card-spacer-x / 2;

.input-group,
.nav,
.pagination {
margin-bottom: -$card-spacer-y / 2.5;
margin-top: -$card-spacer-y / 2.5;
}

[data-toggle="tooltip"] {
position: relative;
}
}
}

.card-title {
float: left;
font-size: $card-title-font-size;
font-weight: $card-title-font-weight;
margin: 0;
}

.card-text {
clear: both;
}


// Box Tools Buttons
.btn-tool {
background-color: transparent;
color: $gray-500;
font-size: $font-size-sm;
margin: -(($card-spacer-y / 2) * 2) 0;
padding: .25rem .5rem;

.btn-group.show &,
&:hover {
color: $gray-700;
}

.show &,
&:focus {
box-shadow: none !important;
}
}

.text-sm {
.card-title {
font-size: $card-title-font-size-sm;
}

.nav-link {
padding: $card-nav-link-padding-sm-y $card-nav-link-padding-sm-x;
}
}

// Box Body
.card-body {
// @include border-radius-sides(0, 0, $border-radius, $border-radius);
// .no-header & {
// @include border-top-radius($border-radius);
// }

// Tables within the box body
> .table {
margin-bottom: 0;

> thead > tr > th,
> thead > tr > td {
border-top-width: 0;
}
}

// Calendar within the box body
.fc {
margin-top: 5px;
}

.full-width-chart {
margin: -19px;
}

&.p-0 .full-width-chart {
margin: -9px;
}
}

.chart-legend {
@include list-unstyled ();
margin: 10px 0;

> li {
@media (max-width: map-get($grid-breakpoints, sm)) {
float: left;
margin-right: 10px;
}
}
}

// Comment Box
.card-comments {
background-color: $gray-100;

.card-comment {
@include clearfix ();
border-bottom: 1px solid $gray-200;
padding: 8px 0;

&:last-of-type {
border-bottom: 0;
}

&:first-of-type {
padding-top: 0;
}

img {
height: $card-img-size;
width: $card-img-size;
float: left;
}
}

.comment-text {
color: lighten($gray-700, 20%);
margin-left: 40px;
}

.username {
color: $gray-700;
display: block;
font-weight: 600;
}

.text-muted {
font-size: 12px;
font-weight: 400;
}
}

// Widgets
//-----------

// Widget: TODO LIST
.todo-list {
list-style: none;
margin: 0;
overflow: auto;
padding: 0;

// Todo list element
> li {
@include border-radius(2px);
background-color: $gray-100;
border-left: 2px solid $gray-200;
color: $gray-700;
margin-bottom: 2px;
padding: 10px;

&:last-of-type {
margin-bottom: 0;
}

> input[type="checkbox"] {
margin: 0 10px 0 5px;
}

.text {
display: inline-block;
font-weight: 600;
margin-left: 5px;
}

// Time labels
.badge {
font-size: .7rem;
margin-left: 10px;
}

// Tools and options box
.tools {
color: theme-color("danger");
display: none;
float: right;

// icons
> .fa,
> .fas,
> .far,
> .fab,
> .fal,
> .fad,
> .svg-inline--fa,
> .ion {
cursor: pointer;
margin-right: 5px;
}
}

&:hover .tools {
display: inline-block;
}

&.done {
color: darken($gray-500, 25%);

.text {
font-weight: 500;
text-decoration: line-through;
}

.badge {
background-color: $gray-500 !important;
}
}
}

// Color variants
@each $name, $color in $theme-colors {
.#{$name} {
border-left-color: $color;
}
}

@each $name, $color in $colors {
.#{$name} {
border-left-color: $color;
}
}

.handle {
cursor: move;
display: inline-block;
margin: 0 5px;
}
}

// END TODO WIDGET

// Input in box
.card-input {
max-width: 200px;
}

// Nav Tabs override
.card-default {
.nav-item {
&:first-child .nav-link {
border-left: 0;
}
}
}

.dark-mode {

// Color variants
@each $name, $color in $theme-colors-alt {
@include cards-variant($name, $color);
}

@each $name, $color in $colors-alt {
@include cards-variant($name, $color);
}

.card {
background-color: $dark;
color: $white;

.card {
background-color: lighten($dark, 5%);
color: $white;
}
.nav.flex-column > li {
border-bottom-color: $gray-600;
}
.card-footer {
background-color: rgba($black, .1);
}
&.card-outline-tabs .card-header a:hover {
border-color: $gray-600;
border-bottom-color: transparent;
}
&:not(.card-outline) > .card-header a.active {
color: $white;
}
}

.card-comments {
background-color: lighten($dark, 1.25%);
.username {
color: $gray-400;
}
.card-comment {
border-bottom-color: lighten($dark, 7.5%);
}
}

.todo-list > li {
background-color: lighten($dark, 5%);
border-color: lighten($dark, 7.5%);
color: $white;
}

.todo-list {
@each $name, $color in $theme-colors-alt {
.#{$name} {
border-left-color: $color;
}
}

@each $name, $color in $colors-alt {
.#{$name} {
border-left-color: $color;
}
}
}
}

+ 28
- 0
MVCTemplate/wwwroot/build/scss/_carousel.scss Zobrazit soubor

@@ -0,0 +1,28 @@
//
// Component: Carousel
//

.carousel-control-custom-icon {
.carousel-control-prev & {
margin-left: -20px;
}
.carousel-control-next & {
margin-right: 20px;
}

> .fa,
> .fas,
> .far,
> .fab,
> .fal,
> .fad,
> .svg-inline--fa,
> .ion {
display: inline-block;
font-size: 40px;
margin-top: -20px;
position: absolute;
top: 50%;
z-index: 5;
}
}

+ 44
- 0
MVCTemplate/wwwroot/build/scss/_close.scss Zobrazit soubor

@@ -0,0 +1,44 @@
.close {
float: right;
@include font-size($close-font-size);
font-weight: $close-font-weight;
line-height: 1;
color: $close-color;
text-shadow: $close-text-shadow;
opacity: .5;

// Override <a>'s hover style
@include hover() {
color: $close-color;
text-decoration: none;
}

&:not(:disabled):not(.disabled) {
@include hover-focus() {
opacity: .75;
}
}

&:focus {
outline: none;
}
}

// Additional properties for button version
// iOS requires the button element instead of an anchor tag.
// If you want the anchor version, it requires `href="#"`.
// See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile

// stylelint-disable-next-line selector-no-qualifying-type
button.close {
padding: 0;
background-color: transparent;
border: 0;
}

// Future-proof disabling of clicks on `<a>` elements

// stylelint-disable-next-line selector-no-qualifying-type
a.close.disabled {
pointer-events: none;
}

+ 144
- 0
MVCTemplate/wwwroot/build/scss/_colors.scss Zobrazit soubor

@@ -0,0 +1,144 @@
//
// Misc: Colors
//

// Background colors (theme colors)
@each $name, $color in $theme-colors {
@include background-variant($name, $color);
}

// Background colors (colors)
@each $name, $color in $colors {
@include background-variant($name, $color);
}

.bg-gray {
background-color: $gray-500;
color: color-yiq($gray-500);
}

.bg-gray-light {
background-color: lighten($gray-200, 3%);
color: color-yiq(lighten($gray-200, 3%)) !important;
}

.bg-black {
background-color: $black;
color: color-yiq($black) !important;
}

.bg-white {
background-color: $white;
color: color-yiq($white) !important;
}

// Gradient Background colors (theme colors)
@each $name, $color in $theme-colors {
@include background-gradient-variant($name, $color);
}

// Gradient Background colors (colors)
@each $name, $color in $colors {
@include background-gradient-variant($name, $color);
}

// Backgrund Color Disabled
[class^="bg-"].disabled {
opacity: .65;
}

// Text muted hover
a.text-muted:hover {
color: theme-color(primary) !important;
}

// Link Styles
.link-muted {
color: darken($gray-500, 30%);

&:hover,
&:focus {
color: darken($gray-500, 40%);
}
}

.link-black {
color: $gray-600;

&:hover,
&:focus {
color: lighten($gray-500, 20%);
}
}

// Accent colors (theme colors)
@each $name, $color in $theme-colors {
@include accent-variant($name, $color);
}

// Accent colors (colors)
@each $name, $color in $colors {
@include accent-variant($name, $color);
}

// Accent button override fix
[class*="accent-"] {
@each $name, $color in $theme-colors {
a.btn-#{$name} {
color: color-yiq($color);
}
}
}

.dark-mode {
.bg-light {
background-color: lighten($dark, 7.5%) !important;
color: $white !important;
}
.text-black,
.text-dark,
.link-black,
.link-dark {
color: $gray-400;
}

// Background colors (theme colors)
@each $name, $color in $theme-colors-alt {
@include background-variant($name, $color);
}

// Background colors (colors)
@each $name, $color in $colors-alt {
@include background-variant($name, $color);
}

// Gradient Background colors (theme colors)
@each $name, $color in $theme-colors-alt {
@include background-gradient-variant($name, $color);
}

// Gradient Background colors (colors)
@each $name, $color in $colors-alt {
@include background-gradient-variant($name, $color);
}

// Accent colors (theme colors)
@each $name, $color in $theme-colors-alt {
@include accent-variant($name, $color);
}

[class*="accent-"] {
@each $name, $color in $theme-colors-alt {
a.btn-#{$name} {
color: color-yiq($color);
}
}
}

// Accent colors (colors)
@each $name, $color in $colors-alt {
@include accent-variant($name, $color);
}
}

//

+ 173
- 0
MVCTemplate/wwwroot/build/scss/_control-sidebar.scss Zobrazit soubor

@@ -0,0 +1,173 @@
//
// Component: Control Sidebar
//

html.control-sidebar-animate {
overflow-x: hidden;
}

.control-sidebar {
bottom: $main-footer-height;
position: absolute;
top: $main-header-height;
z-index: $zindex-control-sidebar;

&,
&::before {
bottom: $main-footer-height;
display: none;
right: -$control-sidebar-width;
width: $control-sidebar-width;
@include transition(right $transition-speed $transition-fn, display $transition-speed $transition-fn);
}

&::before {
content: "";
display: block;
position: fixed;
top: 0;
z-index: -1;
}
}

body.text-sm {
.control-sidebar {
bottom: $main-footer-height-sm;
top: $main-header-height-sm;
}
}

.main-header.text-sm ~ .control-sidebar {
top: $main-header-height-sm;
}

.main-footer.text-sm ~ .control-sidebar {
bottom: $main-footer-height-sm;
}

.control-sidebar-push-slide {
.content-wrapper,
.main-footer {
@include transition(margin-right $transition-speed $transition-fn);
}
}

// Control sidebar open state
.control-sidebar-open {
.control-sidebar {
display: block;

&,
&::before {
right: 0;
}
}

&.control-sidebar-push,
&.control-sidebar-push-slide {
.content-wrapper,
.main-footer {
margin-right: $control-sidebar-width;
}
}
}

// Control sidebar slide over content state
.control-sidebar-slide-open {
.control-sidebar {
display: block;

&,
&::before {
right: 0;
@include transition(right $transition-speed $transition-fn, display $transition-speed $transition-fn);
}
}

&.control-sidebar-push,
&.control-sidebar-push-slide {
.content-wrapper,
.main-footer {
margin-right: $control-sidebar-width;
}
}
}

// Dark skin
.control-sidebar-dark {
background-color: $sidebar-dark-bg;

&,
a,
.nav-link {
color: $sidebar-dark-color;
}

a:hover {
color: $sidebar-dark-hover-color;
}

// Headers and labels
h1,
h2,
h3,
h4,
h5,
h6,
label {
color: $sidebar-dark-hover-color;
}

// Tabs
.nav-tabs {
background-color: $sidebar-dark-hover-bg;
border-bottom: 0;
margin-bottom: 5px;

.nav-item {
margin: 0;
}

.nav-link {
border-radius: 0;
padding: 10px 20px;
position: relative;
text-align: center;

&,
&:hover,
&:active,
&:focus,
&.active {
border: 0;
}

&:hover,
&:active,
&:focus,
&.active {
border-bottom-color: transparent;
border-left-color: transparent;
border-top-color: transparent;
color: $sidebar-dark-hover-color;
}

&.active {
background-color: $sidebar-dark-bg;
}
}
}

.tab-pane {
padding: 10px 15px;
}
}

// Light skin
.control-sidebar-light {
color: lighten($sidebar-light-color, 10%);

// Background
background-color: $sidebar-light-bg;
border-left: $main-header-bottom-border;
}

+ 259
- 0
MVCTemplate/wwwroot/build/scss/_direct-chat.scss Zobrazit soubor

@@ -0,0 +1,259 @@
//
// Component: Direct Chat
//

.direct-chat {
.card-body {
overflow-x: hidden;
padding: 0;
position: relative;
}

&.chat-pane-open {
.direct-chat-contacts {
@include translate(0, 0);
}
}


&.timestamp-light {
.direct-chat-timestamp {
color: lighten(color-yiq($yiq-text-light), 10%);
}
}

&.timestamp-dark {
.direct-chat-timestamp {
color: darken(color-yiq($yiq-text-dark), 20%);
}
}
}

.direct-chat-messages {
@include translate(0, 0);
height: 250px;
overflow: auto;
padding: 10px;
}

.direct-chat-msg,
.direct-chat-text {
display: block;
}

.direct-chat-msg {
@include clearfix ();
margin-bottom: 10px;
}

.direct-chat-messages,
.direct-chat-contacts {
transition: transform .5s ease-in-out;
}

.direct-chat-text {
@if $enable-rounded {
@include border-radius($border-radius-lg);
}

background-color: $direct-chat-default-msg-bg;
border: 1px solid $direct-chat-default-msg-border-color;
color: $direct-chat-default-font-color;
margin: 5px 0 0 50px;
padding: 5px 10px;
position: relative;

//Create the arrow
&::after,
&::before {
border: solid transparent;
border-right-color: $direct-chat-default-msg-border-color;
content: " ";
height: 0;
pointer-events: none;
position: absolute;
right: 100%;
top: 15px;
width: 0;
}

&::after {
border-width: 5px;
margin-top: -5px;
}

&::before {
border-width: 6px;
margin-top: -6px;
}

.right & {
margin-left: 0;
margin-right: 50px;

&::after,
&::before {
border-left-color: $direct-chat-default-msg-border-color;
border-right-color: transparent;
left: 100%;
right: auto;
}
}
}

.direct-chat-img {
@include border-radius(50%);
float: left;
height: 40px;
width: 40px;

.right & {
float: right;
}
}

.direct-chat-infos {
display: block;
font-size: $font-size-sm;
margin-bottom: 2px;
}

.direct-chat-name {
font-weight: 600;
}

.direct-chat-timestamp {
color: darken($gray-500, 25%);
}

//Direct chat contacts pane
.direct-chat-contacts-open {
.direct-chat-contacts {
@include translate(0, 0);
}
}

.direct-chat-contacts {
@include translate(101%, 0);
background-color: $dark;
bottom: 0;
color: $white;
height: 250px;
overflow: auto;
position: absolute;
top: 0;
width: 100%;
}

.direct-chat-contacts-light {
background-color: $light;

.contacts-list-name {
color: $gray-700;
}

.contacts-list-date {
color: $gray-600;
}

.contacts-list-msg {
color: darken($gray-600, 10%);
}
}

//Contacts list -- for displaying contacts in direct chat contacts pane
.contacts-list {
@include list-unstyled ();

> li {
@include clearfix ();
border-bottom: 1px solid rgba($black, .2);
margin: 0;
padding: 10px;

&:last-of-type {
border-bottom: 0;
}
}
}

.contacts-list-img {
@include border-radius(50%);
float: left;
width: 40px;
}

.contacts-list-info {
color: $white;
margin-left: 45px;
}

.contacts-list-name,
.contacts-list-status {
display: block;
}

.contacts-list-name {
font-weight: 600;
}

.contacts-list-status {
font-size: $font-size-sm;
}

.contacts-list-date {
color: $gray-400;
font-weight: 400;
}

.contacts-list-msg {
color: darken($gray-400, 10%);
}

// Color variants
@each $name, $color in $theme-colors {
.direct-chat-#{$name} {
@include direct-chat-variant($color);
}
}

@each $name, $color in $colors {
.direct-chat-#{$name} {
@include direct-chat-variant($color);
}
}

.dark-mode {
.direct-chat-text {
background-color: lighten($dark, 7.5%);
border-color: lighten($dark, 10%);
color: $white;

&::after,
&::before {
border-right-color: lighten($dark, 10%);
}
}
.direct-chat-timestamp {
color: $gray-500;
}
.right > .direct-chat-text {
&::after,
&::before {
border-right-color: transparent;
}
}

// Color variants
@each $name, $color in $theme-colors-alt {
.direct-chat-#{$name} {
@include direct-chat-variant($color);
}
}

@each $name, $color in $colors-alt {
.direct-chat-#{$name} {
@include direct-chat-variant($color);
}
}
}

+ 295
- 0
MVCTemplate/wwwroot/build/scss/_dropdown.scss Zobrazit soubor

@@ -0,0 +1,295 @@
//
// Component: Dropdown
//

// General Dropdown Rules
//.dropdown-item {
// &:first-of-type {
// @include border-top-radius($border-radius);
// }
// &:last-of-type {
// @include border-bottom-radius($border-radius);
// }
//}

.text-sm {
.dropdown-menu {
font-size: $font-size-sm !important;
}

.dropdown-toggle::after {
vertical-align: .2rem;
}
}

.dropdown-item-title {
font-size: $font-size-base;
margin: 0;
}

.dropdown-icon {
&::after {
margin-left: 0;
}
}

// Dropdown Sizes
.dropdown-menu-lg {
max-width: 300px;
min-width: 280px;
padding: 0;

.dropdown-divider {
margin: 0;
}

.dropdown-item {
padding: $dropdown-padding-y $dropdown-item-padding-x;
}

p {
margin: 0;
white-space: normal;
}
}

// Dropdown Submenu
.dropdown-submenu {
position: relative;

> a::after {
@include caret-right ();
float: right;
margin-left: .5rem;
margin-top: .5rem;
}

> .dropdown-menu {
left: 100%;
margin-left: 0;
margin-top: 0;
top: 0;
}
}

// Dropdown Hover
.dropdown-hover {
&:hover,
&.nav-item.dropdown:hover,
.dropdown-submenu:hover,
&.dropdown-submenu:hover {
> .dropdown-menu {
display: block;
}
}
}


// Dropdown Sizes
.dropdown-menu-xl {
max-width: 420px;
min-width: 360px;
padding: 0;

.dropdown-divider {
margin: 0;
}

.dropdown-item {
padding: $dropdown-padding-y $dropdown-item-padding-x;
}

p {
margin: 0;
white-space: normal;
}
}

// Dropdown header and footer
.dropdown-footer,
.dropdown-header {
display: block;
font-size: $font-size-sm;
padding: .5rem $dropdown-item-padding-x;
text-align: center;
}

// Add fade animation to dropdown menus by appending
// the class .animated-dropdown-menu to the .dropdown-menu ul (or ol)
.open:not(.dropup) > .animated-dropdown-menu {
@include animation(flipInX .7s both);
backface-visibility: visible !important;
}

// Fix dropdown menu in navbars
.navbar-custom-menu > .navbar-nav {
> li {
position: relative;
> .dropdown-menu {
position: absolute;
right: 0;
left: auto;
}
}
}

@include media-breakpoint-down(sm) {
.navbar-custom-menu > .navbar-nav {
float: right;
> li {
position: static;
> .dropdown-menu {
position: absolute;
right: 5%;
left: auto;
border: 1px solid #ddd;
background-color: $white;
}
}
}
}

// User Menu
.navbar-nav > .user-menu {
> .nav-link::after {
content: none;
}

> .dropdown-menu {
@include border-top-radius(0);
padding: 0;
width: 280px;

&,
> .user-body {
@include border-bottom-radius(4px);
}

// Header menu
> li.user-header {
height: 175px;
padding: 10px;
text-align: center;

// User image
> img {
z-index: 5;
height: 90px;
width: 90px;
border: 3px solid;
border-color: transparent;
border-color: rgba(255, 255, 255, .2);
}

> p {
z-index: 5;
font-size: 17px;
//text-shadow: 2px 2px 3px #333333;
margin-top: 10px;

> small {
display: block;
font-size: 12px;
}
}
}

// Menu Body
> .user-body {
@include clearfix ();
border-bottom: 1px solid $gray-700;
border-top: 1px solid $gray-300;
padding: 15px;

a {
@include media-breakpoint-up(sm) {
background-color: $white !important;
color: $gray-700 !important;
}
}
}

// Menu Footer
> .user-footer {
@include clearfix ();
background-color: $gray-100;
padding: 10px;

.btn-default {
color: $gray-600;

&:hover {
@include media-breakpoint-up(sm) {
background-color: $gray-100;
}
}
}
}
}

.user-image {
@include media-breakpoint-up(sm) {
float: none;
line-height: 10px;
margin-right: .4rem;
margin-top: -8px;
}

border-radius: 50%;
float: left;
height: $sidebar-user-image-width;
margin-right: 10px;
margin-top: -2px;
width: $sidebar-user-image-width;
}
}

.dark-mode {
.dropdown-menu {
background-color: $dark;
color: $white;
}
.dropdown-item {
color: $white;

&:focus,
&:hover {
background-color: lighten($dark, 5%);
}
}
.dropdown-divider {
border-color: $gray-600;
}

.navbar-nav > .user-menu > .dropdown-menu {
> .user-footer {
background-color: lighten($dark, 2.5%);
color: $white;

.btn-default {
color: $white;

&:hover,
&:focus {
background-color: lighten($dark, 5%);
color: $gray-300;
}
&:focus {
background-color: lighten($dark, 7.5%);
}
}
}
> .user-body {
border-color: $gray-600;
}
> .user-body a {
background-color: transparent !important;
color: $white !important;

&:hover,
&:focus {
color: $gray-400 !important;
}
}
}
}

+ 14
- 0
MVCTemplate/wwwroot/build/scss/_elevation.scss Zobrazit soubor

@@ -0,0 +1,14 @@
//
// Component: Elevation
//

.elevation-0 {
box-shadow: none !important;
}

// Background colors (colors)
@each $name, $value in $elevations {
.elevation-#{$name} {
box-shadow: $value !important;
}
}

+ 431
- 0
MVCTemplate/wwwroot/build/scss/_forms.scss Zobrazit soubor

@@ -0,0 +1,431 @@
//
// Component: Forms
//

.form-group {
&.has-icon {
position: relative;

.form-control {
padding-right: 35px;
}

.form-icon {
background-color: transparent;
border: 0;
cursor: pointer;
font-size: 1rem;
// margin-top: -3px;
padding: $input-btn-padding-y $input-btn-padding-x;
position: absolute;
right: 3px;
top: 0;
}
}
}

// Button groups
.btn-group-vertical {
.btn {
&.btn-flat:first-of-type,
&.btn-flat:last-of-type {
@include border-radius(0);
}
}
}

// Support icons in form-control
.form-control-feedback {
&.fa,
&.fas,
&.far,
&.fab,
&.fal,
&.fad,
&.svg-inline--fa,
&.ion {
line-height: $input-height;
}
}

.input-lg + .form-control-feedback,
.input-group-lg + .form-control-feedback {
&.fa,
&.fas,
&.far,
&.fab,
&.fal,
&.fad,
&.svg-inline--fa,
&.ion {
line-height: $input-height-lg;
}
}

.form-group-lg {
.form-control + .form-control-feedback {
&.fa,
&.fas,
&.far,
&.fab,
&.fal,
&.fad,
&.svg-inline--fa,
&.ion {
line-height: $input-height-lg;
}
}
}

.input-sm + .form-control-feedback,
.input-group-sm + .form-control-feedback {
&.fa,
&.fas,
&.far,
&.fab,
&.fal,
&.fad,
&.svg-inline--fa,
&.ion {
line-height: $input-height-sm;
}
}

.form-group-sm {
.form-control + .form-control-feedback {
&.fa,
&.fas,
&.far,
&.fab,
&.fal,
&.fad,
&.svg-inline--fa,
&.ion {
line-height: $input-height-sm;
}
}
}

label:not(.form-check-label):not(.custom-file-label) {
font-weight: $font-weight-bold;
}

.warning-feedback {
@include font-size($form-feedback-font-size);
color: theme-color("warning");
display: none;
margin-top: $form-feedback-margin-top;
width: 100%;
}

.warning-tooltip {
@include border-radius($form-feedback-tooltip-border-radius);
@include font-size($form-feedback-tooltip-font-size);
background-color: rgba(theme-color("warning"), $form-feedback-tooltip-opacity);
color: color-yiq(theme-color("warning"));
display: none;
line-height: $form-feedback-tooltip-line-height;
margin-top: .1rem;
max-width: 100%; // Contain to parent when possible
padding: $form-feedback-tooltip-padding-y $form-feedback-tooltip-padding-x;
position: absolute;
top: 100%;
z-index: 5;
}

.form-control {
&.is-warning {
border-color: theme-color("warning");

@if $enable-validation-icons {
// padding-right: $input-height-inner;
// background-image: none;
// background-repeat: no-repeat;
// background-position: center right $input-height-inner-quarter;
// background-size: $input-height-inner-half $input-height-inner-half;
}

&:focus {
border-color: theme-color("warning");
box-shadow: 0 0 0 $input-focus-width rgba(theme-color("warning"), .25);
}

~ .warning-feedback,
~ .warning-tooltip {
display: block;
}
}
}

// stylelint-disable-next-line selector-no-qualifying-type
textarea.form-control {
&.is-warning {
@if $enable-validation-icons {
padding-right: $input-height-inner;
background-position: top $input-height-inner-quarter right $input-height-inner-quarter;
}
}
}

.custom-select {
&.is-warning {
border-color: theme-color("warning");

@if $enable-validation-icons {
// padding-right: $custom-select-feedback-icon-padding-right;
// background: $custom-select-background, none $custom-select-bg no-repeat $custom-select-feedback-icon-position / $custom-select-feedback-icon-size;
}

&:focus {
border-color: theme-color("warning");
box-shadow: 0 0 0 $input-focus-width rgba(theme-color("warning"), .25);
}

~ .warning-feedback,
~ .warning-tooltip {
display: block;
}
}
}


.form-control-file {
&.is-warning {
~ .warning-feedback,
~ .warning-tooltip {
display: block;
}
}
}

.form-check-input {
&.is-warning {
~ .form-check-label {
color: theme-color("warning");
}

~ .warning-feedback,
~ .warning-tooltip {
display: block;
}
}
}

.custom-control-input.is-warning {
~ .custom-control-label {
color: theme-color("warning");

&::before {
border-color: theme-color("warning");
}
}

~ .warning-feedback,
~ .warning-tooltip {
display: block;
}

&:checked {
~ .custom-control-label::before {
@include gradient-bg(lighten(theme-color("warning"), 10%));
border-color: lighten(theme-color("warning"), 10%);
}
}

&:focus {
~ .custom-control-label::before {
box-shadow: 0 0 0 $input-focus-width rgba(theme-color("warning"), .25);
}

&:not(:checked) ~ .custom-control-label::before {
border-color: theme-color("warning");
}
}
}

// custom file
.custom-file-input {
&.is-warning {
~ .custom-file-label {
border-color: theme-color("warning");
}

~ .warning-feedback,
~ .warning-tooltip {
display: block;
}

&:focus {
~ .custom-file-label {
border-color: theme-color("warning");
box-shadow: 0 0 0 $input-focus-width rgba(theme-color("warning"), .25);
}
}
}
}

// body.text-sm support
body.text-sm {
.input-group-text {
font-size: $font-size-sm;
}
}

// custom .form-control styles
.form-control,
.custom-select {
&.form-control-border {
border-top: 0;
border-left: 0;
border-right: 0;
border-radius: 0;
box-shadow: inherit;

&.border-width-2 {
border-bottom-width: 2px;
}
&.border-width-3 {
border-bottom-width: 3px;
}
}
}

// custom switch color variations
.custom-switch {
@each $name, $color in $theme-colors {
@include custom-switch-variant($name, $color);
}

@each $name, $color in $colors {
@include custom-switch-variant($name, $color);
}
}

// custom range color variations
.custom-range {
@each $name, $color in $theme-colors {
@include custom-range-variant($name, $color);
}

@each $name, $color in $colors {
@include custom-range-variant($name, $color);
}
}

// custom control input variations
@each $name, $color in $theme-colors {
@include custom-control-input-variant($name, $color);
}

@each $name, $color in $colors {
@include custom-control-input-variant($name, $color);
}

.custom-control-input-outline {
~ .custom-control-label::before {
background-color: transparent !important;
box-shadow: none;
}
&:checked ~ .custom-control-label::before {
@include gradient-bg(transparent);
}
}

.navbar-dark {
.btn-navbar,
.form-control-navbar {
background-color: lighten($sidebar-dark-bg, 5%);
border: 1px solid lighten($sidebar-dark-bg, 15%);
color: lighten(color-yiq(lighten($sidebar-dark-bg, 5%)), 15%);
}
.btn-navbar {
&:hover {
background-color: lighten($sidebar-dark-bg, 7.5%);
}
&:focus {
background-color: lighten($sidebar-dark-bg, 10%);
}
}

.form-control-navbar + .input-group-prepend,
.form-control-navbar + .input-group-append {
> .btn-navbar {
background-color: lighten($sidebar-dark-bg, 5%);
color: $white;
border: 1px solid lighten($sidebar-dark-bg, 15%);
border-left: none;
}
}
}

.dark-mode {
.form-control:not(.form-control-navbar):not(.form-control-sidebar),
.custom-select,
.custom-file-label,
.custom-file-label::after,
.custom-control-label::before,
.input-group-text {
background-color: $dark;
color: $white;
}
.form-control:not(.form-control-navbar):not(.form-control-sidebar):not(.is-invalid):not(:focus),
.custom-file-label,
.custom-file-label::after {
border-color: $gray-600;
}
select {
background-color: $dark;
color: $white;
border-color: $gray-600;
}

.input-group-text {
border-color: $gray-600;
}

.custom-control-input:disabled ~ .custom-control-label::before,
.custom-control-input[disabled] ~ .custom-control-label::before {
background-color: lighten($dark, 5%);
border-color: $gray-600;
color: $white;
}

.custom-range {
&::-webkit-slider-runnable-track {
background-color: lighten($dark, 7.5%);
}
&::-moz-range-track {
background-color: lighten($dark, 7.5%);
}
&::-ms-track {
background-color: lighten($dark, 7.5%);
}

@each $name, $color in $theme-colors-alt {
@include custom-range-variant($name, $color);
}

@each $name, $color in $colors-alt {
@include custom-range-variant($name, $color);
}
}

// custom switch color variations
.custom-switch {
@each $name, $color in $theme-colors-alt {
@include custom-switch-variant($name, $color);
}

@each $name, $color in $colors-alt {
@include custom-switch-variant($name, $color);
}
}

@each $name, $color in $theme-colors-alt {
@include custom-control-input-variant($name, $color);
}

@each $name, $color in $colors-alt {
@include custom-control-input-variant($name, $color);
}
}

+ 165
- 0
MVCTemplate/wwwroot/build/scss/_info-box.scss Zobrazit soubor

@@ -0,0 +1,165 @@
//
// Component: Info Box
//

.info-box {
@include box-shadow($card-shadow);
@include border-radius($border-radius);

background-color: $white;
display: flex;
margin-bottom: map-get($spacers, 3);
min-height: 80px;
padding: .5rem;
position: relative;
width: 100%;

.progress {
background-color: rgba($black, .125);
height: 2px;
margin: 5px 0;

.progress-bar {
background-color: $white;
}
}

.info-box-icon {
@if $enable-rounded {
border-radius: $border-radius;
}

align-items: center;
display: flex;
font-size: 1.875rem;
justify-content: center;
text-align: center;
width: 70px;

> img {
max-width: 100%;
}
}

.info-box-content {
display: flex;
flex-direction: column;
justify-content: center;
line-height: 1.8;
flex: 1;
padding: 0 10px;
}

.info-box-number {
display: block;
margin-top: .25rem;
font-weight: $font-weight-bold;
}

.progress-description,
.info-box-text {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

@each $name, $color in $theme-colors {
.info-box {
.bg-#{$name},
.bg-gradient-#{$name} {
color: color-yiq($color);

.progress-bar {
background-color: color-yiq($color);
}
}
}
}

.info-box-more {
display: block;
}

.progress-description {
margin: 0;

}

@include media-breakpoint-up(md) {
.col-xl-2 &,
.col-lg-2 &,
.col-md-2 & {
.progress-description {
display: none;
}
}

.col-xl-3 &,
.col-lg-3 &,
.col-md-3 & {
.progress-description {
display: none;
}
}
}

@include media-breakpoint-up(lg) {
.col-xl-2 &,
.col-lg-2 &,
.col-md-2 & {
.progress-description {
@include font-size(.75rem);
display: block;
}
}

.col-xl-3 &,
.col-lg-3 &,
.col-md-3 & {
.progress-description {
@include font-size(.75rem);
display: block;
}
}
}

@include media-breakpoint-up(xl) {
.col-xl-2 &,
.col-lg-2 &,
.col-md-2 & {
.progress-description {
@include font-size(1rem);
display: block;
}
}

.col-xl-3 &,
.col-lg-3 &,
.col-md-3 & {
.progress-description {
@include font-size(1rem);
display: block;
}
}
}
}

.dark-mode {
.info-box {
background-color: $dark;
color: $white;
@each $name, $color in $theme-colors-alt {
.info-box {
.bg-#{$name},
.bg-gradient-#{$name} {
color: color-yiq($color);

.progress-bar {
background-color: color-yiq($color);
}
}
}
}
}
}

+ 704
- 0
MVCTemplate/wwwroot/build/scss/_layout.scss Zobrazit soubor

@@ -0,0 +1,704 @@
//
// Core: Layout
//

html.scroll-smooth {
scroll-behavior: smooth;
}

html,
body,
.wrapper {
min-height: 100%;
}

.wrapper {
position: relative;

.content-wrapper {
min-height: calc(100vh - #{$main-header-height} - #{$main-footer-height});
}

.layout-boxed & {
@include box-shadow(0 0 10 rgba($black, .3));

&,
&::before {
margin: 0 auto;
max-width: $boxed-layout-max-width;
}

.main-sidebar {
left: inherit;
}
}

@supports not (-webkit-touch-callout: none) {
.layout-fixed & .sidebar {
height: calc(100vh - (#{$main-header-height-inner} + #{$main-header-bottom-border-width}));
}
.layout-fixed.text-sm & .sidebar {
height: calc(100vh - (#{$main-header-height-sm-inner} + #{$main-header-bottom-border-width}));
}
}

.layout-navbar-fixed.layout-fixed & {
.control-sidebar {
top: $main-header-height;
}

.main-header.text-sm ~ .control-sidebar {
top: $main-header-height-sm;
}

.sidebar {
margin-top: $main-header-height;
}

.brand-link.text-sm ~ .sidebar {
margin-top: $main-header-height-sm;
}
}

.layout-navbar-fixed.layout-fixed.text-sm & {
.control-sidebar {
top: $main-header-height-sm;
}

.sidebar {
margin-top: $main-header-height-sm;
}
}

.layout-navbar-fixed.sidebar-mini.sidebar-collapse &,
.layout-navbar-fixed.sidebar-mini-md.sidebar-collapse &,
.layout-navbar-fixed.sidebar-mini-xs.sidebar-collapse & {
.brand-link {
height: $main-header-height;
width: $sidebar-mini-width;

&.text-sm {
height: $main-header-height-sm;
}
}
}

.layout-navbar-fixed.sidebar-mini.sidebar-collapse.text-sm &,
.layout-navbar-fixed.sidebar-mini-md.sidebar-collapse.text-sm &,
.layout-navbar-fixed.sidebar-mini-xs.sidebar-collapse.text-sm & {
.brand-link {
height: $main-header-height-sm;
}
}

body:not(.layout-fixed).layout-navbar-fixed & {
.main-sidebar {
// margin-top: calc(#{$main-header-height} / -1);

// .sidebar {
// margin-top: $main-header-height;
// }
}
}

body:not(.layout-fixed).layout-navbar-fixed.text-sm & {
.main-sidebar {
margin-top: calc(#{$main-header-height-sm} / -1);

.sidebar {
margin-top: $main-header-height-sm;
}
}
}

.layout-navbar-fixed & {
.control-sidebar {
top: 0;
}

a.anchor {
display: block;
position: relative;
top: calc((#{$main-header-height-inner} + #{$main-header-bottom-border-width} + (#{$main-header-link-padding-y} * 2)) / -1);
}

.main-sidebar:hover {
.brand-link {
transition: width $transition-speed $transition-fn;
width: $sidebar-width;
}
}

.brand-link {
overflow: hidden;
position: fixed;
top: 0;
transition: width $transition-speed $transition-fn;
width: $sidebar-width;
z-index: $zindex-main-header + 1;
}

// Sidebar variants brand-link fix
@each $name, $color in $theme-colors {
.sidebar-dark-#{$name} .brand-link:not([class*="navbar"]) {
background-color: $sidebar-dark-bg;
}

.sidebar-light-#{$name} .brand-link:not([class*="navbar"]) {
background-color: $sidebar-light-bg;
}
}

.content-wrapper {
margin-top: $main-header-height;
}

.main-header.text-sm ~ .content-wrapper {
margin-top: $main-header-height-sm;
}

.main-header {
left: 0;
position: fixed;
right: 0;
top: 0;
z-index: $zindex-main-header - 1;
}
}

.layout-navbar-fixed.text-sm & {
.content-wrapper {
margin-top: $main-header-height-sm;
}
}

.layout-navbar-not-fixed & {
.brand-link {
position: static;
}

.sidebar,
.content-wrapper {
margin-top: 0;
}

.main-header {
position: static;
}
}

.layout-navbar-not-fixed.layout-fixed & {
.sidebar {
margin-top: 0;
}
}

@each $breakpoint in map-keys($grid-breakpoints) {
@include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);

.layout#{$infix}-navbar-fixed.layout-fixed & {
.control-sidebar {
top: $main-header-height;
}

.text-sm & .main-header ~ .control-sidebar,
.main-header.text-sm ~ .control-sidebar {
top: $main-header-height-sm;
}

.sidebar {
margin-top: $main-header-height;
}

.text-sm & .brand-link ~ .sidebar,
.brand-link.text-sm ~ .sidebar {
margin-top: $main-header-height-sm;
}
}

.layout#{$infix}-navbar-fixed.layout-fixed.text-sm & {
.control-sidebar {
top: $main-header-height-sm;
}

.sidebar {
margin-top: $main-header-height-sm;
}
}

.layout#{$infix}-navbar-fixed & {
.control-sidebar {
top: 0;
}

a.anchor {
display: block;
position: relative;
top: calc((#{$main-header-height-inner} + #{$main-header-bottom-border-width} + (#{$main-header-link-padding-y} * 2)) / -1);
}

&.sidebar-collapse {
.brand-link {
height: $main-header-height;
transition: width $transition-speed $transition-fn;
width: $sidebar-mini-width;

.text-sm &,
&.text-sm {
height: $main-header-height-sm;
}
}

.main-sidebar:hover {
.brand-link {
transition: width $transition-speed $transition-fn;
width: $sidebar-width;
}
}
}

.brand-link {
overflow: hidden;
position: fixed;
top: 0;
transition: width $transition-speed $transition-fn;
width: $sidebar-width;
z-index: $zindex-main-header + 1;
}

// Sidebar variants brand-link fix
@each $name, $color in $theme-colors {
.sidebar-dark-#{$name} .brand-link:not([class*="navbar"]) {
background-color: $sidebar-dark-bg;
}

.sidebar-light-#{$name} .brand-link:not([class*="navbar"]) {
background-color: $sidebar-light-bg;
}
}

.content-wrapper {
margin-top: $main-header-height;
}

.text-sm & .main-header ~ .content-wrapper,
.main-header.text-sm ~ .content-wrapper {
margin-top: $main-header-height-sm;
}

.main-header {
left: 0;
position: fixed;
right: 0;
top: 0;
z-index: $zindex-main-sidebar - 1;
}
}

.layout#{$infix}-navbar-fixed.text-sm & {
.content-wrapper {
margin-top: $main-header-height-sm;
}
}

body:not(.layout-fixed).layout#{$infix}-navbar-fixed & {
// .main-sidebar {
// margin-top: calc(#{$main-header-height} / -1);

// .sidebar {
// margin-top: $main-header-height;
// }
// }
}

body:not(.layout-fixed).layout#{$infix}-navbar-fixed.text-sm & {
.main-sidebar {
margin-top: calc(#{$main-header-height-sm} / -1);

.sidebar {
margin-top: $main-header-height-sm;
}
}
}

.layout#{$infix}-navbar-not-fixed & {
.brand-link {
position: static;
}

.sidebar,
.content-wrapper {
margin-top: 0;
}

.main-header {
position: static;
}
}

.layout#{$infix}-navbar-not-fixed.layout-fixed & {
.sidebar {
margin-top: 0;
}
}
}
}

.layout-footer-fixed & {
.control-sidebar {
bottom: 0;
}

.main-footer {
bottom: 0;
left: 0;
position: fixed;
right: 0;
z-index: $zindex-main-footer;
}
}

.layout-footer-not-fixed & {
.main-footer {
position: static;
}

.content-wrapper {
margin-bottom: 0;
}
}

@each $breakpoint in map-keys($grid-breakpoints) {
@include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
.layout#{$infix}-footer-fixed & {
.control-sidebar {
bottom: 0;
}

.main-footer {
bottom: 0;
left: 0;
position: fixed;
right: 0;
z-index: $zindex-main-footer;
}

.content-wrapper {
padding-bottom: $main-footer-height;
}
}

.layout#{$infix}-footer-not-fixed & {
.main-footer {
position: static;
}
}
}
}

.layout-top-nav & {
margin-left: 0;

.main-header {
.brand-image {
margin-top: -.5rem;
margin-right: .2rem;
height: 33px;
}
}

.main-sidebar {
bottom: inherit;
height: inherit;
}

.content-wrapper,
.main-header,
.main-footer {
margin-left: 0;
}
}
}


body.sidebar-collapse:not(.sidebar-mini-xs):not(.sidebar-mini-md):not(.sidebar-mini) {
.content-wrapper,
.main-footer,
.main-header {
&,
&::before {
margin-left: 0;
}
}
}

body:not(.sidebar-mini-md):not(.sidebar-mini-xs):not(.layout-top-nav) {
.content-wrapper,
.main-footer,
.main-header {
@include media-breakpoint-up(md) {
@include transition(margin-left $transition-speed $transition-fn);

margin-left: $sidebar-width;

.sidebar-collapse & {
margin-left: 0;
}
}

@include media-breakpoint-down(md) {
margin-left: 0;
}
}
}

.sidebar-mini-md {
.content-wrapper,
.main-footer,
.main-header {
@include media-breakpoint-up(md) {
@include transition(margin-left $transition-speed $transition-fn);

margin-left: $sidebar-width;

.sidebar-collapse & {
margin-left: $sidebar-mini-width;
}
}
@include media-breakpoint-down(md) {
margin-left: $sidebar-mini-width;
}
@include media-breakpoint-down(sm) {
margin-left: 0;
}
}
}

.sidebar-mini-xs {
.content-wrapper,
.main-footer,
.main-header {
@include media-breakpoint-up(md) {
@include transition(margin-left $transition-speed $transition-fn);

margin-left: $sidebar-width;

.sidebar-collapse & {
margin-left: $sidebar-mini-width;
}
}
@include media-breakpoint-down(md) {
margin-left: $sidebar-mini-width;
}
}
}

.content-wrapper {
background-color: $main-bg;

> .content {
padding: $content-padding-y $content-padding-x;
}
}

.main-sidebar {
&,
&::before {
$local-sidebar-transition: margin-left $transition-speed $transition-fn, width $transition-speed $transition-fn;
@include transition($local-sidebar-transition);
width: $sidebar-width;
}

.sidebar-collapse:not(.sidebar-mini):not(.sidebar-mini-md):not(.sidebar-mini-xs) & {
&,
&::before {
box-shadow: none !important;
}
}

.sidebar-collapse & {
&,
&::before {
margin-left: -$sidebar-width;
}

.nav-sidebar.nav-child-indent .nav-treeview {
padding: 0;
}
}

@include media-breakpoint-down(sm) {
&,
&::before {
box-shadow: none !important;
margin-left: -$sidebar-width;
}

.sidebar-open & {
&,
&::before {
margin-left: 0;
}
}
}
}

body:not(.layout-fixed) {
.main-sidebar {
height: inherit;
min-height: 100%;
position: absolute;
top: 0;

.sidebar {
overflow-y: auto;
}
}
}

.layout-fixed {
.brand-link {
width: $sidebar-width;
}

.main-sidebar {
bottom: 0;
float: none;
left: 0;
position: fixed;
top: 0;
}

.control-sidebar {
bottom: 0;
float: none;
position: fixed;
top: 0;

.control-sidebar-content {
height: calc(100vh - #{$main-header-height});
overflow-y: auto;
@include scrollbar-width-thin();
}
}
}

@supports (-webkit-touch-callout: none) {
.layout-fixed {
.main-sidebar {
height: inherit;
}
}
}

.main-footer {
background-color: $main-footer-bg;
border-top: $main-footer-border-top;
color: lighten($gray-700, 25%);
padding: $main-footer-padding;

.text-sm &,
&.text-sm {
padding: $main-footer-padding-sm;
}
}

.content-header {
padding: 15px $content-padding-x;

.text-sm & {
padding: 10px $content-padding-x;
}

h1 {
font-size: 1.8rem;
margin: 0;

.text-sm & {
font-size: 1.5rem;
}
}

.breadcrumb {
background-color: transparent;
line-height: 1.8rem;
margin-bottom: 0;
padding: 0;

.text-sm & {
line-height: 1.5rem;
}
}
}


.hold-transition {
.content-wrapper,
.main-header,
.main-sidebar,
.main-sidebar *,
.control-sidebar,
.control-sidebar *,
.main-footer {
transition: none !important;
animation-duration: 0s !important;
}
}

.dark-mode {
background-color: $dark-main-bg;
color: $white;

.wrapper {
.layout-navbar-fixed & {
@each $name, $color in $theme-colors-alt {
.sidebar-dark-#{$name} .brand-link:not([class*="navbar"]) {
background-color: $sidebar-dark-bg;
}

.sidebar-light-#{$name} .brand-link:not([class*="navbar"]) {
background-color: $sidebar-light-bg;
}
}
}

@each $breakpoint in map-keys($grid-breakpoints) {
@include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);

.layout#{$infix}-navbar-fixed & {
@each $name, $color in $theme-colors-alt {
.sidebar-dark-#{$name} .brand-link:not([class*="navbar"]) {
background-color: $sidebar-dark-bg;
}

.sidebar-light-#{$name} .brand-link:not([class*="navbar"]) {
background-color: $sidebar-light-bg;
}
}
}
}
}
}

.breadcrumb-item {
&.active,
+ .breadcrumb-item::before {
color: $gray-500;
}
}
.main-footer {
background-color: $dark;
border-color: lighten($dark, 10%);
}
.content-wrapper {
background-color: lighten($dark, 7.5%);
color: $white;

.content-header {
color: $white;
}
}
}

+ 179
- 0
MVCTemplate/wwwroot/build/scss/_main-header.scss Zobrazit soubor

@@ -0,0 +1,179 @@
//
// Component: Main Header
//

.main-header {
border-bottom: $main-header-bottom-border;
z-index: $zindex-main-header;

.nav-link {
height: $nav-link-height;
position: relative;
}

.text-sm &,
&.text-sm {
.nav-link {
height: $nav-link-sm-height;
padding: $nav-link-sm-padding-y $nav-link-padding-x;

> .fa,
> .fas,
> .far,
> .fab,
> .fal,
> .fad,
> .svg-inline--fa,
> .ion {
font-size: $font-size-sm;
}
}

}

.navbar-nav {
.nav-item {
margin: 0;
}

&[class*="-right"] {
.dropdown-menu {
left: auto;
margin-top: -3px;
right: 0;

@media (max-width: breakpoint-max(xs)) {
left: 0;
right: auto;
}
}
}
}

&.dropdown-legacy .dropdown-menu {
top: $nav-link-height + $navbar-padding-y;
margin-top: 0;
}
}

// Add this class to images within a nav-link
.navbar-img {
height: $main-header-height / 2;
width: auto;
}

// Navbar badge
.navbar-badge {
font-size: .6rem;
font-weight: 300;
padding: 2px 4px;
position: absolute;
right: 5px;
top: 9px;
}

.btn-navbar {
background-color: transparent;
border-left-width: 0;
}

.form-control-navbar {
border-right-width: 0;

+ .input-group-append {
margin-left: 0;
}
}

.form-control-navbar,
.btn-navbar {
transition: none;
}

.navbar-dark {
.form-control-navbar,
.btn-navbar {
background-color: $main-header-dark-form-control-bg;
border-color: $main-header-dark-form-control-border-color;
}

.form-control-navbar {
&::placeholder {
color: $main-header-dark-placeholder-color;
}

+ .input-group-append > .btn-navbar {
color: $main-header-dark-placeholder-color;
}

&:focus {
&,
+ .input-group-append .btn-navbar {
background-color: $main-header-dark-form-control-focused-bg;
border-color: $main-header-dark-form-control-focused-border-color !important;
color: $main-header-dark-form-control-focused-color;
}
}
}
}

.navbar-light {
.form-control-navbar,
.btn-navbar {
background-color: $main-header-light-form-control-bg;
border-color: $main-header-light-form-control-border-color;
}

.form-control-navbar {
&::placeholder {
color: $main-header-light-placeholder-color;
}

+ .input-group-append > .btn-navbar {
color: $main-header-light-placeholder-color;
}

&:focus {
&,
+ .input-group-append .btn-navbar {
background-color: $main-header-light-form-control-focused-bg;
border-color: $main-header-light-form-control-focused-border-color !important;
color: $main-header-light-form-control-focused-color;
}
}
}

.navbar-search-block {
.form-control-navbar {
&:focus {
&,
+ .input-group-append .btn-navbar {
color: $main-header-light-placeholder-color;
}
}
}
}
}

// Navbar Search
.navbar-search-block {
position: absolute;
padding: 0 $nav-link-padding-x;
left: 0;
top: 0;
right: 0;
bottom: 0;
z-index: 10;
display: none;
justify-content: center;
flex-direction: column;
background-color: initial;

&.navbar-search-open {
display: flex;
}

.input-group {
width: 100%;
}
}

+ 1176
- 0
MVCTemplate/wwwroot/build/scss/_main-sidebar.scss
Diff nebyl zobrazen, protože je příliš veliký
Zobrazit soubor


+ 541
- 0
MVCTemplate/wwwroot/build/scss/_miscellaneous.scss Zobrazit soubor

@@ -0,0 +1,541 @@
//
// Misc: Miscellaneous
//

.border-transparent {
border-color: transparent !important;
}

// Description Blocks
.description-block {
display: block;
margin: 10px 0;
text-align: center;

&.margin-bottom {
margin-bottom: 25px;
}

> .description-header {
font-size: 16px;
font-weight: 600;
margin: 0;
padding: 0;
}

> .description-text {
text-transform: uppercase;
}

// Description Block Extension
.description-icon {
font-size: 16px;
}
}

// List utility classes
.list-group-unbordered {
> .list-group-item {
border-left: 0;
border-radius: 0;
border-right: 0;
padding-left: 0;
padding-right: 0;
}
}

.list-header {
color: $gray-600;
font-size: 15px;
font-weight: 700;
padding: 10px 4px;
}

.list-seperator {
background-color: $card-border-color;
height: 1px;
margin: 15px 0 9px;
}

.list-link {
> a {
color: $gray-600;
padding: 4px;

&:hover {
color: $gray-900;
}
}
}

// User block
.user-block {
float: left;

img {
float: left;
height: 40px;
width: 40px;
}

.username,
.description,
.comment {
display: block;
margin-left: 50px;
}

.username {
font-size: 16px;
font-weight: 600;
margin-top: -1px;
}

.description {
color: $gray-600;
font-size: 13px;
margin-top: -3px;
}

&.user-block-sm {
img {
width: $img-size-sm;
height: $img-size-sm;
}

.username,
.description,
.comment {
margin-left: 40px;
}

.username {
font-size: 14px;
}
}
}

// Image sizes
.img-sm,
.img-md,
.img-lg {
float: left;
}

.img-sm {
height: $img-size-sm;
width: $img-size-sm;

+ .img-push {
margin-left: $img-size-sm + $img-size-push;
}
}

.img-md {
width: $img-size-md;
height: $img-size-md;

+ .img-push {
margin-left: $img-size-md + $img-size-push;
}
}

.img-lg {
width: $img-size-lg;
height: $img-size-lg;

+ .img-push {
margin-left: $img-size-lg + $img-size-push;
}
}

// Image bordered
.img-bordered {
border: 3px solid $gray-500;
padding: 3px;
}

.img-bordered-sm {
border: 2px solid $gray-500;
padding: 2px;
}

// Rounded and Circle Images
.img-rounded {
@include border-radius($border-radius);
}

.img-circle {
@include border-radius(50%);
}

// Image sizes
.img-size-64,
.img-size-50,
.img-size-32 {
height: auto;
}

.img-size-64 {
width: 64px;
}

.img-size-50 {
width: 50px;
}

.img-size-32 {
width: 32px;
}

// Block sizes
.size-32,
.size-40,
.size-50 {
display: block;
text-align: center;
}

.size-32 {
height: 32px;
line-height: 32px;
width: 32px;
}

.size-40 {
height: 40px;
line-height: 40px;
width: 40px;
}

.size-50 {
height: 50px;
line-height: 50px;
width: 50px;
}

// General attachemnt block
.attachment-block {
background-color: $gray-100;
border: 1px solid $card-border-color;
margin-bottom: 10px;
padding: 5px;

.attachment-img {
float: left;
height: auto;
max-height: 100px;
max-width: 100px;
}

.attachment-pushed {
margin-left: 110px;
}

.attachment-heading {
margin: 0;
}

.attachment-text {
color: $gray-700;
}
}

// Overlays for Card, InfoBox & SmallBox
.card,
.overlay-wrapper,
.info-box,
.small-box {
// Box overlay for LOADING STATE effect
> .overlay,
> .loading-img {
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}

.overlay {
@include border-radius($border-radius);
align-items: center;
background-color: rgba($white, .7);
display: flex;
justify-content: center;
z-index: 50;

> .fa,
> .fas,
> .far,
> .fab,
> .fal,
> .fad,
> .svg-inline--fa,
> .ion {
color: $gray-800;
}

&.dark {
background-color: rgba($black, .5);

> .fa,
> .fas,
> .far,
> .fab,
> .fal,
> .fad,
> .svg-inline--fa,
> .ion {
color: $gray-400;
}
}
}
}

.tab-pane {
// Box overlay for LOADING STATE effect on Tab Panels
> .overlay-wrapper {
position: relative;
> .overlay {
border-top-left-radius: 0;
border-top-right-radius: 0;
flex-direction: column;
margin-top: -$card-spacer-x;
margin-left: -$card-spacer-x;
height: calc(100% + 2 * #{$card-spacer-x});
width: calc(100% + 2 * #{$card-spacer-x});

&.dark {
color: $white;
}
}
}
}

// Ribbon
.ribbon-wrapper {
height: $ribbon-wrapper-size;
overflow: hidden;
position: absolute;
right: -2px;
top: -2px;
width: $ribbon-wrapper-size;
z-index: 10;

&.ribbon-lg {
height: $ribbon-lg-wrapper-size;
width: $ribbon-lg-wrapper-size;

.ribbon {
right: $ribbon-lg-right;
top: $ribbon-lg-top;
width: $ribbon-lg-width;
}
}

&.ribbon-xl {
height: $ribbon-xl-wrapper-size;
width: $ribbon-xl-wrapper-size;

.ribbon {
right: $ribbon-xl-right;
top: $ribbon-xl-top;
width: $ribbon-xl-width;
}
}

.ribbon {
box-shadow: 0 0 $ribbon-border-size rgba($black, .3);
font-size: $ribbon-font-size;
line-height: $ribbon-line-height;
padding: $ribbon-padding;
position: relative;
right: $ribbon-right;
text-align: center;
text-shadow: 0 -1px 0 rgba($black, .4);
text-transform: uppercase;
top: $ribbon-top;
transform: rotate(45deg);
width: $ribbon-width;

&::before,
&::after {
border-left: $ribbon-border-size solid transparent;
border-right: $ribbon-border-size solid transparent;
border-top: $ribbon-border-size solid #9e9e9e;
bottom: -$ribbon-border-size;
content: "";
position: absolute;
}

&::before {
left: 0;
}

&::after {
right: 0;
}
}
}

// Scroll To Top
.back-to-top {
bottom: 1.25rem;
position: fixed;
right: 1.25rem;
z-index: $zindex-control-sidebar + 1;

&:focus {
box-shadow: none;
}
}

// Pre
pre {
padding: .75rem;
}

// Blockquotes styles
blockquote {
background-color: $white;
border-left: .7rem solid $primary;
margin: 1.5em .7rem;
padding: .5em .7rem;

.box & {
background-color: $gray-200;
}

p:last-child {
margin-bottom: 0;
}

h1,
h2,
h3,
h4,
h5,
h6 {
color: $primary;
font-size: 1.25rem;
font-weight: 600;
}

@each $color, $value in $theme-colors {
&.quote-#{$color} {
border-color: $value;

h1,
h2,
h3,
h4,
h5,
h6 {
color: $value;
}
}
}

@each $color, $value in $colors {
&.quote-#{$color} {
border-color: $value;

h1,
h2,
h3,
h4,
h5,
h6 {
color: $value;
}
}
}
}


// Tab Custom Content

.tab-custom-content {
border-top: $nav-tabs-border-width solid $nav-tabs-border-color;
margin-top: .5rem;
padding-top: .5rem;
}

.nav + .tab-custom-content {
border-top: none;
border-bottom: $nav-tabs-border-width solid $nav-tabs-border-color;
margin-top: 0;
margin-bottom: .5rem;
padding-bottom: .5rem;
}


// Badge BTN Style
.badge-btn {
border-radius: $button-border-radius-xs;
font-size: $button-font-size-xs;
font-weight: 400;
padding: $button-padding-y-xs * 2 $button-padding-x-xs * 2;
}

.badge-btn.badge-pill {
padding: .375rem .6rem;
}

.dark-mode {
a:not(.btn):hover {
color: lighten($link-color, 10%);
}
.attachment-block {
background-color: lighten($dark, 3.75%);

.attachment-text {
color: $gray-400;
}
}
blockquote {
background-color: lighten($dark, 5%);

@each $color, $value in $theme-colors {
&.quote-#{$color} {
border-color: $value;

h1,
h2,
h3,
h4,
h5,
h6 {
color: $value;
}
}
}

@each $color, $value in $colors {
&.quote-#{$color} {
border-color: $value;

h1,
h2,
h3,
h4,
h5,
h6 {
color: $value;
}
}
}
}
.close,
.mailbox-attachment-close {
color: $gray-500;
text-shadow: 0 1px 0 $gray-700;
}
.tab-custom-content {
border-color: $gray-600;
}
.list-group-item {
background-color: $dark;
border-color: $gray-600;
}
}

+ 15
- 0
MVCTemplate/wwwroot/build/scss/_mixins.scss Zobrazit soubor

@@ -0,0 +1,15 @@
//
// General: Mixins
//

@import "mixins/animations";
@import "mixins/cards";
@import "mixins/sidebar";
@import "mixins/navbar";
@import "mixins/accent";
@import "mixins/custom-forms";
@import "mixins/backgrounds";
@import "mixins/direct-chat";
@import "mixins/toasts";
@import "mixins/touch-support";
@import "mixins/miscellaneous";

+ 76
- 0
MVCTemplate/wwwroot/build/scss/_modals.scss Zobrazit soubor

@@ -0,0 +1,76 @@
//
// Component: Modals
//

// Overlay
.modal-dialog {
.overlay {
display: flex;
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
margin: -$modal-content-border-width;
z-index: ($zindex-modal + 2);
justify-content: center;
align-items: center;
background-color: rgba($black, .7);
color: darken($gray-600, 2.5%);
@include border-radius($modal-content-border-radius);
}
}


// BG Color Variations Fixes
.modal-content {
&.bg-warning {
.modal-header,
.modal-footer {
border-color: $gray-800;
}
}

&.bg-primary,
&.bg-secondary,
&.bg-info,
&.bg-danger,
&.bg-success, {
.close {
color: $white;
text-shadow: 0 1px 0 $black;
}
}
}

.dark-mode {
.modal-header,
.modal-footer {
border-color: $gray-600;
}
.modal-content {
background-color: $dark;

&.bg-warning {
.modal-header,
.modal-footer {
border-color: $gray-600;
}
.close {
color: $dark !important;
text-shadow: 0 1px 0 $gray-700 !important;
}
}

&.bg-primary,
&.bg-secondary,
&.bg-info,
&.bg-danger,
&.bg-success {
.modal-header,
.modal-footer {
border-color: $white;
}
}
}
}

+ 168
- 0
MVCTemplate/wwwroot/build/scss/_navs.scss Zobrazit soubor

@@ -0,0 +1,168 @@
//
// Component: Nav
//

.nav-pills {
.nav-link {
color: $gray-600;

&:not(.active):hover {
color: theme-color("primary");
}
}

.nav-item {
&.dropdown.show {
.nav-link:hover {
color: $dropdown-link-active-color;
}
}
}
}

// Vertical Tabs
.nav-tabs.flex-column {
border-bottom: 0;
border-right: $nav-tabs-border-width solid $nav-tabs-border-color;

.nav-link {
border-bottom-left-radius: $nav-tabs-border-radius;
border-top-right-radius: 0;
margin-right: -$nav-tabs-border-width;

@include hover-focus () {
border-color: $gray-200 transparent $gray-200 $gray-200;
}
}

.nav-link.active,
.nav-item.show .nav-link {
border-color: $gray-300 transparent $gray-300 $gray-300;
}

&.nav-tabs-right {
border-left: $nav-tabs-border-width solid $nav-tabs-border-color;
border-right: 0;

.nav-link {
border-bottom-left-radius: 0;
border-bottom-right-radius: $nav-tabs-border-radius;
border-top-left-radius: 0;
border-top-right-radius: $nav-tabs-border-radius;
margin-left: -$nav-tabs-border-width;

@include hover-focus () {
border-color: $gray-200 $gray-200 $gray-200 transparent;
}
}

.nav-link.active,
.nav-item.show .nav-link {
border-color: $gray-300 $gray-300 $gray-300 transparent;
}
}
}

.navbar-no-expand {
flex-direction: row;

.nav-link {
padding-left: $navbar-nav-link-padding-x;
padding-right: $navbar-nav-link-padding-x;
}

.dropdown-menu {
position: absolute;
}
}

// Color variants
@each $color, $value in $theme-colors {
@if $color == dark or $color == light {
.navbar-#{$color} {
background-color: $value;
@if $color == dark {
border-color: lighten($dark, 10%);
}
}
}
}

@each $color, $value in $theme-colors {
@if $color != dark and $color != light {
@include navbar-variant($color, $value);
}
}

@each $color, $value in $colors {
@include navbar-variant($color, $value);
}

.dark-mode {
.nav-pills .nav-link {
color: $gray-400;
}

.nav-tabs {
border-color: lighten($dark, 15%);

.nav-link:focus,
.nav-link:hover {
border-color: lighten($dark, 15%);
}

.nav-item.show .nav-link,
.nav-link.active {
background-color: $dark;
border-color: lighten($dark, 15%) lighten($dark, 15%) transparent lighten($dark, 15%);
color: $white;
}

&.flex-column {
.nav-item.show .nav-link,
.nav-link {
&.active,
&:focus,
&:hover {
border-color: lighten($dark, 15%) transparent lighten($dark, 15%) lighten($dark, 15%);
}
&:focus,
&:hover {
background-color: lighten($dark, 5%);
}
}
&.nav-tabs-right {
border-color: lighten($dark, 15%);
.nav-link {
&.active,
&:focus,
&:hover {
border-color: lighten($dark, 15%) lighten($dark, 15%) lighten($dark, 15%) transparent;
}
}
}
}
}

// Color variants
@each $color, $value in $theme-colors-alt {
@if $color == dark or $color == light {
.navbar-#{$color} {
background-color: $value;
@if $color == dark {
border-color: lighten($dark, 10%);
}
}
}
}

@each $color, $value in $theme-colors-alt {
@if $color != dark and $color != light {
@include navbar-variant($color, $value);
}
}

@each $color, $value in $colors-alt {
@include navbar-variant($color, $value);
}
}

+ 82
- 0
MVCTemplate/wwwroot/build/scss/_pagination.scss Zobrazit soubor

@@ -0,0 +1,82 @@
//
// Component: Pagination
//

.pagination-month {
.page-item {
justify-self: stretch;

.page-link {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
box-shadow: none;
}
&:first-child,
&:last-child {
.page-link {
height: 100%;
font-size: $font-size-lg;
}
}
.page-month {
margin-bottom: 0;
font-size: $font-size-lg;
font-weight: $font-weight-bold;
}
.page-year {
margin-bottom: 0;
}
}

&.pagination-lg {
.page-month {
font-size: ($font-size-lg * 1.25);
}
}
&.pagination-sm {
.page-month {
font-size: ($font-size-base);
}
}
}

.dark-mode {
.page-item {
&.disabled a,
&.disabled .page-link {
background-color: lighten($dark, 2.5%) !important;
border-color: $gray-600 !important;
color: $gray-600;
}

.page-link {
color: $primary-alt;
}

&.active {
.page-link {
background-color: $primary-alt;
color: $white;

&:hover,
&:focus {
color: $gray-400 !important;
}
}
}
&:not(.active) {
.page-link {
background-color: $dark;
border-color: $gray-600;

&:hover,
&:focus {
color: lighten($primary-alt, 5%);
background-color: lighten($dark, 5%);
}
}
}
}
}

+ 24
- 0
MVCTemplate/wwwroot/build/scss/_preloader.scss Zobrazit soubor

@@ -0,0 +1,24 @@
//
// Core: Preloader
//

.preloader {
display: flex;
background-color: $main-bg;
height: 100vh;
width: 100%;
transition: height 200ms linear;
position: fixed;
left: 0;
top: 0;
z-index: $zindex-preloader;
}

.dark-mode {
.preloader {
background-color: $dark-main-bg;
color: $white;
}
}

//

+ 52
- 0
MVCTemplate/wwwroot/build/scss/_print.scss Zobrazit soubor

@@ -0,0 +1,52 @@
//
// Misc: Print
//

@media print {
//Add to elements that you do not want to show when printing
.no-print {
display: none !important;
}

//Elements that we want to hide when printing
.main-sidebar,
.main-header,
.content-header {
@extend .no-print;
}

//This is the only element that should appear, so let's remove the margins
.content-wrapper,
.main-footer {
@include translate(0, 0);
margin-left: 0 !important;
min-height: 0 !important;
}

.layout-fixed .content-wrapper {
padding-top: 0 !important;
}

//Invoice printing
.invoice {
border: 0;
margin: 0;
padding: 0;
width: 100%;
}

.invoice-col {
float: left;
width: 33.3333333%;
}

//Make sure table content displays properly
.table-responsive {
overflow: auto;

> .table tr th,
> .table tr td {
white-space: normal !important;
}
}
}

+ 68
- 0
MVCTemplate/wwwroot/build/scss/_products.scss Zobrazit soubor

@@ -0,0 +1,68 @@
//
// Component: Products
//

.products-list {
list-style: none;
margin: 0;
padding: 0;

> .item {
@include clearfix ();

@if $enable-rounded {
@include border-radius($border-radius);
}

background-color: $white;
padding: 10px 0;

}

.product-img {
float: left;

img {
height: 50px;
width: 50px;
}
}

.product-info {
margin-left: 60px;
}

.product-title {
font-weight: 600;
}

.product-description {
color: $gray-600;
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}

.product-list-in-card > .item {
@include border-radius(0);
border-bottom: 1px solid $card-border-color;

&:last-of-type {
border-bottom-width: 0;
}
}


.dark-mode {
.products-list > .item {
background-color: $dark;
color: $white;
border-bottom-color: $gray-600;
}

.product-description {
color: $gray-400;
}
}

+ 72
- 0
MVCTemplate/wwwroot/build/scss/_progress-bars.scss Zobrazit soubor

@@ -0,0 +1,72 @@
//
// Component: Progress Bar
//

//General CSS
.progress {
@include box-shadow(none);
@include border-radius($progress-bar-border-radius);

// Vertical bars
&.vertical {
display: inline-block;
height: 200px;
margin-right: 10px;
position: relative;
width: 30px;

> .progress-bar {
bottom: 0;
position: absolute;
width: 100%;
}

//Sizes
&.sm,
&.progress-sm {
width: 20px;
}

&.xs,
&.progress-xs {
width: 10px;
}

&.xxs,
&.progress-xxs {
width: 3px;
}
}
}

.progress-group {
margin-bottom: map-get($spacers, 2);
}

// size variation
.progress-sm {
height: 10px;
}

.progress-xs {
height: 7px;
}

.progress-xxs {
height: 3px;
}

// Remove margins from progress bars when put in a table
.table {
tr > td {
.progress {
margin: 0;
}
}
}

.dark-mode {
.progress {
background: lighten($dark, 7.5%);
}
}

+ 0
- 0
MVCTemplate/wwwroot/build/scss/_root.scss Zobrazit soubor


Některé soubory nejsou zobrazny, neboť je v této revizi změněno mnoho souborů

Načítá se…
Zrušit
Uložit