Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3c22289cf | ||
|
|
d9b58b0502 | ||
|
|
6a1dc75b3b | ||
|
|
57b35ae431 | ||
|
|
4e25c0179e | ||
|
|
0a0f1ea10a | ||
|
|
2d1982d010 | ||
|
|
65d5e4b46a | ||
|
|
329f4a2acb | ||
|
|
8b6149595a | ||
|
|
41c5b18f6f | ||
|
|
8728d7caf0 | ||
|
|
d307c04e7f | ||
|
|
209460b582 |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.vs/
|
||||||
@@ -4,9 +4,10 @@ stages: # Define the stages of the pipeline.
|
|||||||
#- test
|
#- test
|
||||||
- release
|
- release
|
||||||
|
|
||||||
install-job: # This job runs in the build stage, which runs first.
|
web-build: # This job runs in the build stage, which runs first.
|
||||||
stage: build
|
stage: build
|
||||||
image: node:24
|
image: node:24
|
||||||
|
parallel: 2
|
||||||
script:
|
script:
|
||||||
- cd Web
|
- cd Web
|
||||||
- npm install
|
- npm install
|
||||||
@@ -15,11 +16,27 @@ install-job: # This job runs in the build stage, which runs first.
|
|||||||
paths:
|
paths:
|
||||||
- Web/dist/Web/browser # The 'dist' directory will be available in the next stage.
|
- Web/dist/Web/browser # The 'dist' directory will be available in the next stage.
|
||||||
|
|
||||||
|
api-build:
|
||||||
|
stage: build
|
||||||
|
image: mcr.microsoft.com/dotnet/sdk:8.0
|
||||||
|
parallel: 2
|
||||||
|
script:
|
||||||
|
- cd Api
|
||||||
|
- dotnet publish Api.csproj --output ./build --runtime linux-x64 --configuration Release --self-contained true
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- Api/build
|
||||||
|
when: on_success
|
||||||
|
access: all
|
||||||
|
expire_in: 30 days
|
||||||
|
|
||||||
semantic-release:
|
semantic-release:
|
||||||
image: node:24
|
image: node:24
|
||||||
stage: release
|
stage: release
|
||||||
script:
|
script:
|
||||||
- echo $GL_TOKEN
|
- apt update && apt install zip -y
|
||||||
|
- zip -r dist.zip Web/dist/Web/browser
|
||||||
|
- zip -r api.zip Api/build
|
||||||
- npm install --save-dev @semantic-release/gitlab
|
- npm install --save-dev @semantic-release/gitlab
|
||||||
- npx semantic-release --debug
|
- npx semantic-release --debug
|
||||||
only:
|
only:
|
||||||
@@ -32,4 +49,7 @@ deploy-job: # This job runs in the deploy stage.
|
|||||||
- deployment
|
- deployment
|
||||||
script:
|
script:
|
||||||
- cp -ir Web/dist/Web/browser/* /var/www/html
|
- cp -ir Web/dist/Web/browser/* /var/www/html
|
||||||
|
- systemctl stop api.service
|
||||||
|
- cp -ir Api/build/* /var/api
|
||||||
|
- systemctl start api.service
|
||||||
- echo "Application successfully deployed."
|
- echo "Application successfully deployed."
|
||||||
|
|||||||
@@ -11,7 +11,8 @@
|
|||||||
"@semantic-release/gitlab"
|
"@semantic-release/gitlab"
|
||||||
],
|
],
|
||||||
"assets": [
|
"assets": [
|
||||||
{ "path": "Web/dist/Web/browser/*", "label": "bundle" },
|
{ "path": "dist.zip", "label": "Web.zip" },
|
||||||
|
{ "path": "api.zip", "label": "Api.zip" },
|
||||||
{ "url": "https://gitlab.lesko.me/marek/centrum/-/blob/main/README.md", "label": "README.md" }
|
{ "url": "https://gitlab.lesko.me/marek/centrum/-/blob/main/README.md", "label": "README.md" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
5
Api/.config/dotnet-tools.json
Normal file
5
Api/.config/dotnet-tools.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"isRoot": true,
|
||||||
|
"tools": {}
|
||||||
|
}
|
||||||
30
Api/.dockerignore
Normal file
30
Api/.dockerignore
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
**/.classpath
|
||||||
|
**/.dockerignore
|
||||||
|
**/.env
|
||||||
|
**/.git
|
||||||
|
**/.gitignore
|
||||||
|
**/.project
|
||||||
|
**/.settings
|
||||||
|
**/.toolstarget
|
||||||
|
**/.vs
|
||||||
|
**/.vscode
|
||||||
|
**/*.*proj.user
|
||||||
|
**/*.dbmdl
|
||||||
|
**/*.jfm
|
||||||
|
**/azds.yaml
|
||||||
|
**/bin
|
||||||
|
**/charts
|
||||||
|
**/docker-compose*
|
||||||
|
**/Dockerfile*
|
||||||
|
**/node_modules
|
||||||
|
**/npm-debug.log
|
||||||
|
**/obj
|
||||||
|
**/secrets.dev.yaml
|
||||||
|
**/values.dev.yaml
|
||||||
|
LICENSE
|
||||||
|
README.md
|
||||||
|
!**/.gitignore
|
||||||
|
!.git/HEAD
|
||||||
|
!.git/config
|
||||||
|
!.git/packed-refs
|
||||||
|
!.git/refs/heads/**
|
||||||
4
Api/.gitignore
vendored
Normal file
4
Api/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
obj/
|
||||||
|
bin/
|
||||||
|
.vs/
|
||||||
|
build/
|
||||||
21
Api/Api.csproj
Normal file
21
Api/Api.csproj
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<UserSecretsId>aspnet-Api-50db7f4c-1c75-467a-a923-a5477d7decc4</UserSecretsId>
|
||||||
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
|
<DockerfileContext>.</DockerfileContext>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.18" NoWarn="NU1605" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.18" NoWarn="NU1605" />
|
||||||
|
<PackageReference Include="Microsoft.Identity.Web" Version="3.10.0" />
|
||||||
|
<PackageReference Include="Microsoft.Identity.Web.DownstreamApi" Version="3.10.0" />
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.22.1" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
9
Api/Api.csproj.user
Normal file
9
Api/Api.csproj.user
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ActiveDebugProfile>https</ActiveDebugProfile>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
6
Api/Api.http
Normal file
6
Api/Api.http
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
@Api_HostAddress = http://localhost:5012
|
||||||
|
|
||||||
|
GET {{Api_HostAddress}}/weatherforecast/
|
||||||
|
Accept: application/json
|
||||||
|
|
||||||
|
###
|
||||||
31
Api/Api.sln
Normal file
31
Api/Api.sln
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.14.36301.6
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Api", "Api.csproj", "{EC86C676-06E8-4011-A4E3-5118543F4728}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "..\Tests\Tests.csproj", "{819F3EDC-F488-4C63-89D0-4BE09CD0C485}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{EC86C676-06E8-4011-A4E3-5118543F4728}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{EC86C676-06E8-4011-A4E3-5118543F4728}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{EC86C676-06E8-4011-A4E3-5118543F4728}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{EC86C676-06E8-4011-A4E3-5118543F4728}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{819F3EDC-F488-4C63-89D0-4BE09CD0C485}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{819F3EDC-F488-4C63-89D0-4BE09CD0C485}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{819F3EDC-F488-4C63-89D0-4BE09CD0C485}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{819F3EDC-F488-4C63-89D0-4BE09CD0C485}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {A7800B0A-84E4-432A-9E11-6EF3987291FC}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
37
Api/Controllers/WeatherForecastController.cs
Normal file
37
Api/Controllers/WeatherForecastController.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Identity.Web.Resource;
|
||||||
|
|
||||||
|
namespace Api.Controllers
|
||||||
|
{
|
||||||
|
//[Authorize]
|
||||||
|
[ApiController]
|
||||||
|
[Route("[controller]")]
|
||||||
|
//[RequiredScope(RequiredScopesConfigurationKey = "AzureAd:Scopes")]
|
||||||
|
public class WeatherForecastController : ControllerBase
|
||||||
|
{
|
||||||
|
private static readonly string[] Summaries = new[]
|
||||||
|
{
|
||||||
|
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly ILogger<WeatherForecastController> _logger;
|
||||||
|
|
||||||
|
public WeatherForecastController(ILogger<WeatherForecastController> logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet(Name = "GetWeatherForecast")]
|
||||||
|
public IEnumerable<WeatherForecast> Get()
|
||||||
|
{
|
||||||
|
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
||||||
|
{
|
||||||
|
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
|
||||||
|
TemperatureC = Random.Shared.Next(-20, 55),
|
||||||
|
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
|
||||||
|
})
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
30
Api/Dockerfile
Normal file
30
Api/Dockerfile
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
|
||||||
|
|
||||||
|
# This stage is used when running from VS in fast mode (Default for Debug configuration)
|
||||||
|
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
|
||||||
|
USER $APP_UID
|
||||||
|
WORKDIR /app
|
||||||
|
EXPOSE 8080
|
||||||
|
EXPOSE 8081
|
||||||
|
|
||||||
|
|
||||||
|
# This stage is used to build the service project
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
||||||
|
ARG BUILD_CONFIGURATION=Release
|
||||||
|
WORKDIR /src
|
||||||
|
COPY ["Api.csproj", "."]
|
||||||
|
RUN dotnet restore "./Api.csproj"
|
||||||
|
COPY . .
|
||||||
|
WORKDIR "/src/."
|
||||||
|
RUN dotnet build "./Api.csproj" -c $BUILD_CONFIGURATION -o /app/build
|
||||||
|
|
||||||
|
# This stage is used to publish the service project to be copied to the final stage
|
||||||
|
FROM build AS publish
|
||||||
|
ARG BUILD_CONFIGURATION=Release
|
||||||
|
RUN dotnet publish "./Api.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
|
||||||
|
|
||||||
|
# This stage is used in production or when running from VS in regular mode (Default when not using the Debug configuration)
|
||||||
|
FROM base AS final
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=publish /app/publish .
|
||||||
|
ENTRYPOINT ["dotnet", "Api.dll"]
|
||||||
45
Api/Program.cs
Normal file
45
Api/Program.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
|
using Microsoft.Identity.Abstractions;
|
||||||
|
using Microsoft.Identity.Web;
|
||||||
|
using Microsoft.Identity.Web.Resource;
|
||||||
|
|
||||||
|
namespace Api
|
||||||
|
{
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
// Add services to the container.
|
||||||
|
//builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||||
|
// .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
|
||||||
|
|
||||||
|
builder.Services.AddControllers();
|
||||||
|
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||||
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
builder.Services.AddSwaggerGen();
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
// Configure the HTTP request pipeline.
|
||||||
|
// if (app.Environment.IsDevelopment())
|
||||||
|
// {
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI();
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (!app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseHttpsRedirection();
|
||||||
|
}
|
||||||
|
|
||||||
|
// app.UseAuthorization();
|
||||||
|
|
||||||
|
app.MapControllers();
|
||||||
|
|
||||||
|
app.Run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
42
Api/Properties/launchSettings.json
Normal file
42
Api/Properties/launchSettings.json
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"https": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
},
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"applicationUrl": "https://localhost:7145;http://localhost:5012"
|
||||||
|
},
|
||||||
|
"IIS Express": {
|
||||||
|
"commandName": "IISExpress",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Container (Dockerfile)": {
|
||||||
|
"commandName": "Docker",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_HTTPS_PORTS": "8081",
|
||||||
|
"ASPNETCORE_HTTP_PORTS": "8080"
|
||||||
|
},
|
||||||
|
"publishAllPorts": true,
|
||||||
|
"useSSL": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:60760",
|
||||||
|
"sslPort": 44315
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
Api/WeatherForecast.cs
Normal file
13
Api/WeatherForecast.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace Api
|
||||||
|
{
|
||||||
|
public class WeatherForecast
|
||||||
|
{
|
||||||
|
public DateOnly Date { get; set; }
|
||||||
|
|
||||||
|
public int TemperatureC { get; set; }
|
||||||
|
|
||||||
|
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||||
|
|
||||||
|
public string? Summary { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
8
Api/appsettings.Development.json
Normal file
8
Api/appsettings.Development.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
Api/appsettings.json
Normal file
23
Api/appsettings.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
/*
|
||||||
|
The following identity settings need to be configured
|
||||||
|
before the project can be successfully executed.
|
||||||
|
For more info see https://aka.ms/dotnet-template-ms-identity-platform
|
||||||
|
*/
|
||||||
|
"AzureAd": {
|
||||||
|
"Instance": "https://login.microsoftonline.com/",
|
||||||
|
"Domain": "qualified.domain.name",
|
||||||
|
"TenantId": "22222222-2222-2222-2222-222222222222",
|
||||||
|
"ClientId": "11111111-1111-1111-11111111111111111",
|
||||||
|
|
||||||
|
"Scopes": "access_as_user",
|
||||||
|
"CallbackPath": "/signin-oidc"
|
||||||
|
},
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
||||||
2
Tests/.gitignore
vendored
Normal file
2
Tests/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
obj/
|
||||||
|
bin/
|
||||||
38
Tests/IntegrationTest1.cs
Normal file
38
Tests/IntegrationTest1.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
namespace Tests.Tests
|
||||||
|
{
|
||||||
|
public class IntegrationTest1
|
||||||
|
{
|
||||||
|
// Instructions:
|
||||||
|
// 1. Add a project reference to the target AppHost project, e.g.:
|
||||||
|
//
|
||||||
|
// <ItemGroup>
|
||||||
|
// <ProjectReference Include="../MyAspireApp.AppHost/MyAspireApp.AppHost.csproj" />
|
||||||
|
// </ItemGroup>
|
||||||
|
//
|
||||||
|
// 2. Uncomment the following example test and update 'Projects.MyAspireApp_AppHost' to match your AppHost project:
|
||||||
|
//
|
||||||
|
// [Fact]
|
||||||
|
// public async Task GetWebResourceRootReturnsOkStatusCode()
|
||||||
|
// {
|
||||||
|
// // Arrange
|
||||||
|
// var appHost = await DistributedApplicationTestingBuilder.CreateAsync<Projects.MyAspireApp_AppHost>();
|
||||||
|
// appHost.Services.ConfigureHttpClientDefaults(clientBuilder =>
|
||||||
|
// {
|
||||||
|
// clientBuilder.AddStandardResilienceHandler();
|
||||||
|
// });
|
||||||
|
// // To output logs to the xUnit.net ITestOutputHelper, consider adding a package from https://www.nuget.org/packages?q=xunit+logging
|
||||||
|
//
|
||||||
|
// await using var app = await appHost.BuildAsync();
|
||||||
|
// var resourceNotificationService = app.Services.GetRequiredService<ResourceNotificationService>();
|
||||||
|
// await app.StartAsync();
|
||||||
|
|
||||||
|
// // Act
|
||||||
|
// var httpClient = app.CreateHttpClient("webfrontend");
|
||||||
|
// await resourceNotificationService.WaitForResourceAsync("webfrontend", KnownResourceStates.Running).WaitAsync(TimeSpan.FromSeconds(30));
|
||||||
|
// var response = await httpClient.GetAsync("/");
|
||||||
|
|
||||||
|
// // Assert
|
||||||
|
// Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
27
Tests/Tests.csproj
Normal file
27
Tests/Tests.csproj
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Aspire.Hosting.Testing" Version="9.3.1" />
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.2" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="System.Net" />
|
||||||
|
<Using Include="Microsoft.Extensions.DependencyInjection" />
|
||||||
|
<Using Include="Aspire.Hosting.ApplicationModel" />
|
||||||
|
<Using Include="Aspire.Hosting.Testing" />
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"ng": "ng",
|
"ng": "ng",
|
||||||
"start": "ng serve --host 0.0.0.0",
|
"start": "ng serve --host 0.0.0.0",
|
||||||
"build": "ng build",
|
"build": "ng build --configuration=production",
|
||||||
"watch": "ng build --watch --configuration development",
|
"watch": "ng build --watch --configuration development",
|
||||||
"test": "ng test"
|
"test": "ng test"
|
||||||
},
|
},
|
||||||
|
|||||||
16
Web/themes/modernize/.editorconfig
Normal file
16
Web/themes/modernize/.editorconfig
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# Editor configuration, see https://editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.ts]
|
||||||
|
quote_type = single
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
max_line_length = off
|
||||||
|
trim_trailing_whitespace = false
|
||||||
42
Web/themes/modernize/.gitignore
vendored
Normal file
42
Web/themes/modernize/.gitignore
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# Compiled output
|
||||||
|
/dist
|
||||||
|
/tmp
|
||||||
|
/out-tsc
|
||||||
|
/bazel-out
|
||||||
|
|
||||||
|
# Node
|
||||||
|
/node_modules
|
||||||
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
|
||||||
|
# IDEs and editors
|
||||||
|
.idea/
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.c9/
|
||||||
|
*.launch
|
||||||
|
.settings/
|
||||||
|
*.sublime-workspace
|
||||||
|
|
||||||
|
# Visual Studio Code
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.history/*
|
||||||
|
|
||||||
|
# Miscellaneous
|
||||||
|
/.angular/cache
|
||||||
|
.sass-cache/
|
||||||
|
/connect.lock
|
||||||
|
/coverage
|
||||||
|
/libpeerconnection.log
|
||||||
|
testem.log
|
||||||
|
/typings
|
||||||
|
|
||||||
|
# System files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
1
Web/themes/modernize/.npmrc
Normal file
1
Web/themes/modernize/.npmrc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
legacy-peer-deps=true
|
||||||
2
Web/themes/modernize/README.md
Normal file
2
Web/themes/modernize/README.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# Modernize-Angular-pro
|
||||||
|
Modernize Angular Admin Dashboard
|
||||||
96
Web/themes/modernize/angular.json
Normal file
96
Web/themes/modernize/angular.json
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
{
|
||||||
|
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||||
|
"version": 1,
|
||||||
|
"newProjectRoot": "projects",
|
||||||
|
"projects": {
|
||||||
|
"Modernize": {
|
||||||
|
"projectType": "application",
|
||||||
|
"schematics": {
|
||||||
|
"@schematics/angular:component": {
|
||||||
|
"style": "scss"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "",
|
||||||
|
"sourceRoot": "src",
|
||||||
|
"prefix": "app",
|
||||||
|
"architect": {
|
||||||
|
"build": {
|
||||||
|
"builder": "@angular-devkit/build-angular:browser",
|
||||||
|
"options": {
|
||||||
|
"allowedCommonJsDependencies": ["apexcharts", "bezier-easing", "moment"],
|
||||||
|
"outputPath": "dist/Modernize",
|
||||||
|
"index": "src/index.html",
|
||||||
|
"main": "src/main.ts",
|
||||||
|
"polyfills": ["zone.js"],
|
||||||
|
"tsConfig": "tsconfig.app.json",
|
||||||
|
"inlineStyleLanguage": "scss",
|
||||||
|
"assets": ["src/favicon.ico", "src/assets"],
|
||||||
|
"styles": ["src/styles.scss", "src/assets/scss/style.scss"],
|
||||||
|
"scripts": []
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"budgets": [
|
||||||
|
{
|
||||||
|
"type": "initial",
|
||||||
|
"maximumWarning": "12mb",
|
||||||
|
"maximumError": "12mb"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "anyComponentStyle",
|
||||||
|
"maximumWarning": "12mb",
|
||||||
|
"maximumError": "12mb"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputHashing": "all"
|
||||||
|
},
|
||||||
|
"development": {
|
||||||
|
"buildOptimizer": false,
|
||||||
|
"optimization": false,
|
||||||
|
"vendorChunk": true,
|
||||||
|
"extractLicenses": false,
|
||||||
|
"sourceMap": true,
|
||||||
|
"namedChunks": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultConfiguration": "production"
|
||||||
|
},
|
||||||
|
"serve": {
|
||||||
|
"builder": "@angular-devkit/build-angular:dev-server",
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"buildTarget": "Modernize:build:production"
|
||||||
|
},
|
||||||
|
"hmr": {
|
||||||
|
"hmr": true
|
||||||
|
},
|
||||||
|
"development": {
|
||||||
|
"buildTarget": "Modernize:build:development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultConfiguration": "development"
|
||||||
|
},
|
||||||
|
"extract-i18n": {
|
||||||
|
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||||
|
"options": {
|
||||||
|
"buildTarget": "Modernize:build"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"builder": "@angular-devkit/build-angular:karma",
|
||||||
|
"options": {
|
||||||
|
"polyfills": ["zone.js", "zone.js/testing"],
|
||||||
|
"tsConfig": "tsconfig.spec.json",
|
||||||
|
"inlineStyleLanguage": "scss",
|
||||||
|
"assets": ["src/favicon.ico", "src/assets"],
|
||||||
|
"styles": ["src/styles.scss"],
|
||||||
|
"scripts": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cli": {
|
||||||
|
"analytics": false
|
||||||
|
}
|
||||||
|
}
|
||||||
4
Web/themes/modernize/netlify.toml
Normal file
4
Web/themes/modernize/netlify.toml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[[redirects]]
|
||||||
|
from = "/*"
|
||||||
|
to = "/index.html"
|
||||||
|
status = 200
|
||||||
13801
Web/themes/modernize/package-lock.json
generated
Normal file
13801
Web/themes/modernize/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
48
Web/themes/modernize/package.json
Normal file
48
Web/themes/modernize/package.json
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"name": "modernize",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"scripts": {
|
||||||
|
"ng": "ng",
|
||||||
|
"start": "ng serve",
|
||||||
|
"build": "ng build",
|
||||||
|
"watch": "ng build --watch --configuration development",
|
||||||
|
"test": "ng test"
|
||||||
|
},
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@angular/animations": "^19.0.0",
|
||||||
|
"@angular/cdk": "^19.0.0",
|
||||||
|
"@angular/common": "^19.0.0",
|
||||||
|
"@angular/compiler": "^19.0.0",
|
||||||
|
"@angular/core": "^19.0.0",
|
||||||
|
"@angular/forms": "^19.0.0",
|
||||||
|
"@angular/material": "^19.0.0",
|
||||||
|
"@angular/platform-browser": "^19.0.0",
|
||||||
|
"@angular/platform-browser-dynamic": "^19.0.0",
|
||||||
|
"@angular/router": "^19.0.0",
|
||||||
|
"@ngx-translate/core": "^14.0.0",
|
||||||
|
"@ngx-translate/http-loader": "^7.0.0",
|
||||||
|
"angular-tabler-icons": "^2.7.0",
|
||||||
|
"apexcharts": "^3.49.0",
|
||||||
|
"ng-apexcharts": "1.7.6",
|
||||||
|
"ngx-scrollbar": "^11.0.0",
|
||||||
|
"rxjs": "~7.5.0",
|
||||||
|
"sass": "1.81.0",
|
||||||
|
"tslib": "^2.3.0",
|
||||||
|
"zone.js": "~0.15.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@angular-devkit/build-angular": "^19.0.1",
|
||||||
|
"@angular/cli": "~19.0.1",
|
||||||
|
"@angular/compiler-cli": "^19.0.0",
|
||||||
|
"@types/date-fns": "^2.6.0",
|
||||||
|
"@types/jasmine": "~4.3.0",
|
||||||
|
"jasmine-core": "~4.5.0",
|
||||||
|
"karma": "~6.4.0",
|
||||||
|
"karma-chrome-launcher": "~3.1.0",
|
||||||
|
"karma-coverage": "~2.2.0",
|
||||||
|
"karma-jasmine": "~5.1.0",
|
||||||
|
"karma-jasmine-html-reporter": "~2.0.0",
|
||||||
|
"typescript": "~5.6.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
Web/themes/modernize/src/app/app.component.html
Normal file
1
Web/themes/modernize/src/app/app.component.html
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<router-outlet></router-outlet>
|
||||||
35
Web/themes/modernize/src/app/app.component.spec.ts
Normal file
35
Web/themes/modernize/src/app/app.component.spec.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
|
describe('AppComponent', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [
|
||||||
|
RouterTestingModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
AppComponent
|
||||||
|
],
|
||||||
|
}).compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create the app', () => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.componentInstance;
|
||||||
|
expect(app).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should have as title 'Angular15'`, () => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.componentInstance;
|
||||||
|
expect(app.title).toEqual('Angular15');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render title', () => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
const compiled = fixture.nativeElement as HTMLElement;
|
||||||
|
expect(compiled.querySelector('.content span')?.textContent).toContain('Angular15 app is running!');
|
||||||
|
});
|
||||||
|
});
|
||||||
11
Web/themes/modernize/src/app/app.component.ts
Normal file
11
Web/themes/modernize/src/app/app.component.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { RouterOutlet } from '@angular/router';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
imports: [RouterOutlet],
|
||||||
|
templateUrl: './app.component.html'
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
title = 'Modernize Angular Admin Template';
|
||||||
|
}
|
||||||
55
Web/themes/modernize/src/app/app.config.ts
Normal file
55
Web/themes/modernize/src/app/app.config.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import {
|
||||||
|
ApplicationConfig,
|
||||||
|
provideZoneChangeDetection,
|
||||||
|
importProvidersFrom,
|
||||||
|
} from '@angular/core';
|
||||||
|
import {
|
||||||
|
HttpClient,
|
||||||
|
provideHttpClient,
|
||||||
|
withInterceptorsFromDi,
|
||||||
|
} from '@angular/common/http';
|
||||||
|
import { routes } from './app.routes';
|
||||||
|
import {
|
||||||
|
provideRouter,
|
||||||
|
withComponentInputBinding,
|
||||||
|
withInMemoryScrolling,
|
||||||
|
} from '@angular/router';
|
||||||
|
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
|
||||||
|
import { provideClientHydration } from '@angular/platform-browser';
|
||||||
|
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
||||||
|
|
||||||
|
// icons
|
||||||
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
|
import * as TablerIcons from 'angular-tabler-icons/icons';
|
||||||
|
|
||||||
|
// perfect scrollbar
|
||||||
|
import { NgScrollbarModule } from 'ngx-scrollbar';
|
||||||
|
|
||||||
|
//Import all material modules
|
||||||
|
import { MaterialModule } from './material.module';
|
||||||
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
|
||||||
|
export const appConfig: ApplicationConfig = {
|
||||||
|
providers: [
|
||||||
|
provideZoneChangeDetection({ eventCoalescing: true }),
|
||||||
|
provideRouter(
|
||||||
|
routes,
|
||||||
|
withInMemoryScrolling({
|
||||||
|
scrollPositionRestoration: 'enabled',
|
||||||
|
anchorScrolling: 'enabled',
|
||||||
|
}),
|
||||||
|
withComponentInputBinding()
|
||||||
|
),
|
||||||
|
provideHttpClient(withInterceptorsFromDi()),
|
||||||
|
provideClientHydration(),
|
||||||
|
provideAnimationsAsync(),
|
||||||
|
importProvidersFrom(
|
||||||
|
FormsModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
MaterialModule,
|
||||||
|
TablerIconsModule.pick(TablerIcons),
|
||||||
|
NgScrollbarModule,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
};
|
||||||
51
Web/themes/modernize/src/app/app.routes.ts
Normal file
51
Web/themes/modernize/src/app/app.routes.ts
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import { Routes } from '@angular/router';
|
||||||
|
import { BlankComponent } from './layouts/blank/blank.component';
|
||||||
|
import { FullComponent } from './layouts/full/full.component';
|
||||||
|
|
||||||
|
export const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: FullComponent,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
redirectTo: '/dashboard',
|
||||||
|
pathMatch: 'full',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'dashboard',
|
||||||
|
loadChildren: () =>
|
||||||
|
import('./pages/pages.routes').then((m) => m.PagesRoutes),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'ui-components',
|
||||||
|
loadChildren: () =>
|
||||||
|
import('./pages/ui-components/ui-components.routes').then(
|
||||||
|
(m) => m.UiComponentsRoutes
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'extra',
|
||||||
|
loadChildren: () =>
|
||||||
|
import('./pages/extra/extra.routes').then((m) => m.ExtraRoutes),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: BlankComponent,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'authentication',
|
||||||
|
loadChildren: () =>
|
||||||
|
import('./pages/authentication/authentication.routes').then(
|
||||||
|
(m) => m.AuthenticationRoutes
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '**',
|
||||||
|
redirectTo: 'authentication/error',
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<div class="row">
|
||||||
|
@for(productcard of productcards; track productcards) {
|
||||||
|
<div class="col-sm-6 col-lg-3">
|
||||||
|
<mat-card class="cardWithShadow productcard overflow-hidden">
|
||||||
|
<a routerLink="/widgets/cards">
|
||||||
|
<img src="{{ productcard.imgSrc }}" alt="imgSrc" class="w-100" mat-card-image />
|
||||||
|
</a>
|
||||||
|
<mat-card-content class="p-b-24 p-t-12 position-relative">
|
||||||
|
<button mat-mini-fab class="icon-30 cart-btn bg-primary text-white d-block" matTooltip="Add to Cart">
|
||||||
|
<i-tabler name="basket" class="icon-16"></i-tabler>
|
||||||
|
</button>
|
||||||
|
<mat-card-title class="mat-headline-2 f-s-16 m-b-4">{{
|
||||||
|
productcard.title
|
||||||
|
}}</mat-card-title>
|
||||||
|
<div class="d-flex align-items-center justify-content-between">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<h6 class="f-w-600 f-s-16">${{ productcard.price }}</h6>
|
||||||
|
<span class="f-s-14 m-l-4 text-decoration-line-through">${{ productcard.rprice }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="m-l-auto d-flex gap-4">
|
||||||
|
<span><i-tabler name="star" class="fill-warning icon-18"></i-tabler></span>
|
||||||
|
<span><i-tabler name="star" class="fill-warning icon-18"></i-tabler></span>
|
||||||
|
<span><i-tabler name="star" class="fill-warning icon-18"></i-tabler></span>
|
||||||
|
<span><i-tabler name="star" class="fill-warning icon-18"></i-tabler></span>
|
||||||
|
<span><i-tabler name="star" class="fill-warning icon-18"></i-tabler></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatCardModule } from '@angular/material/card';
|
||||||
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
|
|
||||||
|
// ecommerce card
|
||||||
|
interface productCards {
|
||||||
|
id: number;
|
||||||
|
imgSrc: string;
|
||||||
|
title: string;
|
||||||
|
price: string;
|
||||||
|
rprice: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-blog-card',
|
||||||
|
imports: [MatCardModule, TablerIconsModule, MatButtonModule],
|
||||||
|
templateUrl: './blog-card.component.html',
|
||||||
|
})
|
||||||
|
export class AppBlogCardsComponent {
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
productcards: productCards[] = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
imgSrc: '/assets/images/products/s4.jpg',
|
||||||
|
title: 'Boat Headphone',
|
||||||
|
price: '285',
|
||||||
|
rprice: '375',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
imgSrc: '/assets/images/products/s5.jpg',
|
||||||
|
title: 'MacBook Air Pro',
|
||||||
|
price: '285',
|
||||||
|
rprice: '375',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
imgSrc: '/assets/images/products/s7.jpg',
|
||||||
|
title: 'Red Valvet Dress',
|
||||||
|
price: '285',
|
||||||
|
rprice: '375',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
imgSrc: '/assets/images/products/s11.jpg',
|
||||||
|
title: 'Cute Soft Teddybear',
|
||||||
|
price: '285',
|
||||||
|
rprice: '375',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<mat-card class="cardWithShadow overflow-hidden">
|
||||||
|
<mat-card-content class="p-b-0">
|
||||||
|
<div class="d-flex align-items-center m-b-8">
|
||||||
|
<mat-card-title>Monthly Earnings</mat-card-title>
|
||||||
|
<div class="m-l-auto">
|
||||||
|
<button mat-fab class="icon-48 bg-secondary ">
|
||||||
|
<i-tabler name="currency-dollar" class="text-white d-flex"></i-tabler>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h4 class="f-s-24 m-b-6">$6,820</h4>
|
||||||
|
<div class="d-flex align-items-center m-t-16">
|
||||||
|
<button mat-mini-fab class="bg-light-error text-error shadow-none icon-27 p-0 d-flex align-items-center justify-content-center">
|
||||||
|
<i-tabler name="arrow-down-right" class="icon-20 d-flex align-items-center"></i-tabler>
|
||||||
|
</button>
|
||||||
|
<div class="f-s-14 f-w-600 m-l-12">+9%</div>
|
||||||
|
<div class="f-s-14 m-l-4">last year</div>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
<apx-chart [series]="monthlyChart.series" [dataLabels]="monthlyChart.dataLabels" [chart]="monthlyChart.chart"
|
||||||
|
[legend]="monthlyChart.legend" [colors]="monthlyChart.colors" [stroke]="monthlyChart.stroke"
|
||||||
|
[tooltip]="monthlyChart.tooltip" [plotOptions]="monthlyChart.plotOptions"
|
||||||
|
[responsive]="monthlyChart.responsive"></apx-chart>
|
||||||
|
</mat-card>
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
import { Component, ViewChild } from '@angular/core';
|
||||||
|
import {
|
||||||
|
ApexChart,
|
||||||
|
ChartComponent,
|
||||||
|
ApexDataLabels,
|
||||||
|
ApexLegend,
|
||||||
|
ApexStroke,
|
||||||
|
ApexTooltip,
|
||||||
|
ApexAxisChartSeries,
|
||||||
|
ApexPlotOptions,
|
||||||
|
ApexResponsive,
|
||||||
|
NgApexchartsModule,
|
||||||
|
} from 'ng-apexcharts';
|
||||||
|
|
||||||
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
|
||||||
|
export interface monthlyChart {
|
||||||
|
series: ApexAxisChartSeries;
|
||||||
|
chart: ApexChart;
|
||||||
|
dataLabels: ApexDataLabels;
|
||||||
|
plotOptions: ApexPlotOptions;
|
||||||
|
tooltip: ApexTooltip;
|
||||||
|
stroke: ApexStroke;
|
||||||
|
legend: ApexLegend;
|
||||||
|
responsive: ApexResponsive;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-monthly-earnings',
|
||||||
|
imports: [NgApexchartsModule, MaterialModule, TablerIconsModule],
|
||||||
|
templateUrl: './monthly-earnings.component.html',
|
||||||
|
})
|
||||||
|
export class AppMonthlyEarningsComponent {
|
||||||
|
@ViewChild('chart') chart: ChartComponent = Object.create(null);
|
||||||
|
public monthlyChart!: Partial<monthlyChart> | any;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.monthlyChart = {
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '',
|
||||||
|
color: '#49BEFF',
|
||||||
|
data: [25, 66, 20, 40, 12, 58, 20],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
chart: {
|
||||||
|
type: 'area',
|
||||||
|
fontFamily: "'Plus Jakarta Sans', sans-serif;",
|
||||||
|
foreColor: '#adb0bb',
|
||||||
|
toolbar: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
height: 85,
|
||||||
|
sparkline: {
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
group: 'sparklines',
|
||||||
|
},
|
||||||
|
stroke: {
|
||||||
|
curve: 'smooth',
|
||||||
|
width: 2,
|
||||||
|
},
|
||||||
|
fill: {
|
||||||
|
colors: ['#E8F7FF'],
|
||||||
|
type: 'solid',
|
||||||
|
opacity: 0.05,
|
||||||
|
},
|
||||||
|
markers: {
|
||||||
|
size: 0,
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
theme: 'dark',
|
||||||
|
x: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
<mat-card class="cardWithShadow">
|
||||||
|
<mat-card-content>
|
||||||
|
<div class="d-flex">
|
||||||
|
<div class="m-r-auto">
|
||||||
|
<mat-card-title>Top Projects</mat-card-title>
|
||||||
|
<mat-card-subtitle>Best Products</mat-card-subtitle>
|
||||||
|
</div>
|
||||||
|
<mat-form-field class="theme-select" appearance="outline">
|
||||||
|
<mat-select value="mar">
|
||||||
|
@for(month of months; track month.value) {
|
||||||
|
<mat-option [value]="month.value">
|
||||||
|
{{ month.viewValue }}
|
||||||
|
</mat-option>
|
||||||
|
}
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table mat-table [dataSource]="dataSource" class="w-100">
|
||||||
|
<!-- Position Column -->
|
||||||
|
<ng-container matColumnDef="product">
|
||||||
|
<th mat-header-cell *matHeaderCellDef class="f-w-600 f-s-14 p-l-0">
|
||||||
|
Product
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let element" class="p-l-0">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<img [src]="element.imagePath" alt="users" width="48" class="rounded" />
|
||||||
|
<div class="m-l-16">
|
||||||
|
<h6 class="f-s-14 f-w-600">
|
||||||
|
{{ element.pname }}
|
||||||
|
</h6>
|
||||||
|
<span class=" f-s-12">
|
||||||
|
{{ element.category }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Name Column -->
|
||||||
|
<ng-container matColumnDef="progress">
|
||||||
|
<th mat-header-cell *matHeaderCellDef class="f-w-600 f-s-14">
|
||||||
|
Progress
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let element">
|
||||||
|
{{ element.progress }}%
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Weight Column -->
|
||||||
|
<ng-container matColumnDef="status">
|
||||||
|
<th mat-header-cell *matHeaderCellDef class="f-w-600 f-s-14">
|
||||||
|
Status
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let element">
|
||||||
|
@if(element.status == 'low') {
|
||||||
|
<span class="bg-light-success text-success rounded f-w-600 p-6 p-y-4 f-s-12">
|
||||||
|
{{ element.status | titlecase }}
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if(element.status == 'medium') {
|
||||||
|
<span class="bg-light-warning text-warning rounded f-w-600 p-6 p-y-4 f-s-12">
|
||||||
|
{{ element.status | titlecase }}
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if(element.status == 'high') {
|
||||||
|
<span class="bg-light-primary text-primary rounded f-w-600 p-6 p-y-4 f-s-12">
|
||||||
|
{{ element.status | titlecase }}
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if(element.status == 'critical') {
|
||||||
|
<span class="bg-light-error text-error rounded f-w-600 p-6 p-y-4 f-s-12">
|
||||||
|
{{ element.status | titlecase }}
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Symbol Column -->
|
||||||
|
<ng-container matColumnDef="sales">
|
||||||
|
<th mat-header-cell *matHeaderCellDef class="f-w-600 f-s-14">
|
||||||
|
Sales
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let element">
|
||||||
|
${{ element.sales }}k
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { NgApexchartsModule } from 'ng-apexcharts';
|
||||||
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
|
||||||
|
export interface performanceData {
|
||||||
|
id: number;
|
||||||
|
imagePath: string;
|
||||||
|
pname: string;
|
||||||
|
category: string;
|
||||||
|
progress: number;
|
||||||
|
sales: number;
|
||||||
|
status: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ELEMENT_DATA: performanceData[] = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
imagePath: 'assets/images/products/s6.jpg',
|
||||||
|
pname: 'Gaming Console',
|
||||||
|
category: 'Electronics',
|
||||||
|
progress: 78.5,
|
||||||
|
sales: 3.9,
|
||||||
|
status: 'low',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
imagePath: 'assets/images/products/s9.jpg',
|
||||||
|
pname: 'Leather Purse',
|
||||||
|
category: 'Fashion',
|
||||||
|
progress: 58.6,
|
||||||
|
sales: 3.5,
|
||||||
|
status: 'medium',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
imagePath: 'assets/images/products/s7.jpg',
|
||||||
|
pname: 'Red Velvate Dress',
|
||||||
|
category: 'Womens Fashion',
|
||||||
|
progress: 25,
|
||||||
|
sales: 3.8,
|
||||||
|
status: 'high',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
imagePath: 'assets/images/products/s4.jpg',
|
||||||
|
pname: 'Headphone Boat',
|
||||||
|
category: 'Electronics',
|
||||||
|
progress: 96.3,
|
||||||
|
sales: 3.54,
|
||||||
|
status: 'critical',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
interface month {
|
||||||
|
value: string;
|
||||||
|
viewValue: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-product-performance',
|
||||||
|
imports: [
|
||||||
|
NgApexchartsModule,
|
||||||
|
MaterialModule,
|
||||||
|
TablerIconsModule,
|
||||||
|
CommonModule,
|
||||||
|
],
|
||||||
|
templateUrl: './product-performance.component.html',
|
||||||
|
})
|
||||||
|
export class AppProductPerformanceComponent {
|
||||||
|
displayedColumns: string[] = ['product', 'progress', 'status', 'sales'];
|
||||||
|
dataSource = ELEMENT_DATA;
|
||||||
|
|
||||||
|
months: month[] = [
|
||||||
|
{ value: 'mar', viewValue: 'March 2025' },
|
||||||
|
{ value: 'apr', viewValue: 'April 2025' },
|
||||||
|
{ value: 'june', viewValue: 'June 2025' },
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<mat-card class="cardWithShadow">
|
||||||
|
<mat-card-content>
|
||||||
|
<mat-card-title>Recent Transactions</mat-card-title>
|
||||||
|
|
||||||
|
<div class="timeline m-t-24">
|
||||||
|
@for(stat of stats; track stat.title) {
|
||||||
|
<div class="timeline-item d-flex overflow-hidden">
|
||||||
|
<div class="time text-right f-s-14">{{ stat.time }}</div>
|
||||||
|
<div class="point d-flex align-items-center">
|
||||||
|
<span class="timeline-badge border-{{ stat.color }} m-y-8"></span>
|
||||||
|
<span class="timline-border d-block"></span>
|
||||||
|
</div>
|
||||||
|
<div class="desc">
|
||||||
|
@if(stat.subtext) {
|
||||||
|
<span class="f-s-14 lh-20">{{ stat.subtext }}</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if(stat.title) {
|
||||||
|
<span class="f-s-14 lh-20 f-w-600 d-block">{{
|
||||||
|
stat.title
|
||||||
|
}}</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if(stat.link) {
|
||||||
|
<a href="#" class="text-primary text-decoration-none f-s-14">#ML-3467</a>
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { NgApexchartsModule } from 'ng-apexcharts';
|
||||||
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
|
||||||
|
|
||||||
|
interface stats {
|
||||||
|
id: number;
|
||||||
|
time: string;
|
||||||
|
color: string;
|
||||||
|
title?: string;
|
||||||
|
subtext?: string;
|
||||||
|
link?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-recent-transactions',
|
||||||
|
imports: [NgApexchartsModule, MaterialModule],
|
||||||
|
templateUrl: './recent-transactions.component.html',
|
||||||
|
})
|
||||||
|
export class AppRecentTransactionsComponent {
|
||||||
|
stats: stats[] = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
time: '09.30 am',
|
||||||
|
color: 'primary',
|
||||||
|
subtext: 'Payment received from John Doe of $385.90',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
time: '10.30 am',
|
||||||
|
color: 'accent',
|
||||||
|
title: 'New sale recorded',
|
||||||
|
link: '#ML-3467',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
time: '12.30 pm',
|
||||||
|
color: 'success',
|
||||||
|
subtext: 'Payment was made of $64.95 to Michael',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
time: '12.30 pm',
|
||||||
|
color: 'warning',
|
||||||
|
title: 'New sale recorded',
|
||||||
|
link: '#ML-3467',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
time: '12.30 pm',
|
||||||
|
color: 'error',
|
||||||
|
title: 'New arrival recorded',
|
||||||
|
link: '#ML-3467',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
time: '12.30 pm',
|
||||||
|
color: 'success',
|
||||||
|
subtext: 'Payment Done',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<mat-card class="cardWithShadow">
|
||||||
|
<mat-card-content>
|
||||||
|
<div class="d-flex w-100">
|
||||||
|
<mat-card-title>Sales Overview</mat-card-title>
|
||||||
|
<div class="m-l-auto">
|
||||||
|
<mat-form-field class="theme-select" appearance="outline">
|
||||||
|
<mat-select value="mar">
|
||||||
|
@for(month of months; track month.viewValue ) {
|
||||||
|
<mat-option [value]="month.value">
|
||||||
|
{{ month.viewValue }}
|
||||||
|
</mat-option>
|
||||||
|
}
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<apx-chart [series]="salesOverviewChart.series" [dataLabels]="salesOverviewChart.dataLabels"
|
||||||
|
[chart]="salesOverviewChart.chart" [legend]="salesOverviewChart.legend" [xaxis]="salesOverviewChart.xaxis"
|
||||||
|
[yaxis]="salesOverviewChart.yaxis" [grid]="salesOverviewChart.grid" [stroke]="salesOverviewChart.stroke"
|
||||||
|
[tooltip]="salesOverviewChart.tooltip" [plotOptions]="salesOverviewChart.plotOptions"></apx-chart>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
import { Component, ViewChild } from '@angular/core';
|
||||||
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
|
||||||
|
import {
|
||||||
|
ApexChart,
|
||||||
|
ChartComponent,
|
||||||
|
ApexDataLabels,
|
||||||
|
ApexLegend,
|
||||||
|
ApexStroke,
|
||||||
|
ApexTooltip,
|
||||||
|
ApexAxisChartSeries,
|
||||||
|
ApexXAxis,
|
||||||
|
ApexYAxis,
|
||||||
|
ApexGrid,
|
||||||
|
ApexPlotOptions,
|
||||||
|
ApexFill,
|
||||||
|
ApexMarkers,
|
||||||
|
ApexResponsive,
|
||||||
|
NgApexchartsModule,
|
||||||
|
} from 'ng-apexcharts';
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
|
||||||
|
interface month {
|
||||||
|
value: string;
|
||||||
|
viewValue: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface salesOverviewChart {
|
||||||
|
series: ApexAxisChartSeries;
|
||||||
|
chart: ApexChart;
|
||||||
|
dataLabels: ApexDataLabels;
|
||||||
|
plotOptions: ApexPlotOptions;
|
||||||
|
yaxis: ApexYAxis;
|
||||||
|
xaxis: ApexXAxis;
|
||||||
|
fill: ApexFill;
|
||||||
|
tooltip: ApexTooltip;
|
||||||
|
stroke: ApexStroke;
|
||||||
|
legend: ApexLegend;
|
||||||
|
grid: ApexGrid;
|
||||||
|
marker: ApexMarkers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-sales-overview',
|
||||||
|
imports: [MaterialModule, TablerIconsModule, NgApexchartsModule, MatButtonModule],
|
||||||
|
templateUrl: './sales-overview.component.html',
|
||||||
|
})
|
||||||
|
export class AppSalesOverviewComponent {
|
||||||
|
|
||||||
|
@ViewChild('chart') chart: ChartComponent = Object.create(null);
|
||||||
|
|
||||||
|
public salesOverviewChart!: Partial<salesOverviewChart> | any;
|
||||||
|
|
||||||
|
months: month[] = [
|
||||||
|
{ value: 'mar', viewValue: 'Sep 2025' },
|
||||||
|
{ value: 'apr', viewValue: 'Oct 2025' },
|
||||||
|
{ value: 'june', viewValue: 'Nov 2025' },
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
// sales overview chart
|
||||||
|
this.salesOverviewChart = {
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Eanings this month',
|
||||||
|
data: [355, 390, 300, 350, 390, 180, 355, 390],
|
||||||
|
color: '#5D87FF',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Expense this month',
|
||||||
|
data: [280, 250, 325, 215, 250, 310, 280, 250],
|
||||||
|
color: '#49BEFF',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
grid: {
|
||||||
|
borderColor: 'rgba(0,0,0,0.1)',
|
||||||
|
strokeDashArray: 3,
|
||||||
|
xaxis: {
|
||||||
|
lines: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plotOptions: {
|
||||||
|
bar: { horizontal: false, columnWidth: '35%', borderRadius: [4] },
|
||||||
|
},
|
||||||
|
chart: {
|
||||||
|
type: 'bar',
|
||||||
|
height: 390,
|
||||||
|
offsetX: -15,
|
||||||
|
toolbar: { show: false },
|
||||||
|
foreColor: '#adb0bb',
|
||||||
|
fontFamily: 'inherit',
|
||||||
|
sparkline: { enabled: false },
|
||||||
|
},
|
||||||
|
dataLabels: { enabled: false },
|
||||||
|
markers: { size: 0 },
|
||||||
|
legend: { show: false },
|
||||||
|
xaxis: {
|
||||||
|
type: 'category',
|
||||||
|
categories: [
|
||||||
|
'16/08',
|
||||||
|
'17/08',
|
||||||
|
'18/08',
|
||||||
|
'19/08',
|
||||||
|
'20/08',
|
||||||
|
'21/08',
|
||||||
|
'22/08',
|
||||||
|
'23/08',
|
||||||
|
],
|
||||||
|
labels: {
|
||||||
|
style: { cssClass: 'grey--text lighten-2--text fill-color' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
yaxis: {
|
||||||
|
show: true,
|
||||||
|
min: 0,
|
||||||
|
max: 400,
|
||||||
|
tickAmount: 4,
|
||||||
|
labels: {
|
||||||
|
style: {
|
||||||
|
cssClass: 'grey--text lighten-2--text fill-color',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
stroke: {
|
||||||
|
show: true,
|
||||||
|
width: 3,
|
||||||
|
lineCap: 'butt',
|
||||||
|
colors: ['transparent'],
|
||||||
|
},
|
||||||
|
tooltip: { theme: 'light' },
|
||||||
|
|
||||||
|
responsive: [
|
||||||
|
{
|
||||||
|
breakpoint: 600,
|
||||||
|
options: {
|
||||||
|
plotOptions: {
|
||||||
|
bar: {
|
||||||
|
borderRadius: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
<mat-card class="cardWithShadow">
|
||||||
|
<mat-card-content>
|
||||||
|
<mat-card-title>Yearly Breakup</mat-card-title>
|
||||||
|
<div class="row m-t-24">
|
||||||
|
<div class="col-7">
|
||||||
|
<h4 class="f-s-24">$36,358</h4>
|
||||||
|
<div class="d-flex align-items-center m-t-16">
|
||||||
|
<button mat-icon-button class="bg-light-success text-success shadow-none icon-27 p-0 d-flex align-items-center justify-content-center">
|
||||||
|
<i-tabler name="arrow-up-right" class="icon-20 d-flex align-items-center"></i-tabler>
|
||||||
|
</button>
|
||||||
|
<div class="f-w-600 m-l-12 f-s-14">+9%</div>
|
||||||
|
<div class="m-l-4 f-s-14">last year</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex align-items-center m-t-32">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<i-tabler name="circle-filled" class="text-primary icon-12 d-flex"></i-tabler>
|
||||||
|
<div class="m-l-12 f-s-14">2025</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex align-items-center m-l-16">
|
||||||
|
<i-tabler name="circle-filled" class="text-light-primary icon-12 d-flex"></i-tabler>
|
||||||
|
<div class="m-l-12 f-s-14">2024</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-5 d-flex align-items-start">
|
||||||
|
<apx-chart [series]="yearlyChart.series" [dataLabels]="yearlyChart.dataLabels"
|
||||||
|
[chart]="yearlyChart.chart" [legend]="yearlyChart.legend" [colors]="yearlyChart.colors"
|
||||||
|
[stroke]="yearlyChart.stroke" [tooltip]="yearlyChart.tooltip"
|
||||||
|
[plotOptions]="yearlyChart.plotOptions" [responsive]="yearlyChart.responsive"></apx-chart>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
|
||||||
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
|
import {
|
||||||
|
ApexChart,
|
||||||
|
ChartComponent,
|
||||||
|
ApexDataLabels,
|
||||||
|
ApexLegend,
|
||||||
|
ApexStroke,
|
||||||
|
ApexTooltip,
|
||||||
|
ApexAxisChartSeries,
|
||||||
|
ApexXAxis,
|
||||||
|
ApexYAxis,
|
||||||
|
ApexGrid,
|
||||||
|
ApexPlotOptions,
|
||||||
|
ApexFill,
|
||||||
|
ApexMarkers,
|
||||||
|
ApexResponsive,
|
||||||
|
NgApexchartsModule,
|
||||||
|
} from 'ng-apexcharts';
|
||||||
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
|
||||||
|
|
||||||
|
export interface yearlyChart {
|
||||||
|
series: ApexAxisChartSeries;
|
||||||
|
chart: ApexChart;
|
||||||
|
dataLabels: ApexDataLabels;
|
||||||
|
plotOptions: ApexPlotOptions;
|
||||||
|
tooltip: ApexTooltip;
|
||||||
|
stroke: ApexStroke;
|
||||||
|
legend: ApexLegend;
|
||||||
|
responsive: ApexResponsive;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-yearly-breakup',
|
||||||
|
templateUrl: './yearly-breakup.component.html',
|
||||||
|
imports: [MaterialModule, NgApexchartsModule, TablerIconsModule],
|
||||||
|
encapsulation: ViewEncapsulation.None,
|
||||||
|
})
|
||||||
|
export class AppYearlyBreakupComponent {
|
||||||
|
@ViewChild('chart') chart: ChartComponent = Object.create(null);
|
||||||
|
|
||||||
|
public yearlyChart!: Partial<yearlyChart> | any;
|
||||||
|
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
this.yearlyChart = {
|
||||||
|
|
||||||
|
color: "#adb5bd",
|
||||||
|
series: [38, 40, 25],
|
||||||
|
labels: ["2025", "2024", "2023"],
|
||||||
|
chart: {
|
||||||
|
width: 125,
|
||||||
|
type: "donut",
|
||||||
|
fontFamily: "inherit",
|
||||||
|
foreColor: "#adb0bb",
|
||||||
|
},
|
||||||
|
plotOptions: {
|
||||||
|
pie: {
|
||||||
|
startAngle: 0,
|
||||||
|
endAngle: 360,
|
||||||
|
donut: {
|
||||||
|
size: "75%",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
stroke: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
dataLabels: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
legend: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
colors: ['#5D87FF', '#ECF2FF', '#F9F9FD'],
|
||||||
|
|
||||||
|
responsive: [
|
||||||
|
{
|
||||||
|
breakpoint: 991,
|
||||||
|
options: {
|
||||||
|
chart: {
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tooltip: {
|
||||||
|
theme: "dark",
|
||||||
|
fillSeriesColor: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Web/themes/modernize/src/app/config.ts
Normal file
11
Web/themes/modernize/src/app/config.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
export interface AppSettings {
|
||||||
|
|
||||||
|
sidenavOpened: boolean;
|
||||||
|
sidenavCollapsed: boolean;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export const defaults: AppSettings = {
|
||||||
|
sidenavOpened: false,
|
||||||
|
sidenavCollapsed: false,
|
||||||
|
};
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<!-- ============================================================== -->
|
||||||
|
<!-- Only router without any element -->
|
||||||
|
<!-- ============================================================== -->
|
||||||
|
<mat-sidenav-container dir="ltr" class="light-theme">
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
</mat-sidenav-container>
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { CoreService } from 'src/app/services/core.service';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { RouterOutlet } from '@angular/router';
|
||||||
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-blank',
|
||||||
|
templateUrl: './blank.component.html',
|
||||||
|
styleUrls: [],
|
||||||
|
imports: [RouterOutlet, MaterialModule, CommonModule],
|
||||||
|
})
|
||||||
|
export class BlankComponent {
|
||||||
|
private htmlElement!: HTMLHtmlElement;
|
||||||
|
|
||||||
|
options = this.settings.getOptions();
|
||||||
|
|
||||||
|
constructor(private settings: CoreService) {
|
||||||
|
this.htmlElement = document.querySelector('html')!;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
|
||||||
|
<app-topstrip></app-topstrip>
|
||||||
|
<mat-sidenav-container class="mainWrapper blue_theme light-theme" autosize autoFocus dir="ltr">
|
||||||
|
<!-- ============================================================== -->
|
||||||
|
<!-- Vertical Sidebar -->
|
||||||
|
<!-- ============================================================== -->
|
||||||
|
<mat-sidenav #leftsidenav [mode]="isOver ? 'over' : 'side'" [opened]="!isOver"
|
||||||
|
(openedChange)="onSidenavOpenedChange($event)" (closedStart)="onSidenavClosedStart()" class="sidebarNav">
|
||||||
|
<div class="flex-layout">
|
||||||
|
<app-sidebar (toggleMobileNav)="sidenav.toggle()" [showToggle]="isOver"></app-sidebar>
|
||||||
|
<ng-scrollbar class="position-relative" style="height: 100%">
|
||||||
|
<mat-nav-list class="sidebar-list">
|
||||||
|
@for(item of navItems; track item) {
|
||||||
|
<app-nav-item [item]="item" (notify)="sidenav.toggle()">
|
||||||
|
</app-nav-item>
|
||||||
|
}
|
||||||
|
</mat-nav-list>
|
||||||
|
</ng-scrollbar>
|
||||||
|
<div class="p-24">
|
||||||
|
<div class="bg-light-secondary d-flex align-items-center gap-4 rounded p-20 m-t-20">
|
||||||
|
<div>
|
||||||
|
<h5 class="f-s-16 f-w-600 m-b-8">
|
||||||
|
Check Pro <br> Version
|
||||||
|
</h5>
|
||||||
|
<a mat-flat-button
|
||||||
|
href="https://adminmart.com/product/modernize-angular-material-dashboard/?ref=56#product-demo-section" target="_blank"
|
||||||
|
class="d-flex justify-content-center bg-secondary">
|
||||||
|
Check
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<img src="/assets/images/backgrounds/rocket.png" alt="imgae" class="side-img m-t--48 m-r--8" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-sidenav>
|
||||||
|
|
||||||
|
<!-- ============================================================== -->
|
||||||
|
<!-- Main Content -->
|
||||||
|
<!-- ============================================================== -->
|
||||||
|
<mat-sidenav-content class="contentWrapper" #content>
|
||||||
|
<!-- ============================================================== -->
|
||||||
|
<!-- VerticalHeader -->
|
||||||
|
<!-- ============================================================== -->
|
||||||
|
|
||||||
|
<app-header [showToggle]="!isOver" (toggleMobileNav)="sidenav.toggle()"></app-header>
|
||||||
|
|
||||||
|
<main class="pageWrapper maxWidth">
|
||||||
|
<!-- ============================================================== -->
|
||||||
|
<!-- Outlet -->
|
||||||
|
<!-- ============================================================== -->
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<div class="p-16 p-b-30 text-center">
|
||||||
|
Design & Developed by <a class="text-decoration-none" href="https://adminmart.com/" target="_blank">AdminMart.com</a>
|
||||||
|
</div>
|
||||||
|
</mat-sidenav-content>
|
||||||
|
|
||||||
|
</mat-sidenav-container>
|
||||||
117
Web/themes/modernize/src/app/layouts/full/full.component.ts
Normal file
117
Web/themes/modernize/src/app/layouts/full/full.component.ts
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
import { BreakpointObserver, MediaMatcher } from '@angular/cdk/layout';
|
||||||
|
import { Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||||
|
import { Subscription } from 'rxjs';
|
||||||
|
import { MatSidenav, MatSidenavContent } from '@angular/material/sidenav';
|
||||||
|
import { CoreService } from 'src/app/services/core.service';
|
||||||
|
|
||||||
|
import { filter } from 'rxjs/operators';
|
||||||
|
import { NavigationEnd, Router } from '@angular/router';
|
||||||
|
import { NavService } from '../../services/nav.service';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { NgScrollbarModule } from 'ngx-scrollbar';
|
||||||
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
|
import { HeaderComponent } from './header/header.component';
|
||||||
|
import { SidebarComponent } from './sidebar/sidebar.component';
|
||||||
|
import { AppNavItemComponent } from './sidebar/nav-item/nav-item.component';
|
||||||
|
import { navItems } from './sidebar/sidebar-data';
|
||||||
|
import { AppTopstripComponent } from './top-strip/topstrip.component';
|
||||||
|
|
||||||
|
|
||||||
|
const MOBILE_VIEW = 'screen and (max-width: 768px)';
|
||||||
|
const TABLET_VIEW = 'screen and (min-width: 769px) and (max-width: 1024px)';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-full',
|
||||||
|
imports: [
|
||||||
|
RouterModule,
|
||||||
|
AppNavItemComponent,
|
||||||
|
MaterialModule,
|
||||||
|
CommonModule,
|
||||||
|
SidebarComponent,
|
||||||
|
NgScrollbarModule,
|
||||||
|
TablerIconsModule,
|
||||||
|
HeaderComponent,
|
||||||
|
AppTopstripComponent
|
||||||
|
],
|
||||||
|
templateUrl: './full.component.html',
|
||||||
|
styleUrls: [],
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
|
})
|
||||||
|
export class FullComponent implements OnInit {
|
||||||
|
navItems = navItems;
|
||||||
|
|
||||||
|
@ViewChild('leftsidenav')
|
||||||
|
public sidenav: MatSidenav;
|
||||||
|
resView = false;
|
||||||
|
@ViewChild('content', { static: true }) content!: MatSidenavContent;
|
||||||
|
//get options from service
|
||||||
|
options = this.settings.getOptions();
|
||||||
|
private layoutChangesSubscription = Subscription.EMPTY;
|
||||||
|
private isMobileScreen = false;
|
||||||
|
private isContentWidthFixed = true;
|
||||||
|
private isCollapsedWidthFixed = false;
|
||||||
|
private htmlElement!: HTMLHtmlElement;
|
||||||
|
|
||||||
|
get isOver(): boolean {
|
||||||
|
return this.isMobileScreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private settings: CoreService,
|
||||||
|
private router: Router,
|
||||||
|
private breakpointObserver: BreakpointObserver,
|
||||||
|
) {
|
||||||
|
this.htmlElement = document.querySelector('html')!;
|
||||||
|
this.layoutChangesSubscription = this.breakpointObserver
|
||||||
|
.observe([MOBILE_VIEW, TABLET_VIEW])
|
||||||
|
.subscribe((state) => {
|
||||||
|
// SidenavOpened must be reset true when layout changes
|
||||||
|
this.options.sidenavOpened = true;
|
||||||
|
this.isMobileScreen = state.breakpoints[MOBILE_VIEW];
|
||||||
|
if (this.options.sidenavCollapsed == false) {
|
||||||
|
this.options.sidenavCollapsed = state.breakpoints[TABLET_VIEW];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initialize project theme with options
|
||||||
|
|
||||||
|
|
||||||
|
// This is for scroll to top
|
||||||
|
this.router.events
|
||||||
|
.pipe(filter((event) => event instanceof NavigationEnd))
|
||||||
|
.subscribe((e) => {
|
||||||
|
this.content.scrollTo({ top: 0 });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void { }
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.layoutChangesSubscription.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleCollapsed() {
|
||||||
|
this.isContentWidthFixed = false;
|
||||||
|
this.options.sidenavCollapsed = !this.options.sidenavCollapsed;
|
||||||
|
this.resetCollapsedState();
|
||||||
|
}
|
||||||
|
|
||||||
|
resetCollapsedState(timer = 400) {
|
||||||
|
setTimeout(() => this.settings.setOptions(this.options), timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSidenavClosedStart() {
|
||||||
|
this.isContentWidthFixed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
onSidenavOpenedChange(isOpened: boolean) {
|
||||||
|
this.isCollapsedWidthFixed = !this.isOver;
|
||||||
|
this.options.sidenavOpened = isOpened;
|
||||||
|
//this.settings.setOptions(this.options);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
<mat-toolbar class="topbar gap-10">
|
||||||
|
|
||||||
|
<!-- Mobile Menu -->
|
||||||
|
|
||||||
|
<button mat-icon-button (click)="toggleMobileNav.emit()" class="d-flex d-lg-none justify-content-center">
|
||||||
|
<i-tabler name="menu-2" class="icon-20 d-flex"></i-tabler>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button mat-icon-button [matMenuTriggerFor]="menu" aria-label="Notifications">
|
||||||
|
<i-tabler class="d-flex" name="bell" matBadge="1" matBadgeColor="primary"></i-tabler>
|
||||||
|
</button>
|
||||||
|
<mat-menu #menu="matMenu">
|
||||||
|
<button mat-menu-item>Item 1</button>
|
||||||
|
<button mat-menu-item>Item 2</button>
|
||||||
|
</mat-menu>
|
||||||
|
|
||||||
|
|
||||||
|
<span class="flex-1-auto"></span>
|
||||||
|
|
||||||
|
<!-- --------------------------------------------------------------- -->
|
||||||
|
<!-- profile Dropdown -->
|
||||||
|
<!-- --------------------------------------------------------------- -->
|
||||||
|
<a mat-flat-button href="https://adminmart.com/product/modernize-angular-admin-dashboard/?ref=56#product-demo-section"
|
||||||
|
target="_blank" class="d-flex justify-content-center bg-success">
|
||||||
|
Check Pro Template
|
||||||
|
</a>
|
||||||
|
<button mat-mini-fab [matMenuTriggerFor]="profilemenu" aria-label="Notifications">
|
||||||
|
<img src="/assets/images/profile/user-1.jpg" class="rounded-circle object-cover d-block" width="35" />
|
||||||
|
</button>
|
||||||
|
<mat-menu #profilemenu="matMenu" class="cardWithShadow topbar-dd">
|
||||||
|
<button mat-menu-item>
|
||||||
|
<mat-icon class="d-flex align-items-center"><i-tabler name="user" class="icon-18 d-flex"></i-tabler></mat-icon>My
|
||||||
|
Profile
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item>
|
||||||
|
<mat-icon class="d-flex align-items-center"><i-tabler name="mail" class="icon-18 d-flex"></i-tabler></mat-icon>My
|
||||||
|
Account
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item>
|
||||||
|
<mat-icon class="d-flex align-items-center"><i-tabler name="list-check"
|
||||||
|
class="icon-18 d-flex"></i-tabler></mat-icon>My Task
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="p-x-12 m-t-12">
|
||||||
|
<a [routerLink]="['/authentication/login']" mat-stroked-button class="w-100">Logout</a>
|
||||||
|
</div>
|
||||||
|
</mat-menu>
|
||||||
|
</mat-toolbar>
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import {
|
||||||
|
Component,
|
||||||
|
Output,
|
||||||
|
EventEmitter,
|
||||||
|
Input,
|
||||||
|
ViewEncapsulation,
|
||||||
|
} from '@angular/core';
|
||||||
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { NgScrollbarModule } from 'ngx-scrollbar';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-header',
|
||||||
|
imports: [
|
||||||
|
RouterModule,
|
||||||
|
CommonModule,
|
||||||
|
NgScrollbarModule,
|
||||||
|
TablerIconsModule,
|
||||||
|
MaterialModule,
|
||||||
|
],
|
||||||
|
templateUrl: './header.component.html',
|
||||||
|
encapsulation: ViewEncapsulation.None,
|
||||||
|
})
|
||||||
|
export class HeaderComponent {
|
||||||
|
@Input() showToggle = true;
|
||||||
|
@Input() toggleChecked = false;
|
||||||
|
@Output() toggleMobileNav = new EventEmitter<void>();
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { CoreService } from 'src/app/services/core.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-branding',
|
||||||
|
imports: [],
|
||||||
|
template: `
|
||||||
|
<a href="/" class="logodark">
|
||||||
|
<img
|
||||||
|
src="./assets/images/logos/dark-logo.svg"
|
||||||
|
class="align-middle m-2"
|
||||||
|
alt="logo"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
`,
|
||||||
|
})
|
||||||
|
export class BrandingComponent {
|
||||||
|
options = this.settings.getOptions();
|
||||||
|
constructor(private settings: CoreService) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
@if(item.navCap){
|
||||||
|
<div mat-subheader class="nav-caption">
|
||||||
|
{{ item.navCap }}
|
||||||
|
</div>
|
||||||
|
} @if(!item.navCap && !item.external) {
|
||||||
|
<a mat-list-item (click)="onItemSelected(item)" [ngClass]="{
|
||||||
|
activeMenu: item.route ? router.isActive(item.route, true) : false,
|
||||||
|
expanded: expanded,
|
||||||
|
disabled: item.disabled
|
||||||
|
}" class="menu-list-item">
|
||||||
|
<i-tabler class="routeIcon" name="{{ item.iconName }}" matListItemIcon></i-tabler>
|
||||||
|
<span class="hide-menu">{{ item.displayName }}</span>
|
||||||
|
|
||||||
|
@if(item.children && item.children.length) {
|
||||||
|
<span class="arrow-icon" fxFlex>
|
||||||
|
<span fxFlex></span>
|
||||||
|
@if(item.chip) {
|
||||||
|
<span>
|
||||||
|
<span class="{{ item.chipClass }} p-x-8 p-y-4 item-chip f-w-500 rounded-pill ">{{ item.chipContent }}</span>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
<mat-icon [@indicatorRotate]="expanded ? 'expanded' : 'collapsed'">
|
||||||
|
expand_more
|
||||||
|
</mat-icon>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
</a>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- external Link -->
|
||||||
|
|
||||||
|
@if(!item.navCap && item.external) {
|
||||||
|
<mat-list-item (click)="openExternalLink(item.route)" class="menu-list-item" target="_blank">
|
||||||
|
<i-tabler class="routeIcon" name="{{ item.iconName }}" matListItemIcon></i-tabler>
|
||||||
|
<span class="hide-menu">{{ item.displayName }} </span>
|
||||||
|
@if(item.chip) {
|
||||||
|
<span>
|
||||||
|
<span class="{{ item.chipClass }} p-x-8 p-y-4 item-chip f-w-500 rounded-pill ">{{ item.chipContent }}</span>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
</mat-list-item>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- children -->
|
||||||
|
@if(expanded) { @for(child of item.children; track child) {
|
||||||
|
<app-nav-item [item]="child" (click)="onSubItemSelected(child)" [depth]="depth + 1">
|
||||||
|
</app-nav-item>
|
||||||
|
} }
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import {
|
||||||
|
Component,
|
||||||
|
HostBinding,
|
||||||
|
Input,
|
||||||
|
OnChanges,
|
||||||
|
Output,
|
||||||
|
EventEmitter,
|
||||||
|
} from '@angular/core';
|
||||||
|
import { NavItem } from './nav-item';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { NavService } from '../../../../services/nav.service';
|
||||||
|
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-nav-item',
|
||||||
|
imports: [TranslateModule, TablerIconsModule, MaterialModule, CommonModule],
|
||||||
|
templateUrl: './nav-item.component.html',
|
||||||
|
styleUrls: [],
|
||||||
|
})
|
||||||
|
export class AppNavItemComponent implements OnChanges {
|
||||||
|
@Output() notify: EventEmitter<boolean> = new EventEmitter<boolean>();
|
||||||
|
|
||||||
|
@Input() item: NavItem | any;
|
||||||
|
|
||||||
|
expanded: any = false;
|
||||||
|
|
||||||
|
@HostBinding('attr.aria-expanded') ariaExpanded = this.expanded;
|
||||||
|
@Input() depth: any;
|
||||||
|
|
||||||
|
constructor(public navService: NavService, public router: Router) {}
|
||||||
|
|
||||||
|
ngOnChanges() {
|
||||||
|
const url = this.navService.currentUrl();
|
||||||
|
if (this.item.route && url) {
|
||||||
|
this.expanded = url.indexOf(`/${this.item.route}`) === 0;
|
||||||
|
this.ariaExpanded = this.expanded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onItemSelected(item: NavItem) {
|
||||||
|
if (!item.children || !item.children.length) {
|
||||||
|
this.router.navigate([item.route]);
|
||||||
|
}
|
||||||
|
if (item.children && item.children.length) {
|
||||||
|
this.expanded = !this.expanded;
|
||||||
|
}
|
||||||
|
//scroll
|
||||||
|
window.scroll({
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
behavior: 'smooth',
|
||||||
|
});
|
||||||
|
if (!this.expanded) {
|
||||||
|
if (window.innerWidth < 1024) {
|
||||||
|
this.notify.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
openExternalLink(url: string): void {
|
||||||
|
if (url) {
|
||||||
|
window.open(url, '_blank');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubItemSelected(item: NavItem) {
|
||||||
|
if (!item.children || !item.children.length) {
|
||||||
|
if (this.expanded && window.innerWidth < 1024) {
|
||||||
|
this.notify.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
export interface NavItem {
|
||||||
|
displayName?: string;
|
||||||
|
iconName?: string;
|
||||||
|
navCap?: string;
|
||||||
|
route?: string;
|
||||||
|
children?: NavItem[];
|
||||||
|
chip?: boolean;
|
||||||
|
chipContent?: string;
|
||||||
|
chipClass?: string;
|
||||||
|
external?: boolean;
|
||||||
|
}
|
||||||
@@ -0,0 +1,914 @@
|
|||||||
|
import { NavItem } from './nav-item/nav-item';
|
||||||
|
|
||||||
|
export const navItems: NavItem[] = [
|
||||||
|
{
|
||||||
|
navCap: 'Home',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Dashboard',
|
||||||
|
iconName: 'layout-grid-add',
|
||||||
|
route: '/dashboard',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Analytical',
|
||||||
|
iconName: 'aperture',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/dashboards/dashboard1',
|
||||||
|
chip: true,
|
||||||
|
external: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'eCommerce',
|
||||||
|
iconName: 'shopping-cart',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/dashboards/dashboard2',
|
||||||
|
chip: true,
|
||||||
|
external: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
navCap: 'Apps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Chat',
|
||||||
|
iconName: 'message-dots',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/apps/chat',
|
||||||
|
chip: true,
|
||||||
|
external: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Calendar',
|
||||||
|
iconName: 'calendar',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/apps/calendar',
|
||||||
|
chip: true,
|
||||||
|
external: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Email',
|
||||||
|
iconName: 'mail',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/apps/email/inbox',
|
||||||
|
chip: true,
|
||||||
|
external: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Kanban',
|
||||||
|
iconName: 'checklist',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/apps/kanban',
|
||||||
|
chip: true,
|
||||||
|
external: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Contacts',
|
||||||
|
iconName: 'phone',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/apps/contacts',
|
||||||
|
chip: true,
|
||||||
|
external: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Contact List',
|
||||||
|
iconName: 'list-details',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/apps/contact-list',
|
||||||
|
chip: true,
|
||||||
|
external: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Courses',
|
||||||
|
iconName: 'certificate',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/apps/courses',
|
||||||
|
chip: true,
|
||||||
|
external: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Employee',
|
||||||
|
iconName: 'brand-ctemplar',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/apps/employee',
|
||||||
|
chip: true,
|
||||||
|
external: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Notes',
|
||||||
|
iconName: 'note',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/apps/notes',
|
||||||
|
chip: true,
|
||||||
|
external: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Tickets',
|
||||||
|
iconName: 'ticket',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/apps/tickets',
|
||||||
|
chip: true,
|
||||||
|
external: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'ToDo',
|
||||||
|
iconName: 'edit',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/apps/todo',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Invoice',
|
||||||
|
iconName: 'file-invoice',
|
||||||
|
chip: true,
|
||||||
|
route: '',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
displayName: 'List',
|
||||||
|
iconName: 'point',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
route: '/https://modernize-angular-main.netlify.app/apps/invoice',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Detail',
|
||||||
|
iconName: 'point',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
route:
|
||||||
|
'/https://modernize-angular-main.netlify.app/apps/viewInvoice/101',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Create',
|
||||||
|
iconName: 'point',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
route: '/https://modernize-angular-main.netlify.app/apps/addInvoice',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Edit',
|
||||||
|
iconName: 'point',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
route:
|
||||||
|
'/https://modernize-angular-main.netlify.app/apps/editinvoice/101',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
displayName: 'Blog',
|
||||||
|
iconName: 'chart-donut-3',
|
||||||
|
chip: true,
|
||||||
|
route: 'apps/blog',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
displayName: 'Post',
|
||||||
|
iconName: 'point',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/apps/blog/post',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Detail',
|
||||||
|
iconName: 'point',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
route:
|
||||||
|
'https://modernize-angular-main.netlify.app/apps/blog/detail/Early Black Friday Amazon deals: cheap TVs, headphones, laptops',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
navCap: 'Ui Components',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Badge',
|
||||||
|
iconName: 'archive',
|
||||||
|
route: '/ui-components/badge',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Chips',
|
||||||
|
iconName: 'info-circle',
|
||||||
|
route: '/ui-components/chips',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Lists',
|
||||||
|
iconName: 'list-details',
|
||||||
|
route: '/ui-components/lists',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Menu',
|
||||||
|
iconName: 'file-text',
|
||||||
|
route: '/ui-components/menu',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Tooltips',
|
||||||
|
iconName: 'file-text-ai',
|
||||||
|
route: '/ui-components/tooltips',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Forms',
|
||||||
|
iconName: 'clipboard-text',
|
||||||
|
route: '/ui-components/forms',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Tables',
|
||||||
|
iconName: 'table',
|
||||||
|
route: '/ui-components/tables',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Expansion Panel',
|
||||||
|
iconName: 'layout-bottombar-inactive',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/ui-components/expansion',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Dialog',
|
||||||
|
iconName: 'diabolo',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/ui-components/dialog',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Divider',
|
||||||
|
iconName: 'separator',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/ui-components/divider',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Paginator',
|
||||||
|
iconName: 'text-wrap',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/ui-components/paginator',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Progress Bar',
|
||||||
|
iconName: 'progress',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/ui-components/progress',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Progress Spinner',
|
||||||
|
iconName: 'rotate-2',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/ui-components/progress-spinner',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Ripples',
|
||||||
|
iconName: 'ripple',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/ui-components/ripples',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Slide Toggle',
|
||||||
|
iconName: 'toggle-left',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/ui-components/slide-toggle',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Slider',
|
||||||
|
iconName: 'adjustments-alt',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/ui-components/slider',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Snackbar',
|
||||||
|
iconName: 'stack-backward',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/ui-components/snackbar',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Tabs',
|
||||||
|
iconName: 'border-all',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/ui-components/tabs',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Toolbar',
|
||||||
|
iconName: 'tools-kitchen',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/ui-components/toolbar',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Tooltips',
|
||||||
|
iconName: 'tooltip',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/ui-components/tooltips',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
navCap: 'Pages',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Roll Base Access',
|
||||||
|
iconName: 'lock-access',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/apps/permission',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Treeview',
|
||||||
|
iconName: 'git-merge',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/theme-pages/treeview',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Pricing',
|
||||||
|
iconName: 'currency-dollar',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/theme-pages/pricing',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Account Setting',
|
||||||
|
iconName: 'user-circle',
|
||||||
|
route:
|
||||||
|
'https://modernize-angular-main.netlify.app/theme-pages/account-setting',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'FAQ',
|
||||||
|
iconName: 'help',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/theme-pages/faq',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Landingpage',
|
||||||
|
iconName: 'app-window',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/landingpage',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Widgets',
|
||||||
|
iconName: 'layout',
|
||||||
|
route: 'widgets',
|
||||||
|
chip: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
displayName: 'Cards',
|
||||||
|
iconName: 'point',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/widgets/cards',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Banners',
|
||||||
|
iconName: 'point',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/widgets/banners',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Charts',
|
||||||
|
iconName: 'point',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/widgets/charts',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
navCap: 'Extra',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Icons',
|
||||||
|
iconName: 'mood-smile',
|
||||||
|
route: '/extra/icons',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Sample Page',
|
||||||
|
iconName: 'brand-dribbble',
|
||||||
|
route: '/extra/sample-page',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
navCap: 'Forms',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Elements',
|
||||||
|
iconName: 'apps',
|
||||||
|
chip: true,
|
||||||
|
route: 'forms/forms-elements',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
displayName: 'Autocomplete',
|
||||||
|
iconName: 'point',
|
||||||
|
route:
|
||||||
|
'https://modernize-angular-main.netlify.app/forms/forms-elements/autocomplete',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Button',
|
||||||
|
iconName: 'point',
|
||||||
|
route:
|
||||||
|
'https://modernize-angular-main.netlify.app/forms/forms-elements/button',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Checkbox',
|
||||||
|
iconName: 'point',
|
||||||
|
route:
|
||||||
|
'https://modernize-angular-main.netlify.app/forms/forms-elements/checkbox',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Radio',
|
||||||
|
iconName: 'point',
|
||||||
|
route:
|
||||||
|
'https://modernize-angular-main.netlify.app/forms/forms-elements/radio',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Datepicker',
|
||||||
|
iconName: 'point',
|
||||||
|
route:
|
||||||
|
'https://modernize-angular-main.netlify.app/forms/forms-elements/datepicker',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Form Layouts',
|
||||||
|
iconName: 'file-description',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/forms/form-layouts',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Form Horizontal',
|
||||||
|
iconName: 'box-align-bottom',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/forms/form-horizontal',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Form Vertical',
|
||||||
|
iconName: 'box-align-left',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/forms/form-vertical',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Form Wizard',
|
||||||
|
iconName: 'files',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/forms/form-wizard',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Toastr',
|
||||||
|
iconName: 'notification',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/forms/form-toastr',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
navCap: 'Tables',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Tables',
|
||||||
|
iconName: 'layout',
|
||||||
|
route: 'tables',
|
||||||
|
chip: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
displayName: 'Basic Table',
|
||||||
|
iconName: 'point',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/tables/basic-table',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Dynamic Table',
|
||||||
|
iconName: 'point',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/tables/dynamic-table',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Expand Table',
|
||||||
|
iconName: 'point',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/tables/expand-table',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Filterable Table',
|
||||||
|
iconName: 'point',
|
||||||
|
route:
|
||||||
|
'https://modernize-angular-main.netlify.app/tables/filterable-table',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Footer Row Table',
|
||||||
|
iconName: 'point',
|
||||||
|
route:
|
||||||
|
'https://modernize-angular-main.netlify.app/tables/footer-row-table',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'HTTP Table',
|
||||||
|
iconName: 'point',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/tables/http-table',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Mix Table',
|
||||||
|
iconName: 'point',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/tables/mix-table',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Multi Header Footer',
|
||||||
|
iconName: 'point',
|
||||||
|
route:
|
||||||
|
'https://modernize-angular-main.netlify.app/tables/multi-header-footer-table',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Pagination Table',
|
||||||
|
iconName: 'point',
|
||||||
|
route:
|
||||||
|
'https://modernize-angular-main.netlify.app/tables/pagination-table',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Row Context Table',
|
||||||
|
iconName: 'point',
|
||||||
|
route:
|
||||||
|
'https://modernize-angular-main.netlify.app/tables/row-context-table',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Selection Table',
|
||||||
|
iconName: 'point',
|
||||||
|
route:
|
||||||
|
'https://modernize-angular-main.netlify.app/tables/selection-table',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Sortable Table',
|
||||||
|
iconName: 'point',
|
||||||
|
route:
|
||||||
|
'https://modernize-angular-main.netlify.app/tables/sortable-table',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Sticky Column',
|
||||||
|
iconName: 'point',
|
||||||
|
route:
|
||||||
|
'https://modernize-angular-main.netlify.app/tables/sticky-column-table',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Sticky Header Footer',
|
||||||
|
iconName: 'point',
|
||||||
|
route:
|
||||||
|
'https://modernize-angular-main.netlify.app/tables/sticky-header-footer-table',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Data table',
|
||||||
|
iconName: 'border-outer',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/datatable/kichen-sink',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
navCap: 'Chart',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Line',
|
||||||
|
iconName: 'chart-line',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/charts/line',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Gredient',
|
||||||
|
iconName: 'chart-arcs',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/charts/gredient',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Area',
|
||||||
|
iconName: 'chart-area',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/charts/area',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Candlestick',
|
||||||
|
iconName: 'chart-candle',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/charts/candlestick',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Column',
|
||||||
|
iconName: 'chart-dots',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/charts/column',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Doughnut & Pie',
|
||||||
|
iconName: 'chart-donut-3',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/charts/doughnut-pie',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Radialbar & Radar',
|
||||||
|
iconName: 'chart-radar',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/charts/radial-radar',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
navCap: 'Auth',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Login',
|
||||||
|
iconName: 'login',
|
||||||
|
route: '/authentication',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
displayName: 'Login',
|
||||||
|
iconName: 'point',
|
||||||
|
route: '/authentication/login',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Side Login',
|
||||||
|
iconName: 'point',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/authentication/login',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Register',
|
||||||
|
iconName: 'user-plus',
|
||||||
|
route: '/authentication',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
displayName: 'Register',
|
||||||
|
iconName: 'point',
|
||||||
|
route: '/authentication/register',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Side Register',
|
||||||
|
iconName: 'point',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/authentication/side-register',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Forgot Pwd',
|
||||||
|
iconName: 'rotate',
|
||||||
|
chip: true,
|
||||||
|
route: '/authentication',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
displayName: 'Side Forgot Pwd',
|
||||||
|
iconName: 'point',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/authentication/side-forgot-pwd',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Boxed Forgot Pwd',
|
||||||
|
iconName: 'point',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/authentication/boxed-forgot-pwd',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Two Steps',
|
||||||
|
iconName: 'zoom-code',
|
||||||
|
chip: true,
|
||||||
|
route: '/authentication',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
displayName: 'Side Two Steps',
|
||||||
|
iconName: 'point',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/authentication/side-two-steps',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Boxed Two Steps',
|
||||||
|
iconName: 'point',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app/authentication/boxed-two-steps',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Error',
|
||||||
|
iconName: 'alert-circle',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app//authentication/error',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Maintenance',
|
||||||
|
iconName: 'settings',
|
||||||
|
route: 'https://modernize-angular-main.netlify.app//authentication/maintenance',
|
||||||
|
external: true,
|
||||||
|
chip: true,
|
||||||
|
chipClass: 'bg-light-secondary text-secondary',
|
||||||
|
chipContent: 'PRO',
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<div class="d-flex align-items-center justify-content-between">
|
||||||
|
<div class="branding"><app-branding></app-branding></div>
|
||||||
|
|
||||||
|
@if(showToggle) {
|
||||||
|
<a href="javascript:void(0)" (click)="toggleMobileNav.emit()"
|
||||||
|
class="d-flex justify-content-center ng-star-inserted icon-40 align-items-center">
|
||||||
|
<i-tabler name="x" class="icon-20 d-flex"></i-tabler>
|
||||||
|
</a>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import {
|
||||||
|
Component,
|
||||||
|
EventEmitter,
|
||||||
|
Input,
|
||||||
|
OnInit,
|
||||||
|
Output,
|
||||||
|
ViewChild,
|
||||||
|
} from '@angular/core';
|
||||||
|
import { BrandingComponent } from './branding.component';
|
||||||
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-sidebar',
|
||||||
|
imports: [BrandingComponent, TablerIconsModule, MaterialModule],
|
||||||
|
templateUrl: './sidebar.component.html',
|
||||||
|
})
|
||||||
|
export class SidebarComponent implements OnInit {
|
||||||
|
constructor() {}
|
||||||
|
@Input() showToggle = true;
|
||||||
|
@Output() toggleMobileNav = new EventEmitter<void>();
|
||||||
|
@Output() toggleCollapsed = new EventEmitter<void>();
|
||||||
|
|
||||||
|
ngOnInit(): void {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
<div class="app-topstrip bg-dark text-white p-y-16 p-x-24 w-100 d-flex align-items-center justify-content-between">
|
||||||
|
<div class="d-none d-sm-flex align-items-center justify-content-center gap-20">
|
||||||
|
<a class="d-flex align-items-center" href="https://adminmart.com/" target="_blank">
|
||||||
|
<img src="/assets/images/logos/logo-adminmart.svg" alt="" width="150">
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div class="linkbar d-none d-lg-flex align-items-center justify-content-center gap-16">
|
||||||
|
<!-- Templates -->
|
||||||
|
<a mat-button class="link-hover p-x-0 text-white d-flex" href="https://adminmart.com/templates/angular/"
|
||||||
|
target="_blank">
|
||||||
|
<div class="d-flex align-items-center gap-8 f-s-16 f-w-400">
|
||||||
|
<i class="iconify icon-20 d-flex" data-icon="solar:window-frame-linear"></i>
|
||||||
|
Templates
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<!-- Support -->
|
||||||
|
<a mat-button class="link-hover p-x-0 text-white d-flex" href="https://adminmart.com/support/"
|
||||||
|
target="_blank">
|
||||||
|
<div class="d-flex align-items-center gap-8 f-s-16 f-w-400">
|
||||||
|
<i class="iconify icon-20 d-flex" data-icon="solar:question-circle-linear"></i>
|
||||||
|
Help
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<!-- Hire Us -->
|
||||||
|
<a mat-button class="link-hover p-x-0 text-white d-flex" href="https://adminmart.com/hire-us/"
|
||||||
|
target="_blank">
|
||||||
|
<div class="d-flex align-items-center gap-8 f-s-16 f-w-400">
|
||||||
|
<i class="iconify icon-20 d-flex" data-icon="solar:case-round-linear"></i>
|
||||||
|
Hire Us
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="topstrip-right d-flex align-items-center justify-content-center gap-16">
|
||||||
|
<h6 class="text-linear-gradient f-s-14 text-uppercase text-lg-left text-center">Checkout Pro Version</h6>
|
||||||
|
|
||||||
|
<div class="topstrip-right-inner d-flex justify-content-center align-items-center gap-10">
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center align-items-center gap-10">
|
||||||
|
<!-- Live Preview -->
|
||||||
|
<button class="live-preview-drop d-flex align-items-center gap-4 text-white f-s-16 p-x-16" mat-button
|
||||||
|
[matMenuTriggerFor]="beforeMenu">
|
||||||
|
<div class="d-flex align-items-center gap-6">
|
||||||
|
Live Preview
|
||||||
|
<i class="iconify icon-20 d-flex" data-icon="solar:alt-arrow-down-linear"></i>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<mat-menu class="p-x-16 p-y-8 rounded-7" #beforeMenu="matMenu" xPosition="before">
|
||||||
|
<a mat-menu-item class="rounded-7"
|
||||||
|
href="https://adminmart.com/product/modernize-angular-material-dashboard/?ref=56#product-demo-section"
|
||||||
|
target="_blank">
|
||||||
|
<div class="d-flex align-items-center gap-12 f-s-16">
|
||||||
|
<img src="/assets/images/svgs/angular-cat-icon.svg" width="18" alt="angular">
|
||||||
|
Angular Version
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<a mat-menu-item class="rounded-7"
|
||||||
|
href="https://adminmart.com/product/modernize-react-mui-dashboard-theme/?ref=56#product-demo-section"
|
||||||
|
target="_blank">
|
||||||
|
<div class="d-flex align-items-center gap-12 f-s-16">
|
||||||
|
<img src="/assets/images/svgs/react-cat-icon.svg" width="18" alt="react">
|
||||||
|
React Version
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<a mat-menu-item class="rounded-7"
|
||||||
|
href="https://adminmart.com/product/modernize-vuetify-vue-admin-dashboard/?ref=56#product-demo-section"
|
||||||
|
target="_blank">
|
||||||
|
<div class="d-flex align-items-center gap-12 f-s-16">
|
||||||
|
<img src="/assets/images/svgs/vue-cat-icon.svg" width="18" alt="vueJs">
|
||||||
|
VueJs Version
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<a mat-menu-item class="rounded-7"
|
||||||
|
href="https://adminmart.com/product/modernize-next-js-admin-dashboard/?ref=56#product-demo-section"
|
||||||
|
target="_blank">
|
||||||
|
<div class="d-flex align-items-center gap-12 f-s-16">
|
||||||
|
<img src="/assets/images/svgs/next-cat-icon.svg" width="18" alt="nextJs">
|
||||||
|
NextJs Version
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<a mat-menu-item class="rounded-7"
|
||||||
|
href="https://adminmart.com/product/modernize-nuxt-js-admin-dashboard/?ref=56#product-demo-section"
|
||||||
|
target="_blank">
|
||||||
|
<div class="d-flex align-items-center gap-12 f-s-16">
|
||||||
|
<img src="/assets/images/svgs/nuxt-cat-icon.svg" width="18" alt="nuxtJs">
|
||||||
|
NuxtJs Version
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<a mat-menu-item class="rounded-7"
|
||||||
|
href="https://adminmart.com/product/modernize-tailwind-nextjs-dashboard-template/?ref=56#product-demo-section"
|
||||||
|
target="_blank">
|
||||||
|
<div class="d-flex align-items-center gap-12 f-s-16">
|
||||||
|
<img src="/assets/images/svgs/tailwindcss.svg" width="20" alt="tailwind">
|
||||||
|
Tailwind Version
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<a mat-menu-item class="rounded-7"
|
||||||
|
href="https://adminmart.com/product/modernize-bootstrap-5-admin-template/?ref=56#product-demo-section"
|
||||||
|
target="_blank">
|
||||||
|
<div class="d-flex align-items-center gap-12 f-s-16">
|
||||||
|
<img src="/assets/images/svgs/bt-cat-icon.svg" width="20" alt="bootstrap">
|
||||||
|
Bootstrap Version
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</mat-menu>
|
||||||
|
|
||||||
|
<!-- Get Pro -->
|
||||||
|
<a mat-button class="get-pro-btn text-white p-x-16"
|
||||||
|
href="https://adminmart.com/product/modernize-angular-material-dashboard/?ref=56" target="_blank">
|
||||||
|
<div class="d-flex align-items-center gap-8 f-s-16 f-w-400">
|
||||||
|
<i class="iconify icon-18 d-flex" data-icon="solar:crown-linear"></i>
|
||||||
|
Get Pro
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-topstrip',
|
||||||
|
imports: [TablerIconsModule, MatButtonModule, MatMenuModule],
|
||||||
|
templateUrl: './topstrip.component.html',
|
||||||
|
})
|
||||||
|
export class AppTopstripComponent {
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
85
Web/themes/modernize/src/app/material.module.ts
Normal file
85
Web/themes/modernize/src/app/material.module.ts
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
// Material Form Controls
|
||||||
|
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||||
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||||
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
|
import { MatInputModule } from '@angular/material/input';
|
||||||
|
import { MatRadioModule } from '@angular/material/radio';
|
||||||
|
import { MatSelectModule } from '@angular/material/select';
|
||||||
|
import { MatSliderModule } from '@angular/material/slider';
|
||||||
|
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||||
|
// Material Navigation
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatSidenavModule } from '@angular/material/sidenav';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
|
// Material Layout
|
||||||
|
import { MatCardModule } from '@angular/material/card';
|
||||||
|
import { MatDividerModule } from '@angular/material/divider';
|
||||||
|
import { MatExpansionModule } from '@angular/material/expansion';
|
||||||
|
import { MatGridListModule } from '@angular/material/grid-list';
|
||||||
|
import { MatListModule } from '@angular/material/list';
|
||||||
|
import { MatStepperModule } from '@angular/material/stepper';
|
||||||
|
import { MatTabsModule } from '@angular/material/tabs';
|
||||||
|
import { MatTreeModule } from '@angular/material/tree';
|
||||||
|
// Material Buttons & Indicators
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatButtonToggleModule } from '@angular/material/button-toggle';
|
||||||
|
import { MatBadgeModule } from '@angular/material/badge';
|
||||||
|
import { MatChipsModule } from '@angular/material/chips';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||||
|
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||||
|
import { MatRippleModule } from '@angular/material/core';
|
||||||
|
// Material Popups & Modals
|
||||||
|
import { MatBottomSheetModule } from '@angular/material/bottom-sheet';
|
||||||
|
import { MatDialogModule } from '@angular/material/dialog';
|
||||||
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
|
// Material Data tables
|
||||||
|
import { MatPaginatorModule } from '@angular/material/paginator';
|
||||||
|
import { MatSortModule } from '@angular/material/sort';
|
||||||
|
import { MatTableModule } from '@angular/material/table';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [],
|
||||||
|
exports: [
|
||||||
|
MatAutocompleteModule,
|
||||||
|
MatCheckboxModule,
|
||||||
|
MatDatepickerModule,
|
||||||
|
MatFormFieldModule,
|
||||||
|
MatInputModule,
|
||||||
|
MatRadioModule,
|
||||||
|
MatSelectModule,
|
||||||
|
MatSliderModule,
|
||||||
|
MatSlideToggleModule,
|
||||||
|
MatMenuModule,
|
||||||
|
MatSidenavModule,
|
||||||
|
MatToolbarModule,
|
||||||
|
MatCardModule,
|
||||||
|
MatDividerModule,
|
||||||
|
MatExpansionModule,
|
||||||
|
MatGridListModule,
|
||||||
|
MatListModule,
|
||||||
|
MatStepperModule,
|
||||||
|
MatTabsModule,
|
||||||
|
MatTreeModule,
|
||||||
|
MatButtonModule,
|
||||||
|
MatButtonToggleModule,
|
||||||
|
MatBadgeModule,
|
||||||
|
MatChipsModule,
|
||||||
|
MatIconModule,
|
||||||
|
MatProgressSpinnerModule,
|
||||||
|
MatProgressBarModule,
|
||||||
|
MatRippleModule,
|
||||||
|
MatBottomSheetModule,
|
||||||
|
MatDialogModule,
|
||||||
|
MatSnackBarModule,
|
||||||
|
MatTooltipModule,
|
||||||
|
MatPaginatorModule,
|
||||||
|
MatSortModule,
|
||||||
|
MatTableModule,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class MaterialModule {}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { Routes } from '@angular/router';
|
||||||
|
|
||||||
|
import { AppSideLoginComponent } from './side-login/side-login.component';
|
||||||
|
import { AppSideRegisterComponent } from './side-register/side-register.component';
|
||||||
|
|
||||||
|
export const AuthenticationRoutes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'login',
|
||||||
|
component: AppSideLoginComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'register',
|
||||||
|
component: AppSideRegisterComponent,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<div class="blank-layout-container justify-content-center align-items-center bg-light">
|
||||||
|
<div class="position-relative row w-100 h-100 bg-gredient justify-content-center">
|
||||||
|
<div class="col-lg-4 d-flex align-items-center">
|
||||||
|
<mat-card class="cardWithShadow boxed-auth">
|
||||||
|
<mat-card-content class="p-32">
|
||||||
|
<div class="text-center">
|
||||||
|
<a [routerLink]="['/dashboard']">
|
||||||
|
<img src="./assets/images/logos/dark-logo.svg" class="align-middle m-2" alt="logo" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row m-t-24 custom-row">
|
||||||
|
<div class="col-12 col-sm-6">
|
||||||
|
<button mat-stroked-button class="w-100">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<img src="/assets/images/svgs/google-icon.svg" alt="google" width="16" class="m-r-8" />
|
||||||
|
<span>
|
||||||
|
Sign in with Google
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-sm-6">
|
||||||
|
<button mat-stroked-button class="w-100 d-flex align-items-center">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<img src="/assets/images/svgs/facebook-icon.svg" alt="facebook" width="40" class="m-r-4" />
|
||||||
|
Sign in with FB
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="or-border m-t-30">or sign in with</div>
|
||||||
|
|
||||||
|
<form class="m-t-30">
|
||||||
|
<mat-label class="f-s-14 f-w-600 m-b-12 d-block">Username</mat-label>
|
||||||
|
<mat-form-field appearance="outline" class="w-100" color="primary">
|
||||||
|
<input matInput />
|
||||||
|
</mat-form-field>
|
||||||
|
<!-- password -->
|
||||||
|
<mat-label class="f-s-14 f-w-600 m-b-12 d-block">Password</mat-label>
|
||||||
|
<mat-form-field appearance="outline" class="w-100" color="primary">
|
||||||
|
<input matInput type="password" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<div class="d-flex align-items-center m-b-12">
|
||||||
|
<mat-checkbox color="primary">Remember this Device</mat-checkbox>
|
||||||
|
<a [routerLink]="['/']" class="text-primary f-w-600 text-decoration-none m-l-auto f-s-14">Forgot Password
|
||||||
|
?</a>
|
||||||
|
</div>
|
||||||
|
<a [routerLink]="['/']" mat-flat-button color="primary" class="w-100">
|
||||||
|
Sign In
|
||||||
|
</a>
|
||||||
|
<!-- input -->
|
||||||
|
</form>
|
||||||
|
<span class="d-block f-w-500 text-center m-t-24">New to Modernize?
|
||||||
|
<a [routerLink]="['/authentication/register']" class="text-decoration-none text-primary f-w-500 f-s-14">
|
||||||
|
Create an account</a>
|
||||||
|
</span>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { FormGroup, FormControl, Validators } from '@angular/forms';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { ReactiveFormsModule } from '@angular/forms';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-side-login',
|
||||||
|
imports: [RouterModule, MaterialModule, FormsModule, ReactiveFormsModule],
|
||||||
|
templateUrl: './side-login.component.html',
|
||||||
|
})
|
||||||
|
export class AppSideLoginComponent {
|
||||||
|
|
||||||
|
constructor( private router: Router) {}
|
||||||
|
|
||||||
|
form = new FormGroup({
|
||||||
|
uname: new FormControl('', [Validators.required, Validators.minLength(6)]),
|
||||||
|
password: new FormControl('', [Validators.required]),
|
||||||
|
});
|
||||||
|
|
||||||
|
get f() {
|
||||||
|
return this.form.controls;
|
||||||
|
}
|
||||||
|
|
||||||
|
submit() {
|
||||||
|
// console.log(this.form.value);
|
||||||
|
this.router.navigate(['/']);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
<div class="blank-layout-container justify-content-center align-items-center bg-light">
|
||||||
|
<div class="position-relative row w-100 h-100 bg-gredient justify-content-center">
|
||||||
|
<div class="col-lg-4 d-flex align-items-center">
|
||||||
|
<mat-card class="cardWithShadow boxed-auth">
|
||||||
|
<mat-card-content class="p-32">
|
||||||
|
<div class="text-center">
|
||||||
|
<a [routerLink]="['/dashboard']">
|
||||||
|
<img src="./assets/images/logos/dark-logo.svg" class="align-middle m-2" alt="logo" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row m-t-24 custom-row">
|
||||||
|
<div class="col-12 col-sm-6">
|
||||||
|
<button mat-stroked-button class="w-100">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<img src="/assets/images/svgs/google-icon.svg" alt="google" width="16" class="m-r-8" />
|
||||||
|
Sign in with Google
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 col-sm-6">
|
||||||
|
<button mat-stroked-button class="w-100 d-flex align-items-center">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<img src="/assets/images/svgs/facebook-icon.svg" alt="facebook" width="40" class="m-r-4" />
|
||||||
|
Sign in with FB
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="or-border m-t-30">or sign up with</div>
|
||||||
|
|
||||||
|
<form class="m-t-30">
|
||||||
|
<mat-label class="f-s-14 f-w-600 m-b-12 d-block">Name</mat-label>
|
||||||
|
<mat-form-field appearance="outline" class="w-100" color="primary">
|
||||||
|
<input matInput />
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-label class="f-s-14 f-w-600 m-b-12 d-block">Email Adddress</mat-label>
|
||||||
|
<mat-form-field appearance="outline" class="w-100" color="primary">
|
||||||
|
<input matInput type="email" />
|
||||||
|
</mat-form-field>
|
||||||
|
<!-- password -->
|
||||||
|
<mat-label class="f-s-14 f-w-600 m-b-12 d-block">Password</mat-label>
|
||||||
|
<mat-form-field appearance="outline" class="w-100" color="primary">
|
||||||
|
<input matInput type="password" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<a [routerLink]="['/']" mat-flat-button color="primary" class="w-100">
|
||||||
|
Sign Up
|
||||||
|
</a>
|
||||||
|
<!-- input -->
|
||||||
|
</form>
|
||||||
|
<span class="d-block f-w-500 text-center m-t-24">Already have an Account?
|
||||||
|
|
||||||
|
<a [routerLink]="['/authentication/login']" class="text-decoration-none text-primary f-w-500 f-s-14">
|
||||||
|
Sign In</a>
|
||||||
|
</span>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { CoreService } from 'src/app/services/core.service';
|
||||||
|
import { FormGroup, FormControl, Validators } from '@angular/forms';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-side-register',
|
||||||
|
imports: [RouterModule, MaterialModule, FormsModule, ReactiveFormsModule],
|
||||||
|
templateUrl: './side-register.component.html',
|
||||||
|
})
|
||||||
|
export class AppSideRegisterComponent {
|
||||||
|
options = this.settings.getOptions();
|
||||||
|
|
||||||
|
constructor(private settings: CoreService, private router: Router) {}
|
||||||
|
|
||||||
|
form = new FormGroup({
|
||||||
|
uname: new FormControl('', [Validators.required, Validators.minLength(6)]),
|
||||||
|
email: new FormControl('', [Validators.required]),
|
||||||
|
password: new FormControl('', [Validators.required]),
|
||||||
|
});
|
||||||
|
|
||||||
|
get f() {
|
||||||
|
return this.form.controls;
|
||||||
|
}
|
||||||
|
|
||||||
|
submit() {
|
||||||
|
// console.log(this.form.value);
|
||||||
|
this.router.navigate(['/']);
|
||||||
|
}
|
||||||
|
}
|
||||||
22
Web/themes/modernize/src/app/pages/extra/extra.routes.ts
Normal file
22
Web/themes/modernize/src/app/pages/extra/extra.routes.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { Routes } from '@angular/router';
|
||||||
|
|
||||||
|
|
||||||
|
// pages
|
||||||
|
import { AppIconsComponent } from './icons/icons.component';
|
||||||
|
import { AppSamplePageComponent } from './sample-page/sample-page.component';
|
||||||
|
|
||||||
|
export const ExtraRoutes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'icons',
|
||||||
|
component: AppIconsComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'sample-page',
|
||||||
|
component: AppSamplePageComponent,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<!-- ============================================================== -->
|
||||||
|
<!-- Simple four boxes Row -->
|
||||||
|
<!-- ============================================================== -->
|
||||||
|
<mat-card class="cardWithShadow">
|
||||||
|
<mat-card-content>
|
||||||
|
<mat-card-title>Icons</mat-card-title>
|
||||||
|
<mat-card-subtitle class="m-b-24">Tabler Icons</mat-card-subtitle>
|
||||||
|
<iframe src="https://tabler.io/icons" title="Tabler Icons" width="100%" height="630px"
|
||||||
|
allowfullscreen frameBorder="0">
|
||||||
|
</iframe>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { MaterialModule } from '../../../material.module';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-icons',
|
||||||
|
imports: [MaterialModule],
|
||||||
|
templateUrl: './icons.component.html',
|
||||||
|
})
|
||||||
|
export class AppIconsComponent { }
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<!-- ============================================================== -->
|
||||||
|
<!-- Simple four boxes Row -->
|
||||||
|
<!-- ============================================================== -->
|
||||||
|
<mat-card class="cardWithShadow">
|
||||||
|
<mat-card-content>
|
||||||
|
<mat-card-title>Sample Page</mat-card-title>
|
||||||
|
<mat-card-subtitle>This is test page</mat-card-subtitle>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { MaterialModule } from '../../../material.module';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-sample-page',
|
||||||
|
imports: [MaterialModule],
|
||||||
|
templateUrl: './sample-page.component.html',
|
||||||
|
})
|
||||||
|
|
||||||
|
export class AppSamplePageComponent { }
|
||||||
16
Web/themes/modernize/src/app/pages/pages.routes.ts
Normal file
16
Web/themes/modernize/src/app/pages/pages.routes.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { Routes } from '@angular/router';
|
||||||
|
import { StarterComponent } from './starter/starter.component';
|
||||||
|
|
||||||
|
export const PagesRoutes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: StarterComponent,
|
||||||
|
data: {
|
||||||
|
title: 'Starter Page',
|
||||||
|
urls: [
|
||||||
|
{ title: 'Dashboard', url: '/dashboards/dashboard1' },
|
||||||
|
{ title: 'Starter Page' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-8">
|
||||||
|
<app-sales-overview></app-sales-overview>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<app-yearly-breakup></app-yearly-breakup>
|
||||||
|
<app-monthly-earnings></app-monthly-earnings>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<app-recent-transactions></app-recent-transactions>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-8">
|
||||||
|
<app-product-performance></app-product-performance>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<app-blog-card></app-blog-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { Component, ViewEncapsulation } from '@angular/core';
|
||||||
|
import { MaterialModule } from '../../material.module';
|
||||||
|
import { AppSalesOverviewComponent } from 'src/app/components/sales-overview/sales-overview.component';
|
||||||
|
import { AppYearlyBreakupComponent } from 'src/app/components/yearly-breakup/yearly-breakup.component';
|
||||||
|
import { AppMonthlyEarningsComponent } from 'src/app/components/monthly-earnings/monthly-earnings.component';
|
||||||
|
import { AppRecentTransactionsComponent } from 'src/app/components/recent-transactions/recent-transactions.component';
|
||||||
|
import { AppProductPerformanceComponent } from 'src/app/components/product-performance/product-performance.component';
|
||||||
|
import { AppBlogCardsComponent } from 'src/app/components/blog-card/blog-card.component';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-starter',
|
||||||
|
imports: [
|
||||||
|
MaterialModule,
|
||||||
|
AppSalesOverviewComponent,
|
||||||
|
AppYearlyBreakupComponent,
|
||||||
|
AppMonthlyEarningsComponent,
|
||||||
|
AppRecentTransactionsComponent,
|
||||||
|
AppProductPerformanceComponent,
|
||||||
|
AppBlogCardsComponent
|
||||||
|
],
|
||||||
|
templateUrl: './starter.component.html',
|
||||||
|
encapsulation: ViewEncapsulation.None,
|
||||||
|
})
|
||||||
|
export class StarterComponent { }
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<mat-card class="cardWithShadow theme-card">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title class="m-b-0">Badges</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-content>
|
||||||
|
<div matBadge="4" matBadgeOverlap="false" class="d-inline">Text with a badge</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-content>
|
||||||
|
<div matBadge="1" matBadgeSize="small" class="d-inline">Text with small badge</div><br /><br />
|
||||||
|
<div matBadge="1" matBadgeSize="large" class="d-inline">Text with large badge</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-content>
|
||||||
|
<p class="f-w-500 text-muted">
|
||||||
|
Button with a badge on the left
|
||||||
|
<button mat-flat-button color="primary" matBadge="8" matBadgePosition="before" matBadgeColor="accent">
|
||||||
|
Action
|
||||||
|
</button>
|
||||||
|
</p>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-content>
|
||||||
|
<p class="f-w-500 text-muted">
|
||||||
|
Icon with a badge
|
||||||
|
<mat-icon matBadge="15" matBadgeColor="warn">home</mat-icon>
|
||||||
|
</p>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-content>
|
||||||
|
<p>
|
||||||
|
Button toggles badge visibility
|
||||||
|
<button mat-flat-button color="primary" matBadge="7" [matBadgeHidden]="hidden"
|
||||||
|
(click)="toggleBadgeVisibility()">
|
||||||
|
Hide
|
||||||
|
</button>
|
||||||
|
</p>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatBadgeModule } from '@angular/material/badge';
|
||||||
|
import { MatCardModule } from '@angular/material/card';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-badge',
|
||||||
|
templateUrl: './badge.component.html',
|
||||||
|
imports: [MatBadgeModule, MatButtonModule, MatIconModule, MatCardModule],
|
||||||
|
})
|
||||||
|
export class AppBadgeComponent implements OnInit {
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
ngOnInit(): void {}
|
||||||
|
|
||||||
|
hidden = false;
|
||||||
|
|
||||||
|
toggleBadgeVisibility() {
|
||||||
|
this.hidden = !this.hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,172 @@
|
|||||||
|
<mat-card class="cardWithShadow theme-card">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title class="m-b-0">Chips</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<!-- ------------------------------------------------------------------------- -->
|
||||||
|
<!-- basic -->
|
||||||
|
<!-- ------------------------------------------------------------------------- -->
|
||||||
|
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Basic</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<mat-chip-listbox aria-label="Fish selection">
|
||||||
|
<mat-chip-option class="f-s-14" color="primary">One fish</mat-chip-option>
|
||||||
|
<mat-chip-option class="f-s-14">Two fish</mat-chip-option>
|
||||||
|
<mat-chip-option class="f-s-14" color="accent" selected>Accent fish</mat-chip-option>
|
||||||
|
<mat-chip-option class="f-s-14" color="warn">Warn fish</mat-chip-option>
|
||||||
|
</mat-chip-listbox>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<!-- ------------------------------------------------------------------------- -->
|
||||||
|
<!-- avatar -->
|
||||||
|
<!-- ------------------------------------------------------------------------- -->
|
||||||
|
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Avatar</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<mat-chip-set aria-label="Dog selection">
|
||||||
|
<mat-chip class="f-s-14">
|
||||||
|
<img matChipAvatar src="/assets/images/profile/user-1.jpg" alt="Photo of a Shiba Inu" />
|
||||||
|
Anderson
|
||||||
|
</mat-chip>
|
||||||
|
<mat-chip class="f-s-14" color="primary">
|
||||||
|
<img matChipAvatar src="/assets/images/profile/user-2.jpg" alt="Photo of a Shiba Inu" />
|
||||||
|
Monty
|
||||||
|
</mat-chip>
|
||||||
|
<mat-chip class="f-s-14" color="accent">
|
||||||
|
<img matChipAvatar src="/assets/images/profile/user-3.jpg" alt="Photo of a Shiba Inu" />
|
||||||
|
Mathew
|
||||||
|
</mat-chip>
|
||||||
|
</mat-chip-set>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<!-- ------------------------------------------------------------------------- -->
|
||||||
|
<!-- Drag n Drop -->
|
||||||
|
<!-- ------------------------------------------------------------------------- -->
|
||||||
|
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Drag n Drop</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<mat-chip-set class="example-chip" cdkDropList cdkDropListOrientation="horizontal"
|
||||||
|
(cdkDropListDropped)="drop($event)">
|
||||||
|
@for (vegetable of vegetables(); track vegetable.name) {
|
||||||
|
<mat-chip class="example-box" cdkDrag>{{
|
||||||
|
vegetable.name
|
||||||
|
}}</mat-chip>
|
||||||
|
}
|
||||||
|
</mat-chip-set>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<!-- ------------------------------------------------------------------------- -->
|
||||||
|
<!-- Stacked -->
|
||||||
|
<!-- ------------------------------------------------------------------------- -->
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Stacked </mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<mat-chip-listbox class="mat-mdc-chip-set-stacked" aria-label="Color selection">
|
||||||
|
@for(chip of availableColors; track chip.color) {
|
||||||
|
<mat-chip-option selected [color]="chip.color">
|
||||||
|
{{ chip.name }}
|
||||||
|
</mat-chip-option>
|
||||||
|
}
|
||||||
|
</mat-chip-listbox>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12">
|
||||||
|
<!-- ------------------------------------------------------------------------- -->
|
||||||
|
<!-- Input -->
|
||||||
|
<!-- ------------------------------------------------------------------------- -->
|
||||||
|
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Input</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<mat-form-field appearance="outline" class="w-100">
|
||||||
|
<mat-label>Favorite Fruits</mat-label>
|
||||||
|
<mat-chip-grid #chipGrid aria-label="Enter fruits">
|
||||||
|
@for(fruit of fruits; track fruit.name) {
|
||||||
|
<mat-chip-row (removed)="remove(fruit)" [editable]="true" (edited)="edit(fruit, $event)"
|
||||||
|
[aria-description]="'press enter to edit ' + fruit.name" class="f-s-14">
|
||||||
|
{{ fruit.name }}
|
||||||
|
<button matChipRemove [attr.aria-label]="'remove ' + fruit.name">
|
||||||
|
<mat-icon>cancel</mat-icon>
|
||||||
|
</button>
|
||||||
|
</mat-chip-row>
|
||||||
|
}
|
||||||
|
|
||||||
|
<input placeholder="New fruit..." [matChipInputFor]="chipGrid"
|
||||||
|
[matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="addOnBlur"
|
||||||
|
(matChipInputTokenEnd)="add($event)" />
|
||||||
|
</mat-chip-grid>
|
||||||
|
</mat-form-field>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12">
|
||||||
|
<!-- ------------------------------------------------------------------------- -->
|
||||||
|
<!-- Form Control -->
|
||||||
|
<!-- ------------------------------------------------------------------------- -->
|
||||||
|
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Form Control</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<div class="d-flex gap-8">
|
||||||
|
<button mat-stroked-button color="primary" (click)="formControl.disable()">
|
||||||
|
Disable form control
|
||||||
|
</button>
|
||||||
|
<button mat-raised-button color="primary" (click)="formControl.enable()">
|
||||||
|
Enable form control
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<mat-form-field appearance="outline" class="w-100 m-t-20">
|
||||||
|
<mat-label>Video keywords</mat-label>
|
||||||
|
<mat-chip-grid #formChip aria-label="Enter keywords" [formControl]="formControl">
|
||||||
|
@for (keyword of keywords(); track keyword) {
|
||||||
|
<mat-chip-row (removed)="removeKeyword(keyword)">
|
||||||
|
{{ keyword }}
|
||||||
|
<button matChipRemove aria-label="'remove ' + keyword">
|
||||||
|
<mat-icon>cancel</mat-icon>
|
||||||
|
</button>
|
||||||
|
</mat-chip-row>
|
||||||
|
}
|
||||||
|
</mat-chip-grid>
|
||||||
|
<input placeholder="New keyword..." [matChipInputFor]="formChip"
|
||||||
|
(matChipInputTokenEnd)="addForm($event)" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<span class="f-w-600">The following keywords are entered:</span>
|
||||||
|
{{ formControl.value }}
|
||||||
|
</p>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
.example-box.cdk-drag-animating {
|
||||||
|
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-chip .cdk-drop-list-dragging {
|
||||||
|
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,161 @@
|
|||||||
|
import { COMMA, ENTER } from '@angular/cdk/keycodes';
|
||||||
|
import { ThemePalette } from '@angular/material/core';
|
||||||
|
import {
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
Component,
|
||||||
|
inject,
|
||||||
|
signal,
|
||||||
|
} from '@angular/core';
|
||||||
|
import {
|
||||||
|
CdkDrag,
|
||||||
|
CdkDragDrop,
|
||||||
|
CdkDropList,
|
||||||
|
moveItemInArray,
|
||||||
|
} from '@angular/cdk/drag-drop';
|
||||||
|
import { MatCardModule } from '@angular/material/card';
|
||||||
|
import {
|
||||||
|
MatChipEditedEvent,
|
||||||
|
MatChipInputEvent,
|
||||||
|
MatChipsModule,
|
||||||
|
} from '@angular/material/chips';
|
||||||
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { LiveAnnouncer } from '@angular/cdk/a11y';
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
|
||||||
|
export interface ChipColor {
|
||||||
|
name: string;
|
||||||
|
color: ThemePalette;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Fruit {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Vegetable {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-chips',
|
||||||
|
templateUrl: './chips.component.html',
|
||||||
|
styleUrls: ['./chips.component.scss'],
|
||||||
|
imports: [
|
||||||
|
MatFormFieldModule,
|
||||||
|
MatChipsModule,
|
||||||
|
MatIconModule,
|
||||||
|
MatCardModule,
|
||||||
|
CdkDropList,
|
||||||
|
CdkDrag,
|
||||||
|
FormsModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
MatButtonModule
|
||||||
|
],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class AppChipsComponent {
|
||||||
|
// drag n drop
|
||||||
|
readonly vegetables = signal<Vegetable[]>([
|
||||||
|
{ name: 'apple' },
|
||||||
|
{ name: 'banana' },
|
||||||
|
{ name: 'strawberry' },
|
||||||
|
{ name: 'orange' },
|
||||||
|
{ name: 'kiwi' },
|
||||||
|
{ name: 'cherry' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
drop(event: CdkDragDrop<Vegetable[]>) {
|
||||||
|
this.vegetables.update((vegetables) => {
|
||||||
|
moveItemInArray(vegetables, event.previousIndex, event.currentIndex);
|
||||||
|
return [...vegetables];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Stacked
|
||||||
|
//
|
||||||
|
availableColors: ChipColor[] = [
|
||||||
|
{ name: 'Primary', color: 'primary' },
|
||||||
|
{ name: 'Accent', color: 'accent' },
|
||||||
|
{ name: 'Warn', color: 'warn' },
|
||||||
|
];
|
||||||
|
|
||||||
|
//
|
||||||
|
// chips with input
|
||||||
|
//
|
||||||
|
addOnBlur = true;
|
||||||
|
readonly separatorKeysCodes = [ENTER, COMMA] as const;
|
||||||
|
fruits: Fruit[] = [{ name: 'Lemon' }, { name: 'Lime' }, { name: 'Apple' }];
|
||||||
|
|
||||||
|
add(event: MatChipInputEvent): void {
|
||||||
|
const value = (event.value || '').trim();
|
||||||
|
|
||||||
|
// Add our fruit
|
||||||
|
if (value) {
|
||||||
|
this.fruits.push({ name: value });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the input value
|
||||||
|
event.chipInput!.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(fruit: Fruit): void {
|
||||||
|
const index = this.fruits.indexOf(fruit);
|
||||||
|
|
||||||
|
if (index >= 0) {
|
||||||
|
this.fruits.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
edit(fruit: Fruit, event: MatChipEditedEvent) {
|
||||||
|
const value = event.value.trim();
|
||||||
|
|
||||||
|
// Remove fruit if it no longer has a name
|
||||||
|
if (!value) {
|
||||||
|
this.remove(fruit);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Edit existing fruit
|
||||||
|
const index = this.fruits.indexOf(fruit);
|
||||||
|
if (index >= 0) {
|
||||||
|
this.fruits[index].name = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// form control
|
||||||
|
|
||||||
|
readonly keywords = signal(['angular', 'how-to', 'tutorial', 'accessibility']);
|
||||||
|
readonly formControl = new FormControl(['angular']);
|
||||||
|
|
||||||
|
announcer = inject(LiveAnnouncer);
|
||||||
|
|
||||||
|
removeKeyword(keyword: string) {
|
||||||
|
this.keywords.update(keywords => {
|
||||||
|
const index = keywords.indexOf(keyword);
|
||||||
|
if (index < 0) {
|
||||||
|
return keywords;
|
||||||
|
}
|
||||||
|
|
||||||
|
keywords.splice(index, 1);
|
||||||
|
this.announcer.announce(`removed ${keyword}`);
|
||||||
|
return [...keywords];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addForm(event: MatChipInputEvent): void {
|
||||||
|
const value = (event.value || '').trim();
|
||||||
|
|
||||||
|
// Add our keyword
|
||||||
|
if (value) {
|
||||||
|
this.keywords.update(keywords => [...keywords, value]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the input value
|
||||||
|
event.chipInput!.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function isDragDrop(object: any): object is CdkDragDrop<string[]> {
|
||||||
|
return 'previousIndex' in object;
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
<mat-card class="cardWithShadow theme-card">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title class="m-b-0">Form</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<form>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<!-- input -->
|
||||||
|
<mat-label class="f-w-600 m-b-8 d-block">Your Name</mat-label>
|
||||||
|
<mat-form-field appearance="outline" class="w-100" color="primary">
|
||||||
|
<input matInput placeholder="your name " />
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<mat-label class="f-w-600 m-b-8 d-block">Country</mat-label>
|
||||||
|
<mat-form-field appearance="outline" class="w-100">
|
||||||
|
<mat-select [(value)]="selectedCountry">
|
||||||
|
@for(option of country; track option.value) {
|
||||||
|
<mat-option [value]="option.value">{{
|
||||||
|
option.viewValue
|
||||||
|
}}</mat-option>
|
||||||
|
}
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<!-- input -->
|
||||||
|
<mat-label class="f-w-600 m-b-8 d-block">Email</mat-label>
|
||||||
|
<mat-form-field appearance="outline" class="w-100" color="primary">
|
||||||
|
<input matInput type="email" placeholder="your email" />
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<mat-label class="f-w-600 m-b-8 d-block">State</mat-label>
|
||||||
|
<mat-form-field appearance="outline" class="w-100">
|
||||||
|
<mat-select [(value)]="selectedState">
|
||||||
|
@for(option of state; track option.value) {
|
||||||
|
<mat-option [value]="option.value">{{
|
||||||
|
option.viewValue
|
||||||
|
}}</mat-option>
|
||||||
|
}
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<!-- input -->
|
||||||
|
<mat-label class="f-w-600 m-b-8 d-block">Password</mat-label>
|
||||||
|
<mat-form-field appearance="outline" class="w-100" color="primary">
|
||||||
|
<input matInput type="password" placeholder="your password" />
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<mat-label class="f-w-600 m-b-8 d-block">City</mat-label>
|
||||||
|
<mat-form-field appearance="outline" class="w-100">
|
||||||
|
<mat-select [(value)]="selectedCity">
|
||||||
|
@for(option of city; track option.value) {
|
||||||
|
<mat-option [value]="option.value">{{
|
||||||
|
option.viewValue
|
||||||
|
}}</mat-option>
|
||||||
|
}
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="m-t-12">
|
||||||
|
<button mat-flat-button color="primary" class="m-r-8">Submit</button>
|
||||||
|
<button mat-stroked-button color="warn">Cancel</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatSelectModule } from '@angular/material/select';
|
||||||
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
|
import { MatCardModule } from '@angular/material/card';
|
||||||
|
import { MatInputModule } from '@angular/material/input';
|
||||||
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
import { MatRadioModule } from '@angular/material/radio';
|
||||||
|
|
||||||
|
interface Food {
|
||||||
|
value: string;
|
||||||
|
viewValue: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-forms',
|
||||||
|
imports: [
|
||||||
|
MatFormFieldModule,
|
||||||
|
MatSelectModule,
|
||||||
|
FormsModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
MatRadioModule,
|
||||||
|
MatButtonModule,
|
||||||
|
MatCardModule,
|
||||||
|
MatInputModule,
|
||||||
|
MatCheckboxModule,
|
||||||
|
],
|
||||||
|
templateUrl: './forms.component.html',
|
||||||
|
})
|
||||||
|
export class AppFormsComponent {
|
||||||
|
country: Food[] = [
|
||||||
|
{ value: 'steak-0', viewValue: 'USA' },
|
||||||
|
{ value: 'pizza-1', viewValue: 'India' },
|
||||||
|
{ value: 'tacos-2', viewValue: 'France' },
|
||||||
|
{ value: 'tacos-3', viewValue: 'UK' },
|
||||||
|
];
|
||||||
|
|
||||||
|
selectedCountry = this.country[2].value;
|
||||||
|
|
||||||
|
city: Food[] = [
|
||||||
|
{ value: 'steak-0', viewValue: 'Mexico' },
|
||||||
|
{ value: 'pizza-1', viewValue: 'Mumbai' },
|
||||||
|
{ value: 'tacos-2', viewValue: 'Tokyo' },
|
||||||
|
{ value: 'tacos-3', viewValue: 'New York' },
|
||||||
|
];
|
||||||
|
|
||||||
|
selectedCity = this.city[1].value;
|
||||||
|
|
||||||
|
state: Food[] = [
|
||||||
|
{ value: 'steak-0', viewValue: 'Cuba' },
|
||||||
|
{ value: 'pizza-1', viewValue: 'Djibouti' },
|
||||||
|
{ value: 'tacos-2', viewValue: 'Bulgaria' },
|
||||||
|
{ value: 'tacos-3', viewValue: 'Cabo Verde' },
|
||||||
|
];
|
||||||
|
|
||||||
|
selectedState = this.state[3].value;
|
||||||
|
}
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
<mat-card class="cardWithShadow theme-card">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title class="m-b-0">Lists</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<!-- --------------------------------------------------- -->
|
||||||
|
<!-- basic -->
|
||||||
|
<!-- --------------------------------------------------- -->
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Basic</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<mat-list role="list">
|
||||||
|
<mat-list-item role="listitem">Item 1</mat-list-item>
|
||||||
|
<mat-list-item role="listitem">Item 2</mat-list-item>
|
||||||
|
<mat-list-item role="listitem">Item 3</mat-list-item>
|
||||||
|
</mat-list>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<!-- --------------------------------------------------- -->
|
||||||
|
<!-- two line -->
|
||||||
|
<!-- --------------------------------------------------- -->
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Two Line</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<mat-list>
|
||||||
|
<mat-list-item>
|
||||||
|
<span matListItemTitle class="f-s-16 f-w-600">Title</span>
|
||||||
|
<span matListItemLine>Second line</span>
|
||||||
|
</mat-list-item>
|
||||||
|
<mat-list-item>
|
||||||
|
<span matListItemTitle class="f-s-16 f-w-600">Title</span>
|
||||||
|
<span matListItemLine>Second line</span>
|
||||||
|
</mat-list-item>
|
||||||
|
</mat-list>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<!-- --------------------------------------------------- -->
|
||||||
|
<!-- two line -->
|
||||||
|
<!-- --------------------------------------------------- -->
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Three Line</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<mat-list>
|
||||||
|
<mat-list-item>
|
||||||
|
<span matListItemTitle class="f-s-16 f-w-600">Title</span>
|
||||||
|
<span matListItemLine>Second line</span>
|
||||||
|
<span matListItemLine>Third line</span>
|
||||||
|
</mat-list-item>
|
||||||
|
<mat-list-item>
|
||||||
|
<span matListItemTitle class="f-s-16 f-w-600">Title</span>
|
||||||
|
<span matListItemLine>Second line. This line will truncate.</span>
|
||||||
|
<span>Third line</span>
|
||||||
|
</mat-list-item>
|
||||||
|
</mat-list>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<!-- --------------------------------------------------- -->
|
||||||
|
<!-- two line -->
|
||||||
|
<!-- --------------------------------------------------- -->
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Three Line with Text wrapping</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<mat-list style="max-width: 500px">
|
||||||
|
<mat-list-item lines="3">
|
||||||
|
<span matListItemTitle class="f-s-16 f-w-600">Title</span>
|
||||||
|
<span>Secondary line that will wrap because the list lines is
|
||||||
|
explicitly set to 3 lines. Text inside of a `matListItemTitle`
|
||||||
|
or `matListItemLine` will never wrap.
|
||||||
|
</span>
|
||||||
|
</mat-list-item>
|
||||||
|
<mat-list-item lines="3">
|
||||||
|
<span matListItemTitle class="f-s-16 f-w-600">Title</span>
|
||||||
|
<span>Secondary line that will wrap because the list lines is
|
||||||
|
explicitly set to 3 lines. Text inside of a `matListItemTitle`
|
||||||
|
or `matListItemLine` will never wrap.
|
||||||
|
</span>
|
||||||
|
</mat-list-item>
|
||||||
|
</mat-list>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<!-- --------------------------------------------------- -->
|
||||||
|
<!-- List with Selection -->
|
||||||
|
<!-- --------------------------------------------------- -->
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>List with Selection</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<mat-selection-list #shoes>
|
||||||
|
@for(shoe of typesOfShoes; track shoe) {
|
||||||
|
<mat-list-option>
|
||||||
|
{{ shoe }}
|
||||||
|
</mat-list-option>
|
||||||
|
}
|
||||||
|
</mat-selection-list>
|
||||||
|
|
||||||
|
<p class="f-w-600 p-16 bg-light-primary rounded">
|
||||||
|
Options selected: {{ shoes.selectedOptions.selected.length }}
|
||||||
|
</p>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<!-- --------------------------------------------------- -->
|
||||||
|
<!-- List with single Selection -->
|
||||||
|
<!-- --------------------------------------------------- -->
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>List with single Selection</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<mat-selection-list #shoes2 [multiple]="false">
|
||||||
|
@for(shoe of typesOfShoes; track shoe) {
|
||||||
|
<mat-list-option [value]="shoe">
|
||||||
|
{{ shoe }}
|
||||||
|
</mat-list-option>
|
||||||
|
}
|
||||||
|
</mat-selection-list>
|
||||||
|
|
||||||
|
<p class="f-w-600 p-16 bg-light-primary rounded">
|
||||||
|
Option selected:
|
||||||
|
{{
|
||||||
|
shoes2.selectedOptions.hasValue()
|
||||||
|
? shoes2.selectedOptions.selected[0].value
|
||||||
|
: "None"
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12">
|
||||||
|
<!-- --------------------------------------------------- -->
|
||||||
|
<!-- List with sections -->
|
||||||
|
<!-- --------------------------------------------------- -->
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>List with sections</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<mat-list>
|
||||||
|
<div mat-subheader class="m-b-16 f-w-600">Folders</div>
|
||||||
|
@for(folder of folders; track folder.name) {
|
||||||
|
<mat-list-item>
|
||||||
|
<mat-icon matListItemIcon>folder</mat-icon>
|
||||||
|
<div matListItemTitle class="f-w-600">
|
||||||
|
{{ folder.name }}
|
||||||
|
</div>
|
||||||
|
<div matListItemLine class="f-s-14 ">
|
||||||
|
{{ folder.updated | date }}
|
||||||
|
</div>
|
||||||
|
</mat-list-item>
|
||||||
|
}
|
||||||
|
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
<div mat-subheader class="m-y-16 f-w-600">Notes</div>
|
||||||
|
@for(note of notes; track note.name) {
|
||||||
|
<mat-list-item>
|
||||||
|
<mat-icon matListItemIcon>note</mat-icon>
|
||||||
|
<div matListItemTitle class="f-w-600">
|
||||||
|
{{ note.name }}
|
||||||
|
</div>
|
||||||
|
<div matListItemLine class="f-s-14 ">
|
||||||
|
{{ note.updated | date }}
|
||||||
|
</div>
|
||||||
|
</mat-list-item>
|
||||||
|
}
|
||||||
|
</mat-list>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { MatCardModule } from '@angular/material/card';
|
||||||
|
import { MatListModule } from '@angular/material/list';
|
||||||
|
import {MatIconModule} from '@angular/material/icon';
|
||||||
|
import {DatePipe} from '@angular/common';
|
||||||
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
|
||||||
|
|
||||||
|
export interface Section {
|
||||||
|
name: string;
|
||||||
|
updated: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-lists',
|
||||||
|
imports: [MatListModule, MatCardModule, DatePipe,MatIconModule, MaterialModule ],
|
||||||
|
templateUrl: './lists.component.html',
|
||||||
|
})
|
||||||
|
export class AppListsComponent {
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
typesOfShoes: string[] = ['Loafers', 'Sneakers'];
|
||||||
|
|
||||||
|
folders: Section[] = [
|
||||||
|
{
|
||||||
|
name: 'Photos',
|
||||||
|
updated: new Date('1/1/25'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Recipes',
|
||||||
|
updated: new Date('1/17/25'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Work',
|
||||||
|
updated: new Date('1/28/25'),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
notes: Section[] = [
|
||||||
|
{
|
||||||
|
name: 'Vacation Itinerary',
|
||||||
|
updated: new Date('2/20/25'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Kitchen Remodel',
|
||||||
|
updated: new Date('1/18/25'),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
<mat-card class="cardWithShadow theme-card">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title class="m-b-0">Menu</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6 col-lg-4">
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Basic</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<button mat-flat-button color="primary" class="m-t-8" [matMenuTriggerFor]="menu">
|
||||||
|
Menu
|
||||||
|
</button>
|
||||||
|
<mat-menu #menu="matMenu" class="cardWithShadow">
|
||||||
|
<button mat-menu-item>Item 1</button>
|
||||||
|
<button mat-menu-item>Item 2</button>
|
||||||
|
</mat-menu>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 col-lg-4">
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>with Icons</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<button mat-icon-button [matMenuTriggerFor]="menu" aria-label="Example icon-button with a menu">
|
||||||
|
<mat-icon>
|
||||||
|
<i-tabler name="dots" class="icon-20"></i-tabler>
|
||||||
|
</mat-icon>
|
||||||
|
</button>
|
||||||
|
<mat-menu #menu="matMenu" class="cardWithShadow">
|
||||||
|
<button mat-menu-item>
|
||||||
|
<mat-icon>dialpad</mat-icon>
|
||||||
|
<span>Redial</span>
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item disabled>
|
||||||
|
<mat-icon>voicemail</mat-icon>
|
||||||
|
<span>Check voice mail</span>
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item>
|
||||||
|
<mat-icon>notifications_off</mat-icon>
|
||||||
|
<span>Disable alerts</span>
|
||||||
|
</button>
|
||||||
|
</mat-menu>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 col-lg-4">
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Nested Menu</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<button mat-flat-button color="primary" [matMenuTriggerFor]="animals" class="m-t-8">
|
||||||
|
Animal index
|
||||||
|
</button>
|
||||||
|
<mat-menu class="cardWithShadow" #animals="matMenu">
|
||||||
|
<button mat-menu-item [matMenuTriggerFor]="vertebrates">
|
||||||
|
Vertebrates
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item [matMenuTriggerFor]="invertebrates">
|
||||||
|
Invertebrates
|
||||||
|
</button>
|
||||||
|
</mat-menu>
|
||||||
|
|
||||||
|
<mat-menu class="cardWithShadow" #vertebrates="matMenu">
|
||||||
|
<button mat-menu-item [matMenuTriggerFor]="fish">Fishes</button>
|
||||||
|
<button mat-menu-item [matMenuTriggerFor]="amphibians">
|
||||||
|
Amphibians
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item [matMenuTriggerFor]="reptiles">
|
||||||
|
Reptiles
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item>Birds</button>
|
||||||
|
<button mat-menu-item>Mammals</button>
|
||||||
|
</mat-menu>
|
||||||
|
|
||||||
|
<mat-menu class="cardWithShadow" #invertebrates="matMenu">
|
||||||
|
<button mat-menu-item>Insects</button>
|
||||||
|
<button mat-menu-item>Molluscs</button>
|
||||||
|
<button mat-menu-item>Crustaceans</button>
|
||||||
|
<button mat-menu-item>Corals</button>
|
||||||
|
<button mat-menu-item>Arachnids</button>
|
||||||
|
<button mat-menu-item>Velvet worms</button>
|
||||||
|
<button mat-menu-item>Horseshoe crabs</button>
|
||||||
|
</mat-menu>
|
||||||
|
|
||||||
|
<mat-menu class="cardWithShadow" #fish="matMenu">
|
||||||
|
<button mat-menu-item>Baikal oilfish</button>
|
||||||
|
<button mat-menu-item>Bala shark</button>
|
||||||
|
<button mat-menu-item>Ballan wrasse</button>
|
||||||
|
<button mat-menu-item>Bamboo shark</button>
|
||||||
|
<button mat-menu-item>Banded killifish</button>
|
||||||
|
</mat-menu>
|
||||||
|
|
||||||
|
<mat-menu class="cardWithShadow" #amphibians="matMenu">
|
||||||
|
<button mat-menu-item>Sonoran desert toad</button>
|
||||||
|
<button mat-menu-item>Western toad</button>
|
||||||
|
<button mat-menu-item>Arroyo toad</button>
|
||||||
|
<button mat-menu-item>Yosemite toad</button>
|
||||||
|
</mat-menu>
|
||||||
|
|
||||||
|
<mat-menu class="cardWithShadow" #reptiles="matMenu">
|
||||||
|
<button mat-menu-item>Banded Day Gecko</button>
|
||||||
|
<button mat-menu-item>Banded Gila Monster</button>
|
||||||
|
<button mat-menu-item>Black Tree Monitor</button>
|
||||||
|
<button mat-menu-item>Blue Spiny Lizard</button>
|
||||||
|
<button mat-menu-item disabled>Velociraptor</button>
|
||||||
|
</mat-menu>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12">
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Positions</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<button mat-flat-button color="primary" class="w-100" [matMenuTriggerFor]="aboveMenu">
|
||||||
|
Above
|
||||||
|
</button>
|
||||||
|
<mat-menu class="cardWithShadow" #aboveMenu="matMenu" yPosition="above">
|
||||||
|
<button mat-menu-item>Item 1</button>
|
||||||
|
<button mat-menu-item>Item 2</button>
|
||||||
|
</mat-menu>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<button mat-flat-button color="accent" class="w-100" [matMenuTriggerFor]="belowMenu">
|
||||||
|
Below
|
||||||
|
</button>
|
||||||
|
<mat-menu class="cardWithShadow" #belowMenu="matMenu" yPosition="below">
|
||||||
|
<button mat-menu-item>Item 1</button>
|
||||||
|
<button mat-menu-item>Item 2</button>
|
||||||
|
</mat-menu>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<button mat-flat-button color="warn" class="w-100" [matMenuTriggerFor]="beforeMenu">
|
||||||
|
Before
|
||||||
|
</button>
|
||||||
|
<mat-menu class="cardWithShadow" #beforeMenu="matMenu" xPosition="before">
|
||||||
|
<button mat-menu-item>Item 1</button>
|
||||||
|
<button mat-menu-item>Item 2</button>
|
||||||
|
</mat-menu>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<button mat-flat-button color="primary" class="w-100" [matMenuTriggerFor]="afterMenu">
|
||||||
|
After
|
||||||
|
</button>
|
||||||
|
<mat-menu class="cardWithShadow" #afterMenu="matMenu" xPosition="after">
|
||||||
|
<button mat-menu-item>Item 1</button>
|
||||||
|
<button mat-menu-item>Item 2</button>
|
||||||
|
</mat-menu>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatCardModule } from '@angular/material/card';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-menu',
|
||||||
|
imports: [MatCardModule, MatMenuModule, MatIconModule, TablerIconsModule, MatButtonModule],
|
||||||
|
templateUrl: './menu.component.html',
|
||||||
|
})
|
||||||
|
export class AppMenuComponent {
|
||||||
|
constructor() {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
<mat-card class="cardWithShadow">
|
||||||
|
<mat-card-content>
|
||||||
|
<mat-card-title>Table</mat-card-title>
|
||||||
|
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table mat-table [dataSource]="dataSource1" class="w-100">
|
||||||
|
<!-- Position Column -->
|
||||||
|
<ng-container matColumnDef="assigned">
|
||||||
|
<th mat-header-cell *matHeaderCellDef class="f-w-600 f-s-14 p-l-0">
|
||||||
|
Product
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let element" class="p-l-0">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<img [src]="element.imagePath" alt="users" width="60" class="rounded" />
|
||||||
|
<div class="m-l-16">
|
||||||
|
<h6 class="f-s-14 f-w-600">
|
||||||
|
{{ element.uname }}
|
||||||
|
</h6>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Name Column -->
|
||||||
|
<ng-container matColumnDef="name">
|
||||||
|
<th mat-header-cell *matHeaderCellDef class="f-w-600 f-s-14">
|
||||||
|
Payment
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let element">
|
||||||
|
@if(element.budget >= 160) {
|
||||||
|
<h6 class=" f-s-16 m-b-4">
|
||||||
|
<span class="text-dark f-w-600">${{ element.budget }} </span>/ 499
|
||||||
|
</h6>
|
||||||
|
<span class="f-s-14 f-w-500 d-block m-b-4">Full paid</span>
|
||||||
|
<mat-progress-bar mode="determinate" value="80" color="primary"></mat-progress-bar>
|
||||||
|
} @else if(element.budget > 119) {
|
||||||
|
<h6 class=" f-s-16 m-b-4">
|
||||||
|
<span class="text-dark f-w-600">${{ element.budget }} </span>/ 499
|
||||||
|
</h6>
|
||||||
|
<span class="f-s-14 f-w-500 d-block m-b-4">Partially paid</span>
|
||||||
|
<mat-progress-bar mode="determinate" class="mat-error" value="35" color="accent"></mat-progress-bar>
|
||||||
|
} @else if(element.budget < 100) { <h6 class=" f-s-16 m-b-4">
|
||||||
|
<span class="text-dark f-w-600">${{ element.budget }} </span>/ 499
|
||||||
|
</h6>
|
||||||
|
<span class="f-s-14 f-w-500 d-block m-b-4">Cancelled</span>
|
||||||
|
<mat-progress-bar mode="determinate" class="mat-warning" value="50" color="warn"></mat-progress-bar>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Weight Column -->
|
||||||
|
<ng-container matColumnDef="priority">
|
||||||
|
<th mat-header-cell *matHeaderCellDef class="f-w-600 f-s-14">
|
||||||
|
Status
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let element">
|
||||||
|
@if(element.priority == 'cancelled') {
|
||||||
|
<span class="bg-light-warning text-warning rounded f-w-600 p-6 p-y-4 f-s-12">
|
||||||
|
{{ element.priority | titlecase }}
|
||||||
|
</span>
|
||||||
|
} @if(element.priority == 'rejected') {
|
||||||
|
<span class="bg-light-error text-error rounded f-w-600 p-6 p-y-4 f-s-12">
|
||||||
|
{{ element.priority | titlecase }}
|
||||||
|
</span>
|
||||||
|
} @if(element.priority == 'confirmed') {
|
||||||
|
<span class="bg-light-success text-success rounded f-w-600 p-6 p-y-4 f-s-12">
|
||||||
|
{{ element.priority | titlecase }}
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Symbol Column -->
|
||||||
|
<ng-container matColumnDef="budget">
|
||||||
|
<th mat-header-cell *matHeaderCellDef class="f-w-600 f-s-14"></th>
|
||||||
|
<td mat-cell *matCellDef="let element">
|
||||||
|
<button mat-icon-button [matMenuTriggerFor]="menu" aria-label="Example icon-button with a menu">
|
||||||
|
<mat-icon>more_vert</mat-icon>
|
||||||
|
</button>
|
||||||
|
<mat-menu #menu="matMenu">
|
||||||
|
<button mat-menu-item>
|
||||||
|
<mat-icon>add</mat-icon>
|
||||||
|
<span>Add</span>
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item>
|
||||||
|
<mat-icon>edit</mat-icon>
|
||||||
|
<span>Edit</span>
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item>
|
||||||
|
<mat-icon>delete</mat-icon>
|
||||||
|
<span>Delete</span>
|
||||||
|
</button>
|
||||||
|
</mat-menu>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="displayedColumns1"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: displayedColumns1"></tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { MatCardModule } from '@angular/material/card';
|
||||||
|
import { MatTableModule } from '@angular/material/table';
|
||||||
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
|
||||||
|
// table 1
|
||||||
|
export interface productsData {
|
||||||
|
id: number;
|
||||||
|
imagePath: string;
|
||||||
|
uname: string;
|
||||||
|
budget: number;
|
||||||
|
priority: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PRODUCT_DATA: productsData[] = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
imagePath: 'assets/images/products/product-1.png',
|
||||||
|
uname: 'iPhone 13 pro max-Pacific Blue-128GB storage',
|
||||||
|
budget: 180,
|
||||||
|
priority: 'confirmed',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
imagePath: 'assets/images/products/product-2.png',
|
||||||
|
uname: 'Apple MacBook Pro 13 inch-M1-8/256GB-space',
|
||||||
|
budget: 90,
|
||||||
|
priority: 'cancelled',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
imagePath: 'assets/images/products/product-3.png',
|
||||||
|
uname: 'PlayStation 5 DualSense Wireless Controller',
|
||||||
|
budget: 120,
|
||||||
|
priority: 'rejected',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
imagePath: 'assets/images/products/product-4.png',
|
||||||
|
uname: 'Amazon Basics Mesh, Mid-Back, Swivel Office',
|
||||||
|
budget: 160,
|
||||||
|
priority: 'confirmed',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-tables',
|
||||||
|
imports: [
|
||||||
|
MatTableModule,
|
||||||
|
CommonModule,
|
||||||
|
MatCardModule,
|
||||||
|
MaterialModule,
|
||||||
|
MatIconModule,
|
||||||
|
MatMenuModule,
|
||||||
|
MatButtonModule,
|
||||||
|
],
|
||||||
|
templateUrl: './tables.component.html',
|
||||||
|
})
|
||||||
|
export class AppTablesComponent {
|
||||||
|
// table 1
|
||||||
|
displayedColumns1: string[] = ['assigned', 'name', 'priority', 'budget'];
|
||||||
|
dataSource1 = PRODUCT_DATA;
|
||||||
|
}
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
<mat-card class="cardWithShadow theme-card">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title class="m-b-0">Tooltips</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-4 col-sm-6">
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Basic</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<button mat-flat-button color="primary" matTooltip="Info about the action">
|
||||||
|
Button
|
||||||
|
</button>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4 col-sm-6">
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Uppercase</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<button mat-flat-button color="primary" matTooltip="Info about the action" matTooltipClass="text-uppercase">
|
||||||
|
Button
|
||||||
|
</button>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4 col-sm-6">
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Disabled on click</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<button mat-flat-button color="primary" matTooltip="Info about the action"
|
||||||
|
[matTooltipDisabled]="disabled.value" class="m-r-8">
|
||||||
|
Action
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<mat-checkbox [formControl]="disabled" class="example-disabled-checkbox">
|
||||||
|
Tooltip disabled
|
||||||
|
</mat-checkbox>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Position</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<button mat-flat-button color="primary" #tooltip="matTooltip" matTooltip="Info about the action"
|
||||||
|
matTooltipPosition="below" matTooltipHideDelay="100000">
|
||||||
|
Below
|
||||||
|
</button>
|
||||||
|
<button mat-flat-button color="accent" #tooltip="matTooltip" matTooltip="Info about the action"
|
||||||
|
matTooltipPosition="above" class="m-l-8" matTooltipHideDelay="100000">
|
||||||
|
Above
|
||||||
|
</button>
|
||||||
|
<button mat-flat-button color="warn" #tooltip="matTooltip" matTooltip="Info about the action"
|
||||||
|
matTooltipPosition="left" class="m-l-8" matTooltipHideDelay="100000">
|
||||||
|
Left
|
||||||
|
</button>
|
||||||
|
<button mat-flat-button color="primary" #tooltip="matTooltip" matTooltip="Info about the action"
|
||||||
|
matTooltipPosition="right" class="m-l-8" matTooltipHideDelay="100000">
|
||||||
|
Right
|
||||||
|
</button>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Show and Hide</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<mat-form-field class="w-100" appearance="outline">
|
||||||
|
<mat-label>Show delay</mat-label>
|
||||||
|
<input matInput type="number" [formControl]="showDelay" />
|
||||||
|
<mat-hint>milliseconds</mat-hint>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<mat-form-field class="w-100" appearance="outline">
|
||||||
|
<mat-label>Hide delay</mat-label>
|
||||||
|
<input matInput type="number" [formControl]="hideDelay2" />
|
||||||
|
<mat-hint>milliseconds</mat-hint>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<button mat-flat-button color="primary" matTooltip="Info about the action"
|
||||||
|
[matTooltipShowDelay]="showDelay.value" [matTooltipHideDelay]="hideDelay2.value">
|
||||||
|
Action
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-4 col-sm-6">
|
||||||
|
<mat-card class="b-1 shadow-none">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Change Message</mat-card-title>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content class="b-t-1">
|
||||||
|
<mat-form-field class="w-100" appearance="outline">
|
||||||
|
<mat-label>Tooltip message</mat-label>
|
||||||
|
<input matInput [formControl]="message" />
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<button mat-flat-button color="primary" [matTooltip]="message.value || ''"
|
||||||
|
aria-label="Button that displays a tooltip with a custom message">
|
||||||
|
Action
|
||||||
|
</button>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import {FormControl, FormsModule, ReactiveFormsModule} from '@angular/forms';
|
||||||
|
import {MatTooltipModule} from '@angular/material/tooltip';
|
||||||
|
import {MatButtonModule} from '@angular/material/button';
|
||||||
|
import {MatSelectModule} from '@angular/material/select';
|
||||||
|
import {MatFormFieldModule} from '@angular/material/form-field';
|
||||||
|
import { MatCardModule } from '@angular/material/card';
|
||||||
|
import { MatInputModule } from '@angular/material/input';
|
||||||
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-tooltips',
|
||||||
|
imports: [
|
||||||
|
MatFormFieldModule,
|
||||||
|
MatSelectModule,
|
||||||
|
FormsModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
MatButtonModule,
|
||||||
|
MatTooltipModule, MatCardModule, MatInputModule, MatCheckboxModule
|
||||||
|
],
|
||||||
|
templateUrl: './tooltips.component.html',
|
||||||
|
})
|
||||||
|
export class AppTooltipsComponent {
|
||||||
|
// disabled
|
||||||
|
disabled = new FormControl(false);
|
||||||
|
|
||||||
|
// show and hide
|
||||||
|
showDelay = new FormControl(1000);
|
||||||
|
hideDelay2 = new FormControl(2000);
|
||||||
|
|
||||||
|
// change message
|
||||||
|
message = new FormControl('Info about the action');
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import { Routes } from '@angular/router';
|
||||||
|
|
||||||
|
// ui
|
||||||
|
import { AppBadgeComponent } from './badge/badge.component';
|
||||||
|
import { AppChipsComponent } from './chips/chips.component';
|
||||||
|
import { AppListsComponent } from './lists/lists.component';
|
||||||
|
import { AppMenuComponent } from './menu/menu.component';
|
||||||
|
import { AppTooltipsComponent } from './tooltips/tooltips.component';
|
||||||
|
import { AppFormsComponent } from './forms/forms.component';
|
||||||
|
import { AppTablesComponent } from './tables/tables.component';
|
||||||
|
|
||||||
|
export const UiComponentsRoutes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'badge',
|
||||||
|
component: AppBadgeComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'chips',
|
||||||
|
component: AppChipsComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'lists',
|
||||||
|
component: AppListsComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'menu',
|
||||||
|
component: AppMenuComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'tooltips',
|
||||||
|
component: AppTooltipsComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'forms',
|
||||||
|
component: AppFormsComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'tables',
|
||||||
|
component: AppTablesComponent,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
18
Web/themes/modernize/src/app/pipe/filter.pipe.ts
Normal file
18
Web/themes/modernize/src/app/pipe/filter.pipe.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { Pipe, PipeTransform } from '@angular/core';
|
||||||
|
|
||||||
|
@Pipe({ name: 'appFilter', standalone: true, pure: true })
|
||||||
|
export class FilterPipe implements PipeTransform {
|
||||||
|
transform(items: any[], searchText: string): any[] {
|
||||||
|
if (!items) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
if (!searchText) {
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
searchText = searchText.toLocaleLowerCase();
|
||||||
|
|
||||||
|
return items.filter((it) => {
|
||||||
|
return it.displayName.toLocaleLowerCase().includes(searchText);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
21
Web/themes/modernize/src/app/services/core.service.ts
Normal file
21
Web/themes/modernize/src/app/services/core.service.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { Injectable, signal } from '@angular/core';
|
||||||
|
import { AppSettings, defaults } from '../config';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class CoreService {
|
||||||
|
private optionsSignal = signal<AppSettings>(defaults);
|
||||||
|
|
||||||
|
getOptions() {
|
||||||
|
return this.optionsSignal();
|
||||||
|
}
|
||||||
|
|
||||||
|
setOptions(options: Partial<AppSettings>) {
|
||||||
|
this.optionsSignal.update((current) => ({
|
||||||
|
...current,
|
||||||
|
...options,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
17
Web/themes/modernize/src/app/services/nav.service.ts
Normal file
17
Web/themes/modernize/src/app/services/nav.service.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { Injectable, signal } from '@angular/core';
|
||||||
|
import { Event, NavigationEnd, Router } from '@angular/router';
|
||||||
|
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class NavService {
|
||||||
|
showClass: any = false;
|
||||||
|
|
||||||
|
public currentUrl = signal<string | undefined>(undefined);
|
||||||
|
|
||||||
|
constructor(private router: Router) {
|
||||||
|
this.router.events.subscribe((event: Event) => {
|
||||||
|
if (event instanceof NavigationEnd) {
|
||||||
|
this.currentUrl.set(event.urlAfterRedirects);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
0
Web/themes/modernize/src/assets/.gitkeep
Normal file
0
Web/themes/modernize/src/assets/.gitkeep
Normal file
7
Web/themes/modernize/src/assets/i18n/de.json
Normal file
7
Web/themes/modernize/src/assets/i18n/de.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"Starter": "Menüebene",
|
||||||
|
"Menu Level": "Menüebene",
|
||||||
|
"Menu 1": "Menü 1",
|
||||||
|
"Menu 2": "Menü 2",
|
||||||
|
"Disabled": "Behinderte"
|
||||||
|
}
|
||||||
7
Web/themes/modernize/src/assets/i18n/en.json
Normal file
7
Web/themes/modernize/src/assets/i18n/en.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"Starter": "Starter",
|
||||||
|
"Menu Level": "Menu Level",
|
||||||
|
"Menu 1": "Menu 1",
|
||||||
|
"Menu 2": "Menu 2",
|
||||||
|
"Disabled": "Disabled"
|
||||||
|
}
|
||||||
7
Web/themes/modernize/src/assets/i18n/es.json
Normal file
7
Web/themes/modernize/src/assets/i18n/es.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"Starter": "Analítica",
|
||||||
|
"Menu Level": "Nível do menu",
|
||||||
|
"Menu 1": "Menu 1",
|
||||||
|
"Menu 2": "Menu 2",
|
||||||
|
"Disabled": "Desabilitada"
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user