Refactor HTML and configuration files for improved structure and consistency
- Updated videos.html to enhance readability and maintainability. - Refactored webpack.config.js for better organization and clarity. - Cleaned up TypeScript configuration files (tsconfig.app.json, tsconfig.json, tsconfig.spec.json) for consistency in formatting. - Adjusted docker-compose.yaml for improved formatting and readability.
This commit is contained in:
@@ -1,20 +1,19 @@
|
|||||||
FROM mcr.microsoft.com/devcontainers/dotnet:1-8.0-bookworm
|
FROM mcr.microsoft.com/devcontainers/dotnet:1-8.0-bookworm
|
||||||
|
|
||||||
# Install SQL Tools: SQLPackage and sqlcmd
|
# Install SQL Tools: SQLPackage and sqlcmd
|
||||||
COPY mssql/installSQLtools.sh installSQLtools.sh
|
COPY mssql/installSQLtools.sh installSQLtools.sh
|
||||||
RUN bash ./installSQLtools.sh \
|
RUN bash ./installSQLtools.sh && apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts
|
||||||
&& apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts
|
|
||||||
|
# RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
|
||||||
# RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
|
# echo "deb http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google.list && \
|
||||||
# echo "deb http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google.list && \
|
# apt-get update && apt-get install -y google-chrome-stable xvfb
|
||||||
# apt-get update && apt-get install -y google-chrome-stable xvfb
|
# [Optional] Uncomment this section to install additional OS packages.
|
||||||
# [Optional] Uncomment this section to install additional OS packages.
|
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||||
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
# && apt-get -y install --no-install-recommends <your-package-list-here>
|
||||||
# && apt-get -y install --no-install-recommends <your-package-list-here>
|
|
||||||
|
ENV ASPNETCORE_HTTP_PORTS=5000
|
||||||
ENV ASPNETCORE_HTTP_PORTS=5000
|
|
||||||
|
EXPOSE 4200
|
||||||
EXPOSE 4200
|
# [Optional] Uncomment this line to install global node packages.
|
||||||
# [Optional] Uncomment this line to install global node packages.
|
RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && nvm install --lts && nvm use --lts && npm install -g typescript" 2>&1
|
||||||
RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && nvm install --lts && nvm use --lts && npm install -g typescript" 2>&1
|
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1
|
||||||
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1
|
|
||||||
|
|||||||
@@ -1,59 +1,59 @@
|
|||||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
||||||
// README at: https://github.com/devcontainers/templates/tree/main/src/dotnet-mssql
|
// README at: https://github.com/devcontainers/templates/tree/main/src/dotnet-mssql
|
||||||
{
|
{
|
||||||
"name": ".NET (C#), Node.js (TypeScript) & MS SQL",
|
"name": ".NET (C#), Node.js (TypeScript) & MS SQL",
|
||||||
"dockerComposeFile": "docker-compose.yml",
|
"dockerComposeFile": "docker-compose.yml",
|
||||||
"service": "app",
|
"service": "app",
|
||||||
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
|
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
|
||||||
// Features to add to the dev container. More info: https://containers.dev/features.
|
// Features to add to the dev container. More info: https://containers.dev/features.
|
||||||
// "features": {},
|
// "features": {},
|
||||||
// Configure tool-specific properties.
|
// Configure tool-specific properties.
|
||||||
"customizations": {
|
"customizations": {
|
||||||
// Configure properties specific to VS Code.
|
// Configure properties specific to VS Code.
|
||||||
"vscode": {
|
"vscode": {
|
||||||
// Set *default* container specific settings.json values on container create.
|
// Set *default* container specific settings.json values on container create.
|
||||||
"settings": {
|
"settings": {
|
||||||
"mssql.connections": [
|
"mssql.connections": [
|
||||||
{
|
{
|
||||||
"server": "localhost,1433",
|
"server": "localhost,1433",
|
||||||
"database": "",
|
"database": "",
|
||||||
"authenticationType": "SqlLogin",
|
"authenticationType": "SqlLogin",
|
||||||
"user": "sa",
|
"user": "sa",
|
||||||
"password": "P@ssw0rd",
|
"password": "P@ssw0rd",
|
||||||
"emptyPasswordInput": false,
|
"emptyPasswordInput": false,
|
||||||
"savePassword": false,
|
"savePassword": false,
|
||||||
"profileName": "mssql-container"
|
"profileName": "mssql-container"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
// Add the IDs of extensions you want installed when the container is created.
|
// Add the IDs of extensions you want installed when the container is created.
|
||||||
"extensions": [
|
"extensions": [
|
||||||
"ms-dotnettools.csharp",
|
"ms-dotnettools.csharp",
|
||||||
"ms-mssql.mssql"
|
"ms-mssql.mssql"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||||
"forwardPorts": [
|
"forwardPorts": [
|
||||||
4200,
|
4200,
|
||||||
5000,
|
5000,
|
||||||
5001,
|
5001,
|
||||||
1433
|
1433
|
||||||
],
|
],
|
||||||
"portsAttributes": {
|
"portsAttributes": {
|
||||||
"5001": {
|
"5001": {
|
||||||
"protocol": "https"
|
"protocol": "https"
|
||||||
},
|
},
|
||||||
"1433": {
|
"1433": {
|
||||||
"protocol": "tcp"
|
"protocol": "tcp"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// postCreateCommand.sh parameters: $1=SA password, $2=dacpac path, $3=sql script(s) path
|
// postCreateCommand.sh parameters: $1=SA password, $2=dacpac path, $3=sql script(s) path
|
||||||
"containerEnv": {
|
"containerEnv": {
|
||||||
"SA_PASSWORD": "P@ssw0rd",
|
"SA_PASSWORD": "P@ssw0rd",
|
||||||
"ACCEPT_EULA": "Y"
|
"ACCEPT_EULA": "Y"
|
||||||
},
|
},
|
||||||
"postCreateCommand": "bash .devcontainer/mssql/postCreateCommand.sh 'P@ssw0rd' './bin/Debug/' './.devcontainer/mssql/'"
|
"postCreateCommand": "bash .devcontainer/mssql/postCreateCommand.sh 'P@ssw0rd' './bin/Debug/' './.devcontainer/mssql/'"
|
||||||
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
|
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
|
||||||
// "remoteUser": "root"
|
// "remoteUser": "root"
|
||||||
}
|
}
|
||||||
@@ -1,34 +1,34 @@
|
|||||||
version: '3'
|
version: '3'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
- ../..:/workspaces:cached
|
- ../..:/workspaces:cached
|
||||||
|
|
||||||
# Overrides default command so things don't shut down after the process ends.
|
# Overrides default command so things don't shut down after the process ends.
|
||||||
command: sleep infinity
|
command: sleep infinity
|
||||||
ports:
|
ports:
|
||||||
- "4200:4200"
|
- "4200:4200"
|
||||||
# Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function.
|
# Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function.
|
||||||
network_mode: host
|
network_mode: host
|
||||||
|
|
||||||
# Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
|
# Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
|
||||||
# user: root
|
# user: root
|
||||||
|
|
||||||
# Use "forwardPorts" in **devcontainer.json** to forward an app port locally.
|
# Use "forwardPorts" in **devcontainer.json** to forward an app port locally.
|
||||||
# (Adding the "ports" property to this file will not forward from a Codespace.)
|
# (Adding the "ports" property to this file will not forward from a Codespace.)
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: mcr.microsoft.com/mssql/server:2019-latest
|
image: mcr.microsoft.com/mssql/server:2019-latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
network_mode: host
|
network_mode: host
|
||||||
environment:
|
environment:
|
||||||
SA_PASSWORD: P@ssw0rd
|
SA_PASSWORD: P@ssw0rd
|
||||||
ACCEPT_EULA: Y
|
ACCEPT_EULA: Y
|
||||||
|
|
||||||
# Add "forwardPorts": ["db:1433"] to **devcontainer.json** to forward MSSQL locally.
|
# Add "forwardPorts": ["db:1433"] to **devcontainer.json** to forward MSSQL locally.
|
||||||
# (Adding the "ports" property to this file will not forward from a Codespace.)
|
# (Adding the "ports" property to this file will not forward from a Codespace.)
|
||||||
|
|||||||
64
.devcontainer/mssql/postCreateCommand-backup.sh
Normal file
64
.devcontainer/mssql/postCreateCommand-backup.sh
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
dacpac="false"
|
||||||
|
sqlfiles="false"
|
||||||
|
SApassword=$1
|
||||||
|
dacpath=$2
|
||||||
|
sqlpath=$3
|
||||||
|
|
||||||
|
echo "SELECT * FROM SYS.DATABASES" | dd of=testsqlconnection.sql
|
||||||
|
for i in {1..60};
|
||||||
|
do
|
||||||
|
/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P $SApassword -d master -i testsqlconnection.sql > /dev/null
|
||||||
|
if [ $? -eq 0 ]
|
||||||
|
then
|
||||||
|
echo "SQL server ready"
|
||||||
|
break
|
||||||
|
else
|
||||||
|
echo "Not ready yet..."
|
||||||
|
sleep 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
rm testsqlconnection.sql
|
||||||
|
|
||||||
|
for f in $dacpath/*
|
||||||
|
do
|
||||||
|
if [ $f == $dacpath/*".dacpac" ]
|
||||||
|
then
|
||||||
|
dacpac="true"
|
||||||
|
echo "Found dacpac $f"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
for f in $sqlpath/*
|
||||||
|
do
|
||||||
|
if [ $f == $sqlpath/*".sql" ]
|
||||||
|
then
|
||||||
|
sqlfiles="true"
|
||||||
|
echo "Found SQL file $f"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $sqlfiles == "true" ]
|
||||||
|
then
|
||||||
|
for f in $sqlpath/*
|
||||||
|
do
|
||||||
|
if [ $f == $sqlpath/*".sql" ]
|
||||||
|
then
|
||||||
|
echo "Executing $f"
|
||||||
|
/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P $SApassword -d master -i $f
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $dacpac == "true" ]
|
||||||
|
then
|
||||||
|
for f in $dacpath/*
|
||||||
|
do
|
||||||
|
if [ $f == $dacpath/*".dacpac" ]
|
||||||
|
then
|
||||||
|
dbname=$(basename $f ".dacpac")
|
||||||
|
echo "Deploying dacpac $f"
|
||||||
|
/opt/sqlpackage/sqlpackage /Action:Publish /SourceFile:$f /TargetServerName:localhost /TargetDatabaseName:$dbname /TargetUser:sa /TargetPassword:$SApassword
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
@@ -5,60 +5,9 @@ SApassword=$1
|
|||||||
dacpath=$2
|
dacpath=$2
|
||||||
sqlpath=$3
|
sqlpath=$3
|
||||||
|
|
||||||
echo "SELECT * FROM SYS.DATABASES" | dd of=testsqlconnection.sql
|
cd Api
|
||||||
for i in {1..60};
|
dotnet restore ./Api.csproj
|
||||||
do
|
dotnet build ./Api.csproj
|
||||||
/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P $SApassword -d master -i testsqlconnection.sql > /dev/null
|
dotnet tool install --global dotnet-ef --version 8.*
|
||||||
if [ $? -eq 0 ]
|
export PATH="$PATH:/root/.dotnet/tools"
|
||||||
then
|
dotnet-ef database update --project ./Api.csproj --startup-project ./Api.csproj
|
||||||
echo "SQL server ready"
|
|
||||||
break
|
|
||||||
else
|
|
||||||
echo "Not ready yet..."
|
|
||||||
sleep 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
rm testsqlconnection.sql
|
|
||||||
|
|
||||||
for f in $dacpath/*
|
|
||||||
do
|
|
||||||
if [ $f == $dacpath/*".dacpac" ]
|
|
||||||
then
|
|
||||||
dacpac="true"
|
|
||||||
echo "Found dacpac $f"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
for f in $sqlpath/*
|
|
||||||
do
|
|
||||||
if [ $f == $sqlpath/*".sql" ]
|
|
||||||
then
|
|
||||||
sqlfiles="true"
|
|
||||||
echo "Found SQL file $f"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ $sqlfiles == "true" ]
|
|
||||||
then
|
|
||||||
for f in $sqlpath/*
|
|
||||||
do
|
|
||||||
if [ $f == $sqlpath/*".sql" ]
|
|
||||||
then
|
|
||||||
echo "Executing $f"
|
|
||||||
/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P $SApassword -d master -i $f
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $dacpac == "true" ]
|
|
||||||
then
|
|
||||||
for f in $dacpath/*
|
|
||||||
do
|
|
||||||
if [ $f == $dacpath/*".dacpac" ]
|
|
||||||
then
|
|
||||||
dbname=$(basename $f ".dacpac")
|
|
||||||
echo "Deploying dacpac $f"
|
|
||||||
/opt/sqlpackage/sqlpackage /Action:Publish /SourceFile:$f /TargetServerName:localhost /TargetDatabaseName:$dbname /TargetUser:sa /TargetPassword:$SApassword
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
CREATE DATABASE ApplicationDB;
|
|
||||||
GO
|
|
||||||
24
.github/dependabot.yml
vendored
24
.github/dependabot.yml
vendored
@@ -1,12 +1,12 @@
|
|||||||
# To get started with Dependabot version updates, you'll need to specify which
|
# To get started with Dependabot version updates, you'll need to specify which
|
||||||
# package ecosystems to update and where the package manifests are located.
|
# package ecosystems to update and where the package manifests are located.
|
||||||
# Please see the documentation for more information:
|
# Please see the documentation for more information:
|
||||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||||
# https://containers.dev/guide/dependabot
|
# https://containers.dev/guide/dependabot
|
||||||
|
|
||||||
version: 2
|
version: 2
|
||||||
updates:
|
updates:
|
||||||
- package-ecosystem: "devcontainers"
|
- package-ecosystem: "devcontainers"
|
||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: weekly
|
interval: weekly
|
||||||
|
|||||||
156
.gitlab-ci.yml
156
.gitlab-ci.yml
@@ -1,78 +1,78 @@
|
|||||||
|
|
||||||
stages: # Define the stages of the pipeline.
|
stages: # Define the stages of the pipeline.
|
||||||
- build
|
- build
|
||||||
#- test
|
#- test
|
||||||
- release
|
- release
|
||||||
|
|
||||||
semantic-release:
|
semantic-release:
|
||||||
image: node:24
|
image: node:24
|
||||||
stage: release
|
stage: release
|
||||||
script:
|
script:
|
||||||
- apt update && apt install zip -y
|
- apt update && apt install zip -y
|
||||||
- zip -r dist.zip Web/dist/Web/browser
|
- zip -r dist.zip Web/dist/Web/browser
|
||||||
- zip -r api.zip Api/build
|
- 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:
|
||||||
- main
|
- main
|
||||||
|
|
||||||
docker-build:
|
docker-build:
|
||||||
stage: build
|
stage: build
|
||||||
image: docker:latest
|
image: docker:latest
|
||||||
tags:
|
tags:
|
||||||
- shared
|
- shared
|
||||||
services:
|
services:
|
||||||
- name: docker:dind
|
- name: docker:dind
|
||||||
alias: docker
|
alias: docker
|
||||||
variables:
|
variables:
|
||||||
DOCKER_DRIVER: overlay2
|
DOCKER_DRIVER: overlay2
|
||||||
DOCKER_HOST: tcp://docker:2375
|
DOCKER_HOST: tcp://docker:2375
|
||||||
DOCKER_TLS_CERTDIR: ""
|
DOCKER_TLS_CERTDIR: ""
|
||||||
before_script:
|
before_script:
|
||||||
- docker info
|
- docker info
|
||||||
script:
|
script:
|
||||||
- 'sed -i "s|\"apiEndpoint\": \"[^\"]*\"|\"apiEndpoint\": \"https\:\/\/""$PUBLIC_WEB_URL""\"|" Web/public/config.json'
|
- 'sed -i "s|\"apiEndpoint\": \"[^\"]*\"|\"apiEndpoint\": \"https\:\/\/""$PUBLIC_WEB_URL""\"|" Web/public/config.json'
|
||||||
- 'sed -i "s|\"AllowedHosts\": \"[^\"]*\"|\"AllowedHosts\": \"$PUBLIC_WEB_URL\"|" Api/appsettings.json'
|
- 'sed -i "s|\"AllowedHosts\": \"[^\"]*\"|\"AllowedHosts\": \"$PUBLIC_WEB_URL\"|" Api/appsettings.json'
|
||||||
- 'sed -i "s|\"CorsOrigins\": \"[^\"]*\"|\"CorsOrigins\": \"https\:\/\/""$PUBLIC_WEB_URL""\"|" Api/appsettings.json'
|
- 'sed -i "s|\"CorsOrigins\": \"[^\"]*\"|\"CorsOrigins\": \"https\:\/\/""$PUBLIC_WEB_URL""\"|" Api/appsettings.json'
|
||||||
- docker build -t $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:${CI_PIPELINE_IID} -f Dockerfile .
|
- docker build -t $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:${CI_PIPELINE_IID} -f Dockerfile .
|
||||||
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
|
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
|
||||||
- docker push $CI_REGISTRY_IMAGE:latest
|
- docker push $CI_REGISTRY_IMAGE:latest
|
||||||
- docker push $CI_REGISTRY_IMAGE:${CI_PIPELINE_IID}
|
- docker push $CI_REGISTRY_IMAGE:${CI_PIPELINE_IID}
|
||||||
only:
|
only:
|
||||||
- dev
|
- dev
|
||||||
- main
|
- main
|
||||||
|
|
||||||
docker-deploy:
|
docker-deploy:
|
||||||
stage: release
|
stage: release
|
||||||
tags:
|
tags:
|
||||||
- production
|
- production
|
||||||
- shell
|
- shell
|
||||||
script:
|
script:
|
||||||
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
|
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
|
||||||
- cd deployment
|
- cd deployment
|
||||||
- docker compose pull
|
- docker compose pull
|
||||||
- docker compose -f docker-compose.yaml up -d
|
- docker compose -f docker-compose.yaml up -d
|
||||||
- docker image prune -f
|
- docker image prune -f
|
||||||
only:
|
only:
|
||||||
- dev
|
- dev
|
||||||
- main
|
- main
|
||||||
|
|
||||||
update_db:
|
update_db:
|
||||||
image: mcr.microsoft.com/dotnet/sdk:8.0
|
image: mcr.microsoft.com/dotnet/sdk:8.0
|
||||||
stage: release
|
stage: release
|
||||||
needs: ["docker-deploy"]
|
needs: ["docker-deploy"]
|
||||||
script:
|
script:
|
||||||
- cd Api
|
- cd Api
|
||||||
- dotnet restore ./Api.csproj
|
- dotnet restore ./Api.csproj
|
||||||
- dotnet build ./Api.csproj
|
- dotnet build ./Api.csproj
|
||||||
- dotnet tool install --global dotnet-ef --version 8.*
|
- dotnet tool install --global dotnet-ef --version 8.*
|
||||||
- export PATH="$PATH:/root/.dotnet/tools"
|
- export PATH="$PATH:/root/.dotnet/tools"
|
||||||
- dotnet-ef database update --project ./Api.csproj --startup-project ./Api.csproj
|
- dotnet-ef database update --project ./Api.csproj --startup-project ./Api.csproj
|
||||||
only:
|
only:
|
||||||
- dev
|
- dev
|
||||||
- main
|
- main
|
||||||
tags:
|
tags:
|
||||||
- production
|
- production
|
||||||
- docker
|
- docker
|
||||||
variables:
|
variables:
|
||||||
ConnectionStrings__DefaultConnection: "Server=localhost;Database=CentrumDb;User=sa;Password=$DB_PASSWORD;TrustServerCertificate=True;"
|
ConnectionStrings__DefaultConnection: "Server=localhost;Database=CentrumDb;User=sa;Password=$DB_PASSWORD;TrustServerCertificate=True;"
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
coreDump:
|
coreDump:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|||||||
@@ -1,37 +1,37 @@
|
|||||||
tasks:
|
tasks:
|
||||||
hello:
|
hello:
|
||||||
name: Hello World
|
name: Hello World
|
||||||
command: |
|
command: |
|
||||||
echo "Hello, World!"
|
echo "Hello, World!"
|
||||||
triggeredBy:
|
triggeredBy:
|
||||||
- manual
|
- manual
|
||||||
# - postEnvironmentStart
|
# - postEnvironmentStart
|
||||||
# - postDevcontainerStart
|
# - postDevcontainerStart
|
||||||
|
|
||||||
services:
|
services:
|
||||||
example-service:
|
example-service:
|
||||||
name: Example Service
|
name: Example Service
|
||||||
description: Example service simulating a backend
|
description: Example service simulating a backend
|
||||||
commands:
|
commands:
|
||||||
start: |
|
start: |
|
||||||
echo "Starting backend service..."
|
echo "Starting backend service..."
|
||||||
touch /tmp/backend.started
|
touch /tmp/backend.started
|
||||||
while true; do
|
while true; do
|
||||||
sleep 1
|
sleep 1
|
||||||
date
|
date
|
||||||
done
|
done
|
||||||
ready: |
|
ready: |
|
||||||
if [ -f /tmp/backend.started ]; then
|
if [ -f /tmp/backend.started ]; then
|
||||||
echo "Backend service is ready"
|
echo "Backend service is ready"
|
||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
echo "Backend service is not ready"
|
echo "Backend service is not ready"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
# stop: |
|
# stop: |
|
||||||
# echo "Stopping backend service..."
|
# echo "Stopping backend service..."
|
||||||
# rm /tmp/backend.started
|
# rm /tmp/backend.started
|
||||||
# pkill backend
|
# pkill backend
|
||||||
triggeredBy:
|
triggeredBy:
|
||||||
- postEnvironmentStart
|
- postEnvironmentStart
|
||||||
# - postDevcontainerStart
|
# - postDevcontainerStart
|
||||||
|
|||||||
28
.vscode/launch.json
vendored
28
.vscode/launch.json
vendored
@@ -1,15 +1,15 @@
|
|||||||
{
|
{
|
||||||
// Use IntelliSense to learn about possible attributes.
|
// Use IntelliSense to learn about possible attributes.
|
||||||
// Hover to view descriptions of existing attributes.
|
// Hover to view descriptions of existing attributes.
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"type": "chrome",
|
"type": "chrome",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Launch Chrome against localhost",
|
"name": "Launch Chrome against localhost",
|
||||||
"url": "http://localhost:4200",
|
"url": "http://localhost:4200",
|
||||||
"webRoot": "${workspaceFolder}/Web"
|
"webRoot": "${workspaceFolder}/Web"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
80
.vscode/tasks.json
vendored
80
.vscode/tasks.json
vendored
@@ -1,41 +1,41 @@
|
|||||||
{
|
{
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
"label": "build",
|
"label": "build",
|
||||||
"command": "dotnet",
|
"command": "dotnet",
|
||||||
"type": "process",
|
"type": "process",
|
||||||
"args": [
|
"args": [
|
||||||
"build",
|
"build",
|
||||||
"${workspaceFolder}/Api/Api.sln",
|
"${workspaceFolder}/Api/Api.sln",
|
||||||
"/property:GenerateFullPaths=true",
|
"/property:GenerateFullPaths=true",
|
||||||
"/consoleloggerparameters:NoSummary;ForceNoAlign"
|
"/consoleloggerparameters:NoSummary;ForceNoAlign"
|
||||||
],
|
],
|
||||||
"problemMatcher": "$msCompile"
|
"problemMatcher": "$msCompile"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "publish",
|
"label": "publish",
|
||||||
"command": "dotnet",
|
"command": "dotnet",
|
||||||
"type": "process",
|
"type": "process",
|
||||||
"args": [
|
"args": [
|
||||||
"publish",
|
"publish",
|
||||||
"${workspaceFolder}/Api/Api.sln",
|
"${workspaceFolder}/Api/Api.sln",
|
||||||
"/property:GenerateFullPaths=true",
|
"/property:GenerateFullPaths=true",
|
||||||
"/consoleloggerparameters:NoSummary;ForceNoAlign"
|
"/consoleloggerparameters:NoSummary;ForceNoAlign"
|
||||||
],
|
],
|
||||||
"problemMatcher": "$msCompile"
|
"problemMatcher": "$msCompile"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "watch",
|
"label": "watch",
|
||||||
"command": "dotnet",
|
"command": "dotnet",
|
||||||
"type": "process",
|
"type": "process",
|
||||||
"args": [
|
"args": [
|
||||||
"watch",
|
"watch",
|
||||||
"run",
|
"run",
|
||||||
"--project",
|
"--project",
|
||||||
"${workspaceFolder}/Api/Api.sln"
|
"${workspaceFolder}/Api/Api.sln"
|
||||||
],
|
],
|
||||||
"problemMatcher": "$msCompile"
|
"problemMatcher": "$msCompile"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
8
Api/.gitignore
vendored
8
Api/.gitignore
vendored
@@ -1,5 +1,5 @@
|
|||||||
obj/
|
obj/
|
||||||
bin/
|
bin/
|
||||||
.vs/
|
.vs/
|
||||||
build/
|
build/
|
||||||
**/core
|
**/core
|
||||||
@@ -1,70 +1,70 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Api.Models;
|
using Api.Models;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
||||||
namespace Api.Controllers
|
namespace Api.Controllers
|
||||||
{
|
{
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[Route("api/product")]
|
[Route("api/product")]
|
||||||
public class ProductController : ControllerBase
|
public class ProductController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly AppDbContext _context;
|
private readonly AppDbContext _context;
|
||||||
|
|
||||||
public ProductController(AppDbContext context)
|
public ProductController(AppDbContext context)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET: api/Product
|
// GET: api/Product
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public async Task<ActionResult<IEnumerable<Product>>> GetProducts([FromQuery] int? id = null)
|
public async Task<ActionResult<IEnumerable<Product>>> GetProducts([FromQuery] int? id = null)
|
||||||
{
|
{
|
||||||
if (id.HasValue)
|
if (id.HasValue)
|
||||||
{
|
{
|
||||||
return await _context.Products
|
return await _context.Products
|
||||||
.Where(p => p.Id == id.Value)
|
.Where(p => p.Id == id.Value)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return await _context.Products.ToListAsync();
|
return await _context.Products.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
// POST: api/Product
|
// POST: api/Product
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<ActionResult<Product>> PostProduct([FromBody] Product product)
|
public async Task<ActionResult<Product>> PostProduct([FromBody] Product product)
|
||||||
{
|
{
|
||||||
_context.Products.Add(product);
|
_context.Products.Add(product);
|
||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
return CreatedAtAction(nameof(GetProducts), new { id = product.Id }, product);
|
return CreatedAtAction(nameof(GetProducts), new { id = product.Id }, product);
|
||||||
}
|
}
|
||||||
|
|
||||||
// PUT: api/Product/{id}
|
// PUT: api/Product/{id}
|
||||||
[HttpPut("{id}")]
|
[HttpPut("{id}")]
|
||||||
public async Task<IActionResult> PutProduct(int id, [FromBody] Product product)
|
public async Task<IActionResult> PutProduct(int id, [FromBody] Product product)
|
||||||
{
|
{
|
||||||
if (id != product.Id)
|
if (id != product.Id)
|
||||||
{
|
{
|
||||||
return BadRequest();
|
return BadRequest();
|
||||||
}
|
}
|
||||||
_context.Entry(product).State = EntityState.Modified;
|
_context.Entry(product).State = EntityState.Modified;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
catch (DbUpdateConcurrencyException)
|
catch (DbUpdateConcurrencyException)
|
||||||
{
|
{
|
||||||
if (!await _context.Products.AnyAsync(e => e.Id == id))
|
if (!await _context.Products.AnyAsync(e => e.Id == id))
|
||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
112
Api/Migrations/20250727154636_InitialCreate.Designer.cs
generated
112
Api/Migrations/20250727154636_InitialCreate.Designer.cs
generated
@@ -1,56 +1,56 @@
|
|||||||
// <auto-generated />
|
// <auto-generated />
|
||||||
using Api.Models;
|
using Api.Models;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
using Microsoft.EntityFrameworkCore.Metadata;
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
namespace Api.Migrations
|
namespace Api.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(AppDbContext))]
|
[DbContext(typeof(AppDbContext))]
|
||||||
[Migration("20250727154636_InitialCreate")]
|
[Migration("20250727154636_InitialCreate")]
|
||||||
partial class InitialCreate
|
partial class InitialCreate
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.HasAnnotation("ProductVersion", "9.0.7")
|
.HasAnnotation("ProductVersion", "9.0.7")
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||||
|
|
||||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||||
|
|
||||||
modelBuilder.Entity("Api.Models.Product", b =>
|
modelBuilder.Entity("Api.Models.Product", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("int");
|
.HasColumnType("int");
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
b.Property<string>("Name")
|
b.Property<string>("Name")
|
||||||
.HasColumnType("nvarchar(max)");
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
b.Property<decimal>("Price")
|
b.Property<decimal>("Price")
|
||||||
.HasColumnType("decimal(18,2)");
|
.HasColumnType("decimal(18,2)");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.ToTable("Products");
|
b.ToTable("Products");
|
||||||
|
|
||||||
b.HasData(
|
b.HasData(
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = 1,
|
Id = 1,
|
||||||
Name = "Sample Product",
|
Name = "Sample Product",
|
||||||
Price = 9.99m
|
Price = 9.99m
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
#pragma warning restore 612, 618
|
#pragma warning restore 612, 618
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,40 @@
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
namespace Api.Migrations
|
namespace Api.Migrations
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public partial class InitialCreate : Migration
|
public partial class InitialCreate : Migration
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
{
|
{
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "Products",
|
name: "Products",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
Id = table.Column<int>(type: "int", nullable: false)
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
.Annotation("SqlServer:Identity", "1, 1"),
|
.Annotation("SqlServer:Identity", "1, 1"),
|
||||||
Name = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
Name = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
Price = table.Column<decimal>(type: "decimal(18,2)", nullable: false)
|
Price = table.Column<decimal>(type: "decimal(18,2)", nullable: false)
|
||||||
},
|
},
|
||||||
constraints: table =>
|
constraints: table =>
|
||||||
{
|
{
|
||||||
table.PrimaryKey("PK_Products", x => x.Id);
|
table.PrimaryKey("PK_Products", x => x.Id);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.InsertData(
|
migrationBuilder.InsertData(
|
||||||
table: "Products",
|
table: "Products",
|
||||||
columns: new[] { "Id", "Name", "Price" },
|
columns: new[] { "Id", "Name", "Price" },
|
||||||
values: new object[] { 1, "Sample Product", 9.99m });
|
values: new object[] { 1, "Sample Product", 9.99m });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
{
|
{
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "Products");
|
name: "Products");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,53 +1,53 @@
|
|||||||
// <auto-generated />
|
// <auto-generated />
|
||||||
using Api.Models;
|
using Api.Models;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
using Microsoft.EntityFrameworkCore.Metadata;
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
namespace Api.Migrations
|
namespace Api.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(AppDbContext))]
|
[DbContext(typeof(AppDbContext))]
|
||||||
partial class AppDbContextModelSnapshot : ModelSnapshot
|
partial class AppDbContextModelSnapshot : ModelSnapshot
|
||||||
{
|
{
|
||||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.HasAnnotation("ProductVersion", "9.0.7")
|
.HasAnnotation("ProductVersion", "9.0.7")
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||||
|
|
||||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||||
|
|
||||||
modelBuilder.Entity("Api.Models.Product", b =>
|
modelBuilder.Entity("Api.Models.Product", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("int");
|
.HasColumnType("int");
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
b.Property<string>("Name")
|
b.Property<string>("Name")
|
||||||
.HasColumnType("nvarchar(max)");
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
b.Property<decimal>("Price")
|
b.Property<decimal>("Price")
|
||||||
.HasColumnType("decimal(18,2)");
|
.HasColumnType("decimal(18,2)");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.ToTable("Products");
|
b.ToTable("Products");
|
||||||
|
|
||||||
b.HasData(
|
b.HasData(
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = 1,
|
Id = 1,
|
||||||
Name = "Sample Product",
|
Name = "Sample Product",
|
||||||
Price = 9.99m
|
Price = 9.99m
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
#pragma warning restore 612, 618
|
#pragma warning restore 612, 618
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Api.Models
|
namespace Api.Models
|
||||||
{
|
{
|
||||||
public class Product
|
public class Product
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
public decimal Price { get; set; }
|
public decimal Price { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AppDbContext : DbContext
|
public class AppDbContext : DbContext
|
||||||
{
|
{
|
||||||
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
|
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
|
||||||
public DbSet<Product> Products { get; set; }
|
public DbSet<Product> Products { get; set; }
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
base.OnModelCreating(modelBuilder);
|
base.OnModelCreating(modelBuilder);
|
||||||
// Seed data
|
// Seed data
|
||||||
modelBuilder.Entity<Product>().HasData(
|
modelBuilder.Entity<Product>().HasData(
|
||||||
new Product { Id = 1, Name = "Sample Product", Price = 9.99M }
|
new Product { Id = 1, Name = "Sample Product", Price = 9.99M }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ namespace Api
|
|||||||
.AddRewrite(@$"^(?!.*?\b({rewriteString}))^(?!.*?\.\b(jpg|jpeg|png|svg|ttf|woff|woff2|html|js|json|css|ico))", "index.html", false);
|
.AddRewrite(@$"^(?!.*?\b({rewriteString}))^(?!.*?\.\b(jpg|jpeg|png|svg|ttf|woff|woff2|html|js|json|css|ico))", "index.html", false);
|
||||||
app.UseRewriter(rewriteOptions);
|
app.UseRewriter(rewriteOptions);
|
||||||
|
|
||||||
|
// Serve static files from the Angular app
|
||||||
if (app.Environment.IsDevelopment())
|
if (app.Environment.IsDevelopment())
|
||||||
{
|
{
|
||||||
var currentDirectory = Directory.GetCurrentDirectory();
|
var currentDirectory = Directory.GetCurrentDirectory();
|
||||||
|
|||||||
46
Dockerfile
46
Dockerfile
@@ -1,24 +1,24 @@
|
|||||||
# Build Angular Web app
|
# Build Angular Web app
|
||||||
FROM node:24 AS web-build
|
FROM node:24 AS web-build
|
||||||
WORKDIR /app/web
|
WORKDIR /app/web
|
||||||
COPY Web/package*.json ./
|
COPY Web/package*.json ./
|
||||||
RUN npm install
|
RUN npm install
|
||||||
COPY Web/ ./
|
COPY Web/ ./
|
||||||
RUN npm run build -- --output-path=dist/Web/browser
|
RUN npm run build -- --output-path=dist/Web/browser
|
||||||
|
|
||||||
# Build .NET Api app
|
# Build .NET Api app
|
||||||
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS api-build
|
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS api-build
|
||||||
WORKDIR /app/api
|
WORKDIR /app/api
|
||||||
COPY Api/*.csproj ./
|
COPY Api/*.csproj ./
|
||||||
RUN dotnet restore
|
RUN dotnet restore
|
||||||
COPY Api/ ./
|
COPY Api/ ./
|
||||||
RUN dotnet publish Api.csproj -c Release -o /app/api/build
|
RUN dotnet publish Api.csproj -c Release -o /app/api/build
|
||||||
|
|
||||||
# Final runtime image
|
# Final runtime image
|
||||||
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final
|
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=api-build /app/api/build ./
|
COPY --from=api-build /app/api/build ./
|
||||||
COPY --from=web-build /app/web/dist/Web/browser/**/* ./wwwroot/
|
COPY --from=web-build /app/web/dist/Web/browser/**/* ./wwwroot/
|
||||||
ENV ASPNETCORE_URLS=http://+:5000
|
ENV ASPNETCORE_URLS=http://+:5000
|
||||||
EXPOSE 5000
|
EXPOSE 5000
|
||||||
ENTRYPOINT ["dotnet", "Api.dll"]
|
ENTRYPOINT ["dotnet", "Api.dll"]
|
||||||
186
README.md
186
README.md
@@ -1,93 +1,93 @@
|
|||||||
# Centrum
|
# Centrum
|
||||||
|
|
||||||

|

|
||||||
[](https://gitlab.lesko.me/marek/centrum/-/commits/main)
|
[](https://gitlab.lesko.me/marek/centrum/-/commits/main)
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
|
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
|
||||||
|
|
||||||
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
|
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
|
||||||
|
|
||||||
## Add your files
|
## Add your files
|
||||||
|
|
||||||
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
|
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
|
||||||
- [ ] [Add files using the command line](https://docs.gitlab.com/topics/git/add_files/#add-files-to-a-git-repository) or push an existing Git repository with the following command:
|
- [ ] [Add files using the command line](https://docs.gitlab.com/topics/git/add_files/#add-files-to-a-git-repository) or push an existing Git repository with the following command:
|
||||||
|
|
||||||
```
|
```
|
||||||
cd existing_repo
|
cd existing_repo
|
||||||
git remote add origin https://gitlab.lesko.me/marek/centrum.git
|
git remote add origin https://gitlab.lesko.me/marek/centrum.git
|
||||||
git branch -M main
|
git branch -M main
|
||||||
git push -uf origin main
|
git push -uf origin main
|
||||||
```
|
```
|
||||||
|
|
||||||
## Integrate with your tools
|
## Integrate with your tools
|
||||||
|
|
||||||
- [ ] [Set up project integrations](https://gitlab.lesko.me/marek/centrum/-/settings/integrations)
|
- [ ] [Set up project integrations](https://gitlab.lesko.me/marek/centrum/-/settings/integrations)
|
||||||
|
|
||||||
## Collaborate with your team
|
## Collaborate with your team
|
||||||
|
|
||||||
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
|
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
|
||||||
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
|
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
|
||||||
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
|
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
|
||||||
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
|
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
|
||||||
- [ ] [Set auto-merge](https://docs.gitlab.com/user/project/merge_requests/auto_merge/)
|
- [ ] [Set auto-merge](https://docs.gitlab.com/user/project/merge_requests/auto_merge/)
|
||||||
|
|
||||||
## Test and Deploy
|
## Test and Deploy
|
||||||
|
|
||||||
Use the built-in continuous integration in GitLab.
|
Use the built-in continuous integration in GitLab.
|
||||||
|
|
||||||
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/)
|
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/)
|
||||||
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
|
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
|
||||||
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
|
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
|
||||||
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
|
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
|
||||||
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
|
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
|
||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
# Editing this README
|
# Editing this README
|
||||||
|
|
||||||
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
|
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
|
||||||
|
|
||||||
## Suggestions for a good README
|
## Suggestions for a good README
|
||||||
|
|
||||||
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
|
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
|
||||||
|
|
||||||
## Name
|
## Name
|
||||||
Choose a self-explaining name for your project.
|
Choose a self-explaining name for your project.
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
|
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
|
||||||
|
|
||||||
## Badges
|
## Badges
|
||||||
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
|
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
|
||||||
|
|
||||||
## Visuals
|
## Visuals
|
||||||
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
|
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
|
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
|
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
|
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
If you have ideas for releases in the future, it is a good idea to list them in the README.
|
If you have ideas for releases in the future, it is a good idea to list them in the README.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
State if you are open to contributions and what your requirements are for accepting them.
|
State if you are open to contributions and what your requirements are for accepting them.
|
||||||
|
|
||||||
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
|
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
|
||||||
|
|
||||||
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
|
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
|
||||||
|
|
||||||
## Authors and acknowledgment
|
## Authors and acknowledgment
|
||||||
Show your appreciation to those who have contributed to the project.
|
Show your appreciation to those who have contributed to the project.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
For open source projects, say how it is licensed.
|
For open source projects, say how it is licensed.
|
||||||
|
|
||||||
## Project status
|
## Project status
|
||||||
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
|
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
|
||||||
|
|||||||
2
Tests/.gitignore
vendored
2
Tests/.gitignore
vendored
@@ -1,2 +1,2 @@
|
|||||||
obj/
|
obj/
|
||||||
bin/
|
bin/
|
||||||
@@ -1,38 +1,38 @@
|
|||||||
namespace Tests.Tests
|
namespace Tests.Tests
|
||||||
{
|
{
|
||||||
public class IntegrationTest1
|
public class IntegrationTest1
|
||||||
{
|
{
|
||||||
// Instructions:
|
// Instructions:
|
||||||
// 1. Add a project reference to the target AppHost project, e.g.:
|
// 1. Add a project reference to the target AppHost project, e.g.:
|
||||||
//
|
//
|
||||||
// <ItemGroup>
|
// <ItemGroup>
|
||||||
// <ProjectReference Include="../MyAspireApp.AppHost/MyAspireApp.AppHost.csproj" />
|
// <ProjectReference Include="../MyAspireApp.AppHost/MyAspireApp.AppHost.csproj" />
|
||||||
// </ItemGroup>
|
// </ItemGroup>
|
||||||
//
|
//
|
||||||
// 2. Uncomment the following example test and update 'Projects.MyAspireApp_AppHost' to match your AppHost project:
|
// 2. Uncomment the following example test and update 'Projects.MyAspireApp_AppHost' to match your AppHost project:
|
||||||
//
|
//
|
||||||
// [Fact]
|
// [Fact]
|
||||||
// public async Task GetWebResourceRootReturnsOkStatusCode()
|
// public async Task GetWebResourceRootReturnsOkStatusCode()
|
||||||
// {
|
// {
|
||||||
// // Arrange
|
// // Arrange
|
||||||
// var appHost = await DistributedApplicationTestingBuilder.CreateAsync<Projects.MyAspireApp_AppHost>();
|
// var appHost = await DistributedApplicationTestingBuilder.CreateAsync<Projects.MyAspireApp_AppHost>();
|
||||||
// appHost.Services.ConfigureHttpClientDefaults(clientBuilder =>
|
// appHost.Services.ConfigureHttpClientDefaults(clientBuilder =>
|
||||||
// {
|
// {
|
||||||
// clientBuilder.AddStandardResilienceHandler();
|
// clientBuilder.AddStandardResilienceHandler();
|
||||||
// });
|
// });
|
||||||
// // To output logs to the xUnit.net ITestOutputHelper, consider adding a package from https://www.nuget.org/packages?q=xunit+logging
|
// // 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();
|
// await using var app = await appHost.BuildAsync();
|
||||||
// var resourceNotificationService = app.Services.GetRequiredService<ResourceNotificationService>();
|
// var resourceNotificationService = app.Services.GetRequiredService<ResourceNotificationService>();
|
||||||
// await app.StartAsync();
|
// await app.StartAsync();
|
||||||
|
|
||||||
// // Act
|
// // Act
|
||||||
// var httpClient = app.CreateHttpClient("webfrontend");
|
// var httpClient = app.CreateHttpClient("webfrontend");
|
||||||
// await resourceNotificationService.WaitForResourceAsync("webfrontend", KnownResourceStates.Running).WaitAsync(TimeSpan.FromSeconds(30));
|
// await resourceNotificationService.WaitForResourceAsync("webfrontend", KnownResourceStates.Running).WaitAsync(TimeSpan.FromSeconds(30));
|
||||||
// var response = await httpClient.GetAsync("/");
|
// var response = await httpClient.GetAsync("/");
|
||||||
|
|
||||||
// // Assert
|
// // Assert
|
||||||
// Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
// Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<IsTestProject>true</IsTestProject>
|
<IsTestProject>true</IsTestProject>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Aspire.Hosting.Testing" Version="9.3.1" />
|
<PackageReference Include="Aspire.Hosting.Testing" Version="9.3.1" />
|
||||||
<PackageReference Include="coverlet.collector" Version="6.0.2" />
|
<PackageReference Include="coverlet.collector" Version="6.0.2" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
|
||||||
<PackageReference Include="xunit" Version="2.9.2" />
|
<PackageReference Include="xunit" Version="2.9.2" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Using Include="System.Net" />
|
<Using Include="System.Net" />
|
||||||
<Using Include="Microsoft.Extensions.DependencyInjection" />
|
<Using Include="Microsoft.Extensions.DependencyInjection" />
|
||||||
<Using Include="Aspire.Hosting.ApplicationModel" />
|
<Using Include="Aspire.Hosting.ApplicationModel" />
|
||||||
<Using Include="Aspire.Hosting.Testing" />
|
<Using Include="Aspire.Hosting.Testing" />
|
||||||
<Using Include="Xunit" />
|
<Using Include="Xunit" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
# Editor configuration, see https://editorconfig.org
|
# Editor configuration, see https://editorconfig.org
|
||||||
root = true
|
root = true
|
||||||
|
|
||||||
[*]
|
[*]
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
[*.ts]
|
[*.ts]
|
||||||
quote_type = single
|
quote_type = single
|
||||||
ij_typescript_use_double_quotes = false
|
ij_typescript_use_double_quotes = false
|
||||||
|
|
||||||
[*.md]
|
[*.md]
|
||||||
max_line_length = off
|
max_line_length = off
|
||||||
trim_trailing_whitespace = false
|
trim_trailing_whitespace = false
|
||||||
|
|||||||
84
Web/.gitignore
vendored
84
Web/.gitignore
vendored
@@ -1,42 +1,42 @@
|
|||||||
# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
|
# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
|
||||||
|
|
||||||
# Compiled output
|
# Compiled output
|
||||||
/dist
|
/dist
|
||||||
/tmp
|
/tmp
|
||||||
/out-tsc
|
/out-tsc
|
||||||
/bazel-out
|
/bazel-out
|
||||||
|
|
||||||
# Node
|
# Node
|
||||||
/node_modules
|
/node_modules
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
|
|
||||||
# IDEs and editors
|
# IDEs and editors
|
||||||
.idea/
|
.idea/
|
||||||
.project
|
.project
|
||||||
.classpath
|
.classpath
|
||||||
.c9/
|
.c9/
|
||||||
*.launch
|
*.launch
|
||||||
.settings/
|
.settings/
|
||||||
*.sublime-workspace
|
*.sublime-workspace
|
||||||
|
|
||||||
# Visual Studio Code
|
# Visual Studio Code
|
||||||
.vscode/*
|
.vscode/*
|
||||||
!.vscode/settings.json
|
!.vscode/settings.json
|
||||||
!.vscode/tasks.json
|
!.vscode/tasks.json
|
||||||
!.vscode/launch.json
|
!.vscode/launch.json
|
||||||
!.vscode/extensions.json
|
!.vscode/extensions.json
|
||||||
.history/*
|
.history/*
|
||||||
|
|
||||||
# Miscellaneous
|
# Miscellaneous
|
||||||
/.angular/cache
|
/.angular/cache
|
||||||
.sass-cache/
|
.sass-cache/
|
||||||
/connect.lock
|
/connect.lock
|
||||||
/coverage
|
/coverage
|
||||||
/libpeerconnection.log
|
/libpeerconnection.log
|
||||||
testem.log
|
testem.log
|
||||||
/typings
|
/typings
|
||||||
|
|
||||||
# System files
|
# System files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|||||||
8
Web/.vscode/extensions.json
vendored
8
Web/.vscode/extensions.json
vendored
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
|
||||||
"recommendations": ["angular.ng-template"]
|
"recommendations": ["angular.ng-template"]
|
||||||
}
|
}
|
||||||
|
|||||||
42
Web/.vscode/launch.json
vendored
42
Web/.vscode/launch.json
vendored
@@ -1,21 +1,21 @@
|
|||||||
{
|
{
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "ng serve",
|
"name": "ng serve",
|
||||||
"type": "chrome",
|
"type": "chrome",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"preLaunchTask": "npm: start",
|
"preLaunchTask": "npm: start",
|
||||||
"url": "http://localhost:4200/",
|
"url": "http://localhost:4200/",
|
||||||
"webRoot": "${workspaceFolder}/Web",
|
"webRoot": "${workspaceFolder}/Web",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ng test",
|
"name": "ng test",
|
||||||
"type": "chrome",
|
"type": "chrome",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"preLaunchTask": "npm: test",
|
"preLaunchTask": "npm: test",
|
||||||
"url": "http://localhost:9876/debug.html"
|
"url": "http://localhost:9876/debug.html"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
84
Web/.vscode/tasks.json
vendored
84
Web/.vscode/tasks.json
vendored
@@ -1,42 +1,42 @@
|
|||||||
{
|
{
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
|
// For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
"type": "npm",
|
"type": "npm",
|
||||||
"script": "start",
|
"script": "start",
|
||||||
"isBackground": true,
|
"isBackground": true,
|
||||||
"problemMatcher": {
|
"problemMatcher": {
|
||||||
"owner": "typescript",
|
"owner": "typescript",
|
||||||
"pattern": "$tsc",
|
"pattern": "$tsc",
|
||||||
"background": {
|
"background": {
|
||||||
"activeOnStart": true,
|
"activeOnStart": true,
|
||||||
"beginsPattern": {
|
"beginsPattern": {
|
||||||
"regexp": "(.*?)"
|
"regexp": "(.*?)"
|
||||||
},
|
},
|
||||||
"endsPattern": {
|
"endsPattern": {
|
||||||
"regexp": "bundle generation complete"
|
"regexp": "bundle generation complete"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "npm",
|
"type": "npm",
|
||||||
"script": "test",
|
"script": "test",
|
||||||
"isBackground": true,
|
"isBackground": true,
|
||||||
"problemMatcher": {
|
"problemMatcher": {
|
||||||
"owner": "typescript",
|
"owner": "typescript",
|
||||||
"pattern": "$tsc",
|
"pattern": "$tsc",
|
||||||
"background": {
|
"background": {
|
||||||
"activeOnStart": true,
|
"activeOnStart": true,
|
||||||
"beginsPattern": {
|
"beginsPattern": {
|
||||||
"regexp": "(.*?)"
|
"regexp": "(.*?)"
|
||||||
},
|
},
|
||||||
"endsPattern": {
|
"endsPattern": {
|
||||||
"regexp": "bundle generation complete"
|
"regexp": "bundle generation complete"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
118
Web/README.md
118
Web/README.md
@@ -1,59 +1,59 @@
|
|||||||
# Web
|
# Web
|
||||||
|
|
||||||
This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 20.0.6.
|
This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 20.0.6.
|
||||||
|
|
||||||
## Development server
|
## Development server
|
||||||
|
|
||||||
To start a local development server, run:
|
To start a local development server, run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ng serve
|
ng serve
|
||||||
```
|
```
|
||||||
|
|
||||||
Once the server is running, open your browser and navigate to `http://localhost:4200/`. The application will automatically reload whenever you modify any of the source files.
|
Once the server is running, open your browser and navigate to `http://localhost:4200/`. The application will automatically reload whenever you modify any of the source files.
|
||||||
|
|
||||||
## Code scaffolding
|
## Code scaffolding
|
||||||
|
|
||||||
Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
|
Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ng generate component component-name
|
ng generate component component-name
|
||||||
```
|
```
|
||||||
|
|
||||||
For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
|
For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ng generate --help
|
ng generate --help
|
||||||
```
|
```
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
To build the project run:
|
To build the project run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ng build
|
ng build
|
||||||
```
|
```
|
||||||
|
|
||||||
This will compile your project and store the build artifacts in the `dist/` directory. By default, the production build optimizes your application for performance and speed.
|
This will compile your project and store the build artifacts in the `dist/` directory. By default, the production build optimizes your application for performance and speed.
|
||||||
|
|
||||||
## Running unit tests
|
## Running unit tests
|
||||||
|
|
||||||
To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
|
To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ng test
|
ng test
|
||||||
```
|
```
|
||||||
|
|
||||||
## Running end-to-end tests
|
## Running end-to-end tests
|
||||||
|
|
||||||
For end-to-end (e2e) testing, run:
|
For end-to-end (e2e) testing, run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ng e2e
|
ng e2e
|
||||||
```
|
```
|
||||||
|
|
||||||
Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
|
Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
|
||||||
|
|
||||||
## Additional Resources
|
## Additional Resources
|
||||||
|
|
||||||
For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
|
For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
|
||||||
|
|||||||
198
Web/angular.json
198
Web/angular.json
@@ -1,100 +1,100 @@
|
|||||||
{
|
{
|
||||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"newProjectRoot": "projects",
|
"newProjectRoot": "projects",
|
||||||
"projects": {
|
"projects": {
|
||||||
"Web": {
|
"Web": {
|
||||||
"projectType": "application",
|
"projectType": "application",
|
||||||
"schematics": {
|
"schematics": {
|
||||||
"@schematics/angular:component": {
|
"@schematics/angular:component": {
|
||||||
"style": "scss"
|
"style": "scss"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": "",
|
"root": "",
|
||||||
"sourceRoot": "src",
|
"sourceRoot": "src",
|
||||||
"prefix": "app",
|
"prefix": "app",
|
||||||
"architect": {
|
"architect": {
|
||||||
"build": {
|
"build": {
|
||||||
"builder": "@angular/build:application",
|
"builder": "@angular/build:application",
|
||||||
"options": {
|
"options": {
|
||||||
"browser": "src/main.ts",
|
"browser": "src/main.ts",
|
||||||
"tsConfig": "tsconfig.app.json",
|
"tsConfig": "tsconfig.app.json",
|
||||||
"inlineStyleLanguage": "scss",
|
"inlineStyleLanguage": "scss",
|
||||||
"assets": [
|
"assets": [
|
||||||
{
|
{
|
||||||
"glob": "**/*",
|
"glob": "**/*",
|
||||||
"input": "public"
|
"input": "public"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"styles": [
|
"styles": [
|
||||||
"src/styles.scss"
|
"src/styles.scss"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"configurations": {
|
"configurations": {
|
||||||
"production": {
|
"production": {
|
||||||
"budgets": [
|
"budgets": [
|
||||||
{
|
{
|
||||||
"type": "initial",
|
"type": "initial",
|
||||||
"maximumWarning": "500kB",
|
"maximumWarning": "500kB",
|
||||||
"maximumError": "1MB"
|
"maximumError": "1MB"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "anyComponentStyle",
|
"type": "anyComponentStyle",
|
||||||
"maximumWarning": "4kB",
|
"maximumWarning": "4kB",
|
||||||
"maximumError": "8kB"
|
"maximumError": "8kB"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"outputHashing": "all"
|
"outputHashing": "all"
|
||||||
},
|
},
|
||||||
"development": {
|
"development": {
|
||||||
"optimization": false,
|
"optimization": false,
|
||||||
"extractLicenses": false,
|
"extractLicenses": false,
|
||||||
"sourceMap": true
|
"sourceMap": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"defaultConfiguration": "production"
|
"defaultConfiguration": "production"
|
||||||
},
|
},
|
||||||
"serve": {
|
"serve": {
|
||||||
"builder": "@angular/build:dev-server",
|
"builder": "@angular/build:dev-server",
|
||||||
"options": {
|
"options": {
|
||||||
"allowedHosts": [
|
"allowedHosts": [
|
||||||
"localhost",
|
"localhost",
|
||||||
"4200--0197f0a3-fef1-7776-b920-71d5d9c3d787.us01.gitpod.dev"
|
"4200--0197f0a3-fef1-7776-b920-71d5d9c3d787.us01.gitpod.dev"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"configurations": {
|
"configurations": {
|
||||||
"production": {
|
"production": {
|
||||||
"buildTarget": "Web:build:production"
|
"buildTarget": "Web:build:production"
|
||||||
},
|
},
|
||||||
"development": {
|
"development": {
|
||||||
"buildTarget": "Web:build:development"
|
"buildTarget": "Web:build:development"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"defaultConfiguration": "development"
|
"defaultConfiguration": "development"
|
||||||
},
|
},
|
||||||
"extract-i18n": {
|
"extract-i18n": {
|
||||||
"builder": "@angular/build:extract-i18n"
|
"builder": "@angular/build:extract-i18n"
|
||||||
},
|
},
|
||||||
"test": {
|
"test": {
|
||||||
"builder": "@angular/build:karma",
|
"builder": "@angular/build:karma",
|
||||||
"options": {
|
"options": {
|
||||||
"tsConfig": "tsconfig.spec.json",
|
"tsConfig": "tsconfig.spec.json",
|
||||||
"inlineStyleLanguage": "scss",
|
"inlineStyleLanguage": "scss",
|
||||||
"assets": [
|
"assets": [
|
||||||
{
|
{
|
||||||
"glob": "**/*",
|
"glob": "**/*",
|
||||||
"input": "public"
|
"input": "public"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"styles": [
|
"styles": [
|
||||||
"src/styles.scss"
|
"src/styles.scss"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"cli": {
|
"cli": {
|
||||||
"analytics": false
|
"analytics": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
17828
Web/package-lock.json
generated
17828
Web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,46 +1,46 @@
|
|||||||
{
|
{
|
||||||
"name": "web",
|
"name": "web",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"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 --configuration=production",
|
"build": "ng build --configuration=production",
|
||||||
"watch": "ng build --watch --configuration development",
|
"watch": "ng build --watch --configuration development",
|
||||||
"test": "ng test"
|
"test": "ng test"
|
||||||
},
|
},
|
||||||
"prettier": {
|
"prettier": {
|
||||||
"overrides": [
|
"overrides": [
|
||||||
{
|
{
|
||||||
"files": "*.html",
|
"files": "*.html",
|
||||||
"options": {
|
"options": {
|
||||||
"parser": "angular"
|
"parser": "angular"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/common": "^20.0.0",
|
"@angular/common": "^20.0.0",
|
||||||
"@angular/compiler": "^20.0.0",
|
"@angular/compiler": "^20.0.0",
|
||||||
"@angular/core": "^20.0.0",
|
"@angular/core": "^20.0.0",
|
||||||
"@angular/forms": "^20.0.0",
|
"@angular/forms": "^20.0.0",
|
||||||
"@angular/platform-browser": "^20.0.0",
|
"@angular/platform-browser": "^20.0.0",
|
||||||
"@angular/router": "^20.0.0",
|
"@angular/router": "^20.0.0",
|
||||||
"angular-oauth2-oidc": "^20.0.2",
|
"angular-oauth2-oidc": "^20.0.2",
|
||||||
"rxjs": "~7.8.0",
|
"rxjs": "~7.8.0",
|
||||||
"tslib": "^2.3.0"
|
"tslib": "^2.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular/build": "^20.0.6",
|
"@angular/build": "^20.0.6",
|
||||||
"@angular/cli": "^20.0.6",
|
"@angular/cli": "^20.0.6",
|
||||||
"@angular/compiler-cli": "^20.0.0",
|
"@angular/compiler-cli": "^20.0.0",
|
||||||
"@types/jasmine": "~5.1.0",
|
"@types/jasmine": "~5.1.0",
|
||||||
"jasmine-core": "~5.7.0",
|
"jasmine-core": "~5.7.0",
|
||||||
"karma": "~6.4.0",
|
"karma": "~6.4.0",
|
||||||
"karma-chrome-launcher": "~3.2.0",
|
"karma-chrome-launcher": "~3.2.0",
|
||||||
"karma-coverage": "~2.2.0",
|
"karma-coverage": "~2.2.0",
|
||||||
"karma-jasmine": "~5.1.0",
|
"karma-jasmine": "~5.1.0",
|
||||||
"karma-jasmine-html-reporter": "~2.1.0",
|
"karma-jasmine-html-reporter": "~2.1.0",
|
||||||
"typescript": "~5.8.2"
|
"typescript": "~5.8.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"apiEndpoint": "https://localhost:5001"
|
"apiEndpoint": "https://localhost:5001"
|
||||||
}
|
}
|
||||||
@@ -1,34 +1,34 @@
|
|||||||
import { ApplicationConfig, inject, provideAppInitializer, provideBrowserGlobalErrorListeners, provideZonelessChangeDetection } from '@angular/core';
|
import { ApplicationConfig, inject, provideAppInitializer, provideBrowserGlobalErrorListeners, provideZonelessChangeDetection } from '@angular/core';
|
||||||
import { provideRouter } from '@angular/router';
|
import { provideRouter } from '@angular/router';
|
||||||
|
|
||||||
import { routes } from './app.routes';
|
import { routes } from './app.routes';
|
||||||
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
|
import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
|
||||||
import { DefaultOAuthInterceptor, provideOAuthClient } from 'angular-oauth2-oidc';
|
import { DefaultOAuthInterceptor, provideOAuthClient } from 'angular-oauth2-oidc';
|
||||||
import { AppConfigService } from './services/config.service';
|
import { AppConfigService } from './services/config.service';
|
||||||
import { ApiEndpointInterceptor } from './services/http.interceptor';
|
import { ApiEndpointInterceptor } from './services/http.interceptor';
|
||||||
|
|
||||||
export const appConfig: ApplicationConfig = {
|
export const appConfig: ApplicationConfig = {
|
||||||
providers: [
|
providers: [
|
||||||
provideBrowserGlobalErrorListeners(),
|
provideBrowserGlobalErrorListeners(),
|
||||||
provideZonelessChangeDetection(),
|
provideZonelessChangeDetection(),
|
||||||
provideRouter(routes),
|
provideRouter(routes),
|
||||||
provideAppInitializer(() => inject(AppConfigService).loadConfig()),
|
provideAppInitializer(() => inject(AppConfigService).loadConfig()),
|
||||||
{
|
{
|
||||||
provide: HTTP_INTERCEPTORS,
|
provide: HTTP_INTERCEPTORS,
|
||||||
useClass: DefaultOAuthInterceptor,
|
useClass: DefaultOAuthInterceptor,
|
||||||
multi: true,
|
multi: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: HTTP_INTERCEPTORS,
|
provide: HTTP_INTERCEPTORS,
|
||||||
useClass: ApiEndpointInterceptor,
|
useClass: ApiEndpointInterceptor,
|
||||||
multi: true,
|
multi: true,
|
||||||
},
|
},
|
||||||
provideHttpClient(withInterceptorsFromDi()),
|
provideHttpClient(withInterceptorsFromDi()),
|
||||||
provideOAuthClient({
|
provideOAuthClient({
|
||||||
resourceServer: {
|
resourceServer: {
|
||||||
allowedUrls: ['http://localhost:5000', 'https://localhost:5001', 'https://centrum.lesko.me','https://beta.e-dias.sk/'],
|
allowedUrls: ['http://localhost:5000', 'https://localhost:5001', 'https://centrum.lesko.me','https://beta.e-dias.sk/'],
|
||||||
sendAccessToken: true,
|
sendAccessToken: true,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<router-outlet />
|
<router-outlet />
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { CanActivateFn } from '@angular/router';
|
import { CanActivateFn } from '@angular/router';
|
||||||
import { inject } from '@angular/core';
|
import { inject } from '@angular/core';
|
||||||
import { OAuthService } from 'angular-oauth2-oidc';
|
import { OAuthService } from 'angular-oauth2-oidc';
|
||||||
|
|
||||||
|
|
||||||
export const authGuard: CanActivateFn = (route, state) => {
|
export const authGuard: CanActivateFn = (route, state) => {
|
||||||
const authService = inject(OAuthService);
|
const authService = inject(OAuthService);
|
||||||
return authService.hasValidAccessToken(); // returns boolean, Promise, or Observable
|
return authService.hasValidAccessToken(); // returns boolean, Promise, or Observable
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
import { Routes } from '@angular/router';
|
import { Routes } from '@angular/router';
|
||||||
import { Login } from './login/login';
|
import { Login } from './login/login';
|
||||||
import { authGuard } from './app.route.guard';
|
import { authGuard } from './app.route.guard';
|
||||||
|
|
||||||
export const routes: Routes = [
|
export const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: 'login',
|
path: 'login',
|
||||||
component: Login,
|
component: Login,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'content',
|
path: 'content',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
loadComponent: () => import('./content/content').then(m => m.Content),
|
loadComponent: () => import('./content/content').then(m => m.Content),
|
||||||
canActivate: [authGuard],
|
canActivate: [authGuard],
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
import { provideZonelessChangeDetection } from '@angular/core';
|
import { provideZonelessChangeDetection } from '@angular/core';
|
||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed } from '@angular/core/testing';
|
||||||
import { App } from './app';
|
import { App } from './app';
|
||||||
|
|
||||||
describe('App', () => {
|
describe('App', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [App],
|
imports: [App],
|
||||||
providers: [provideZonelessChangeDetection()]
|
providers: [provideZonelessChangeDetection()]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create the app', () => {
|
it('should create the app', () => {
|
||||||
const fixture = TestBed.createComponent(App);
|
const fixture = TestBed.createComponent(App);
|
||||||
const app = fixture.componentInstance;
|
const app = fixture.componentInstance;
|
||||||
expect(app).toBeTruthy();
|
expect(app).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render title', () => {
|
it('should render title', () => {
|
||||||
const fixture = TestBed.createComponent(App);
|
const fixture = TestBed.createComponent(App);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const compiled = fixture.nativeElement as HTMLElement;
|
const compiled = fixture.nativeElement as HTMLElement;
|
||||||
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, Web');
|
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, Web');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,31 +1,31 @@
|
|||||||
import { HTTP_INTERCEPTORS } from '@angular/common/http';
|
import { HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||||
import { APP_INITIALIZER, Component, inject, OnInit, provideAppInitializer } from '@angular/core';
|
import { APP_INITIALIZER, Component, inject, OnInit, provideAppInitializer } from '@angular/core';
|
||||||
import { Router, RouterOutlet } from '@angular/router';
|
import { Router, RouterOutlet } from '@angular/router';
|
||||||
import { DefaultOAuthInterceptor, OAuthService } from 'angular-oauth2-oidc';
|
import { DefaultOAuthInterceptor, OAuthService } from 'angular-oauth2-oidc';
|
||||||
import { AppConfigService } from './services/config.service';
|
import { AppConfigService } from './services/config.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
imports: [RouterOutlet],
|
imports: [RouterOutlet],
|
||||||
providers: [
|
providers: [
|
||||||
OAuthService,
|
OAuthService,
|
||||||
],
|
],
|
||||||
templateUrl: './app.html',
|
templateUrl: './app.html',
|
||||||
styleUrl: './app.scss'
|
styleUrl: './app.scss'
|
||||||
})
|
})
|
||||||
export class App implements OnInit {
|
export class App implements OnInit {
|
||||||
protected title = 'Web';
|
protected title = 'Web';
|
||||||
constructor(private readonly as: OAuthService, private readonly router: Router) {
|
constructor(private readonly as: OAuthService, private readonly router: Router) {
|
||||||
this.as.configure({
|
this.as.configure({
|
||||||
issuer: 'https://identity.lesko.me',
|
issuer: 'https://identity.lesko.me',
|
||||||
redirectUri: window.location.origin + '/login',
|
redirectUri: window.location.origin + '/login',
|
||||||
clientId: '21131567-fea1-42a2-8907-21abd874eff8',
|
clientId: '21131567-fea1-42a2-8907-21abd874eff8',
|
||||||
scope: 'openid profile email',
|
scope: 'openid profile email',
|
||||||
responseType: 'code',
|
responseType: 'code',
|
||||||
timeoutFactor: 0.01,
|
timeoutFactor: 0.01,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.as.loadDiscoveryDocumentAndLogin().then(() => this.router.navigate(['login']));
|
this.as.loadDiscoveryDocumentAndLogin().then(() => this.router.navigate(['login']));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
import { Content } from './content';
|
import { Content } from './content';
|
||||||
|
|
||||||
describe('Content', () => {
|
describe('Content', () => {
|
||||||
let component: Content;
|
let component: Content;
|
||||||
let fixture: ComponentFixture<Content>;
|
let fixture: ComponentFixture<Content>;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [Content]
|
imports: [Content]
|
||||||
})
|
})
|
||||||
.compileComponents();
|
.compileComponents();
|
||||||
|
|
||||||
fixture = TestBed.createComponent(Content);
|
fixture = TestBed.createComponent(Content);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
import { JsonPipe } from '@angular/common';
|
import { JsonPipe } from '@angular/common';
|
||||||
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||||
import { Component, isDevMode, signal } from '@angular/core';
|
import { Component, isDevMode, signal } from '@angular/core';
|
||||||
import { OAuthService } from 'angular-oauth2-oidc';
|
import { OAuthService } from 'angular-oauth2-oidc';
|
||||||
import { AppConfigService } from '../services/config.service';
|
import { AppConfigService } from '../services/config.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-content',
|
selector: 'app-content',
|
||||||
imports: [JsonPipe],
|
imports: [JsonPipe],
|
||||||
templateUrl: './content.html',
|
templateUrl: './content.html',
|
||||||
styleUrl: './content.scss'
|
styleUrl: './content.scss'
|
||||||
})
|
})
|
||||||
export class Content {
|
export class Content {
|
||||||
data = signal({});
|
data = signal({});
|
||||||
|
|
||||||
constructor(httpClient: HttpClient, readonly as: OAuthService, readonly cs: AppConfigService) {
|
constructor(httpClient: HttpClient, readonly as: OAuthService, readonly cs: AppConfigService) {
|
||||||
httpClient.get('/api/product')
|
httpClient.get('/api/product')
|
||||||
.subscribe(data => {
|
.subscribe(data => {
|
||||||
this.data.set(data);
|
this.data.set(data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
|
|
||||||
Logging in...
|
Logging in...
|
||||||
@@ -1,23 +1,23 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
import { Login } from './login';
|
import { Login } from './login';
|
||||||
|
|
||||||
describe('Login', () => {
|
describe('Login', () => {
|
||||||
let component: Login;
|
let component: Login;
|
||||||
let fixture: ComponentFixture<Login>;
|
let fixture: ComponentFixture<Login>;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [Login]
|
imports: [Login]
|
||||||
})
|
})
|
||||||
.compileComponents();
|
.compileComponents();
|
||||||
|
|
||||||
fixture = TestBed.createComponent(Login);
|
fixture = TestBed.createComponent(Login);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,33 +1,33 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { OAuthService } from 'angular-oauth2-oidc';
|
import { OAuthService } from 'angular-oauth2-oidc';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-login',
|
selector: 'app-login',
|
||||||
templateUrl: './login.html',
|
templateUrl: './login.html',
|
||||||
styleUrl: './login.scss'
|
styleUrl: './login.scss'
|
||||||
})
|
})
|
||||||
export class Login implements OnInit {
|
export class Login implements OnInit {
|
||||||
|
|
||||||
constructor(readonly as: OAuthService, readonly router: Router) { }
|
constructor(readonly as: OAuthService, readonly router: Router) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
if (this.as.hasValidAccessToken() && this.as.hasValidIdToken()) {
|
if (this.as.hasValidAccessToken() && this.as.hasValidIdToken()) {
|
||||||
this.getUserInfo();
|
this.getUserInfo();
|
||||||
} else {
|
} else {
|
||||||
this.as.events.subscribe(event => {
|
this.as.events.subscribe(event => {
|
||||||
if (event.type === 'token_received')
|
if (event.type === 'token_received')
|
||||||
if (this.as.hasValidIdToken()) {
|
if (this.as.hasValidIdToken()) {
|
||||||
this.getUserInfo();
|
this.getUserInfo();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getUserInfo(): void {
|
getUserInfo(): void {
|
||||||
this.as.loadUserProfile().then(value => {
|
this.as.loadUserProfile().then(value => {
|
||||||
console.log('User profile loaded:', value);
|
console.log('User profile loaded:', value);
|
||||||
this.router.navigate(['/content']);
|
this.router.navigate(['/content']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,31 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class AppConfigService {
|
export class AppConfigService {
|
||||||
private config: any;
|
private config: any;
|
||||||
|
|
||||||
public loaded: boolean = false;
|
public loaded: boolean = false;
|
||||||
|
|
||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
loadConfig(): Observable<any> {
|
loadConfig(): Observable<any> {
|
||||||
return new Observable(observer => {
|
return new Observable(observer => {
|
||||||
fetch('/config.json')
|
fetch('/config.json')
|
||||||
.then(async response => {
|
.then(async response => {
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`Could not load config.json: ${response.statusText}`);
|
throw new Error(`Could not load config.json: ${response.statusText}`);
|
||||||
}
|
}
|
||||||
this.config = await response.json();
|
this.config = await response.json();
|
||||||
this.loaded = true;
|
this.loaded = true;
|
||||||
observer.next(this.config);
|
observer.next(this.config);
|
||||||
observer.complete();
|
observer.complete();
|
||||||
})
|
})
|
||||||
.catch(error => observer.error(error));
|
.catch(error => observer.error(error));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get setting() {
|
get setting() {
|
||||||
return this.config;
|
return this.config;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
|
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { AppConfigService } from './config.service';
|
import { AppConfigService } from './config.service';
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class ApiEndpointInterceptor implements HttpInterceptor {
|
export class ApiEndpointInterceptor implements HttpInterceptor {
|
||||||
constructor(private readonly configService: AppConfigService) { }
|
constructor(private readonly configService: AppConfigService) { }
|
||||||
|
|
||||||
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||||
return this.prependUrl(req, next);
|
return this.prependUrl(req, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
prependUrl(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
prependUrl(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||||
const apiEndpoint = this.configService.setting.apiEndpoint;
|
const apiEndpoint = this.configService.setting.apiEndpoint;
|
||||||
if (apiEndpoint === undefined || !this.configService.loaded)
|
if (apiEndpoint === undefined || !this.configService.loaded)
|
||||||
throw new Error('API endpoint is not defined or config not loaded');
|
throw new Error('API endpoint is not defined or config not loaded');
|
||||||
|
|
||||||
const isRelative = !/^https?:\/\//i.test(req.url);
|
const isRelative = !/^https?:\/\//i.test(req.url);
|
||||||
const url = isRelative ? `${apiEndpoint.replace(/\/$/, '')}/${req.url.replace(/^\//, '')}` : req.url;
|
const url = isRelative ? `${apiEndpoint.replace(/\/$/, '')}/${req.url.replace(/^\//, '')}` : req.url;
|
||||||
const cloned = req.clone({ url });
|
const cloned = req.clone({ url });
|
||||||
console.trace('ApiEndpointInterceptor hit:', url);
|
console.trace('ApiEndpointInterceptor hit:', url);
|
||||||
return next.handle(cloned);
|
return next.handle(cloned);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Web</title>
|
<title>Web</title>
|
||||||
<base href="/">
|
<base href="/">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<app-root></app-root>
|
<app-root></app-root>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { bootstrapApplication } from '@angular/platform-browser';
|
import { bootstrapApplication } from '@angular/platform-browser';
|
||||||
import { appConfig } from './app/app.config';
|
import { appConfig } from './app/app.config';
|
||||||
import { App } from './app/app';
|
import { App } from './app/app';
|
||||||
|
|
||||||
bootstrapApplication(App, appConfig)
|
bootstrapApplication(App, appConfig)
|
||||||
.catch((err) => console.error(err));
|
.catch((err) => console.error(err));
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
/* You can add global styles to this file, and also import other style files */
|
/* You can add global styles to this file, and also import other style files */
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
# Editor configuration, see https://editorconfig.org
|
# Editor configuration, see https://editorconfig.org
|
||||||
root = true
|
root = true
|
||||||
|
|
||||||
[*]
|
[*]
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
[*.ts]
|
[*.ts]
|
||||||
quote_type = single
|
quote_type = single
|
||||||
|
|
||||||
[*.md]
|
[*.md]
|
||||||
max_line_length = off
|
max_line_length = off
|
||||||
trim_trailing_whitespace = false
|
trim_trailing_whitespace = false
|
||||||
|
|||||||
84
Web/themes/modernize/.gitignore
vendored
84
Web/themes/modernize/.gitignore
vendored
@@ -1,42 +1,42 @@
|
|||||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||||
|
|
||||||
# Compiled output
|
# Compiled output
|
||||||
/dist
|
/dist
|
||||||
/tmp
|
/tmp
|
||||||
/out-tsc
|
/out-tsc
|
||||||
/bazel-out
|
/bazel-out
|
||||||
|
|
||||||
# Node
|
# Node
|
||||||
/node_modules
|
/node_modules
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
|
|
||||||
# IDEs and editors
|
# IDEs and editors
|
||||||
.idea/
|
.idea/
|
||||||
.project
|
.project
|
||||||
.classpath
|
.classpath
|
||||||
.c9/
|
.c9/
|
||||||
*.launch
|
*.launch
|
||||||
.settings/
|
.settings/
|
||||||
*.sublime-workspace
|
*.sublime-workspace
|
||||||
|
|
||||||
# Visual Studio Code
|
# Visual Studio Code
|
||||||
.vscode/*
|
.vscode/*
|
||||||
!.vscode/settings.json
|
!.vscode/settings.json
|
||||||
!.vscode/tasks.json
|
!.vscode/tasks.json
|
||||||
!.vscode/launch.json
|
!.vscode/launch.json
|
||||||
!.vscode/extensions.json
|
!.vscode/extensions.json
|
||||||
.history/*
|
.history/*
|
||||||
|
|
||||||
# Miscellaneous
|
# Miscellaneous
|
||||||
/.angular/cache
|
/.angular/cache
|
||||||
.sass-cache/
|
.sass-cache/
|
||||||
/connect.lock
|
/connect.lock
|
||||||
/coverage
|
/coverage
|
||||||
/libpeerconnection.log
|
/libpeerconnection.log
|
||||||
testem.log
|
testem.log
|
||||||
/typings
|
/typings
|
||||||
|
|
||||||
# System files
|
# System files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
# Modernize-Angular-pro
|
# Modernize-Angular-pro
|
||||||
Modernize Angular Admin Dashboard
|
Modernize Angular Admin Dashboard
|
||||||
|
|||||||
@@ -1,96 +1,96 @@
|
|||||||
{
|
{
|
||||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"newProjectRoot": "projects",
|
"newProjectRoot": "projects",
|
||||||
"projects": {
|
"projects": {
|
||||||
"Modernize": {
|
"Modernize": {
|
||||||
"projectType": "application",
|
"projectType": "application",
|
||||||
"schematics": {
|
"schematics": {
|
||||||
"@schematics/angular:component": {
|
"@schematics/angular:component": {
|
||||||
"style": "scss"
|
"style": "scss"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": "",
|
"root": "",
|
||||||
"sourceRoot": "src",
|
"sourceRoot": "src",
|
||||||
"prefix": "app",
|
"prefix": "app",
|
||||||
"architect": {
|
"architect": {
|
||||||
"build": {
|
"build": {
|
||||||
"builder": "@angular-devkit/build-angular:browser",
|
"builder": "@angular-devkit/build-angular:browser",
|
||||||
"options": {
|
"options": {
|
||||||
"allowedCommonJsDependencies": ["apexcharts", "bezier-easing", "moment"],
|
"allowedCommonJsDependencies": ["apexcharts", "bezier-easing", "moment"],
|
||||||
"outputPath": "dist/Modernize",
|
"outputPath": "dist/Modernize",
|
||||||
"index": "src/index.html",
|
"index": "src/index.html",
|
||||||
"main": "src/main.ts",
|
"main": "src/main.ts",
|
||||||
"polyfills": ["zone.js"],
|
"polyfills": ["zone.js"],
|
||||||
"tsConfig": "tsconfig.app.json",
|
"tsConfig": "tsconfig.app.json",
|
||||||
"inlineStyleLanguage": "scss",
|
"inlineStyleLanguage": "scss",
|
||||||
"assets": ["src/favicon.ico", "src/assets"],
|
"assets": ["src/favicon.ico", "src/assets"],
|
||||||
"styles": ["src/styles.scss", "src/assets/scss/style.scss"],
|
"styles": ["src/styles.scss", "src/assets/scss/style.scss"],
|
||||||
"scripts": []
|
"scripts": []
|
||||||
},
|
},
|
||||||
"configurations": {
|
"configurations": {
|
||||||
"production": {
|
"production": {
|
||||||
"budgets": [
|
"budgets": [
|
||||||
{
|
{
|
||||||
"type": "initial",
|
"type": "initial",
|
||||||
"maximumWarning": "12mb",
|
"maximumWarning": "12mb",
|
||||||
"maximumError": "12mb"
|
"maximumError": "12mb"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "anyComponentStyle",
|
"type": "anyComponentStyle",
|
||||||
"maximumWarning": "12mb",
|
"maximumWarning": "12mb",
|
||||||
"maximumError": "12mb"
|
"maximumError": "12mb"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"outputHashing": "all"
|
"outputHashing": "all"
|
||||||
},
|
},
|
||||||
"development": {
|
"development": {
|
||||||
"buildOptimizer": false,
|
"buildOptimizer": false,
|
||||||
"optimization": false,
|
"optimization": false,
|
||||||
"vendorChunk": true,
|
"vendorChunk": true,
|
||||||
"extractLicenses": false,
|
"extractLicenses": false,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"namedChunks": true
|
"namedChunks": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"defaultConfiguration": "production"
|
"defaultConfiguration": "production"
|
||||||
},
|
},
|
||||||
"serve": {
|
"serve": {
|
||||||
"builder": "@angular-devkit/build-angular:dev-server",
|
"builder": "@angular-devkit/build-angular:dev-server",
|
||||||
"configurations": {
|
"configurations": {
|
||||||
"production": {
|
"production": {
|
||||||
"buildTarget": "Modernize:build:production"
|
"buildTarget": "Modernize:build:production"
|
||||||
},
|
},
|
||||||
"hmr": {
|
"hmr": {
|
||||||
"hmr": true
|
"hmr": true
|
||||||
},
|
},
|
||||||
"development": {
|
"development": {
|
||||||
"buildTarget": "Modernize:build:development"
|
"buildTarget": "Modernize:build:development"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"defaultConfiguration": "development"
|
"defaultConfiguration": "development"
|
||||||
},
|
},
|
||||||
"extract-i18n": {
|
"extract-i18n": {
|
||||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||||
"options": {
|
"options": {
|
||||||
"buildTarget": "Modernize:build"
|
"buildTarget": "Modernize:build"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"test": {
|
"test": {
|
||||||
"builder": "@angular-devkit/build-angular:karma",
|
"builder": "@angular-devkit/build-angular:karma",
|
||||||
"options": {
|
"options": {
|
||||||
"polyfills": ["zone.js", "zone.js/testing"],
|
"polyfills": ["zone.js", "zone.js/testing"],
|
||||||
"tsConfig": "tsconfig.spec.json",
|
"tsConfig": "tsconfig.spec.json",
|
||||||
"inlineStyleLanguage": "scss",
|
"inlineStyleLanguage": "scss",
|
||||||
"assets": ["src/favicon.ico", "src/assets"],
|
"assets": ["src/favicon.ico", "src/assets"],
|
||||||
"styles": ["src/styles.scss"],
|
"styles": ["src/styles.scss"],
|
||||||
"scripts": []
|
"scripts": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"cli": {
|
"cli": {
|
||||||
"analytics": false
|
"analytics": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
[[redirects]]
|
[[redirects]]
|
||||||
from = "/*"
|
from = "/*"
|
||||||
to = "/index.html"
|
to = "/index.html"
|
||||||
status = 200
|
status = 200
|
||||||
27602
Web/themes/modernize/package-lock.json
generated
27602
Web/themes/modernize/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,48 +1,48 @@
|
|||||||
{
|
{
|
||||||
"name": "modernize",
|
"name": "modernize",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"ng": "ng",
|
"ng": "ng",
|
||||||
"start": "ng serve",
|
"start": "ng serve",
|
||||||
"build": "ng build",
|
"build": "ng build",
|
||||||
"watch": "ng build --watch --configuration development",
|
"watch": "ng build --watch --configuration development",
|
||||||
"test": "ng test"
|
"test": "ng test"
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "^19.0.0",
|
"@angular/animations": "^19.0.0",
|
||||||
"@angular/cdk": "^19.0.0",
|
"@angular/cdk": "^19.0.0",
|
||||||
"@angular/common": "^19.0.0",
|
"@angular/common": "^19.0.0",
|
||||||
"@angular/compiler": "^19.0.0",
|
"@angular/compiler": "^19.0.0",
|
||||||
"@angular/core": "^19.0.0",
|
"@angular/core": "^19.0.0",
|
||||||
"@angular/forms": "^19.0.0",
|
"@angular/forms": "^19.0.0",
|
||||||
"@angular/material": "^19.0.0",
|
"@angular/material": "^19.0.0",
|
||||||
"@angular/platform-browser": "^19.0.0",
|
"@angular/platform-browser": "^19.0.0",
|
||||||
"@angular/platform-browser-dynamic": "^19.0.0",
|
"@angular/platform-browser-dynamic": "^19.0.0",
|
||||||
"@angular/router": "^19.0.0",
|
"@angular/router": "^19.0.0",
|
||||||
"@ngx-translate/core": "^14.0.0",
|
"@ngx-translate/core": "^14.0.0",
|
||||||
"@ngx-translate/http-loader": "^7.0.0",
|
"@ngx-translate/http-loader": "^7.0.0",
|
||||||
"angular-tabler-icons": "^2.7.0",
|
"angular-tabler-icons": "^2.7.0",
|
||||||
"apexcharts": "^3.49.0",
|
"apexcharts": "^3.49.0",
|
||||||
"ng-apexcharts": "1.7.6",
|
"ng-apexcharts": "1.7.6",
|
||||||
"ngx-scrollbar": "^11.0.0",
|
"ngx-scrollbar": "^11.0.0",
|
||||||
"rxjs": "~7.5.0",
|
"rxjs": "~7.5.0",
|
||||||
"sass": "1.81.0",
|
"sass": "1.81.0",
|
||||||
"tslib": "^2.3.0",
|
"tslib": "^2.3.0",
|
||||||
"zone.js": "~0.15.0"
|
"zone.js": "~0.15.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular-devkit/build-angular": "^19.0.1",
|
"@angular-devkit/build-angular": "^19.0.1",
|
||||||
"@angular/cli": "~19.0.1",
|
"@angular/cli": "~19.0.1",
|
||||||
"@angular/compiler-cli": "^19.0.0",
|
"@angular/compiler-cli": "^19.0.0",
|
||||||
"@types/date-fns": "^2.6.0",
|
"@types/date-fns": "^2.6.0",
|
||||||
"@types/jasmine": "~4.3.0",
|
"@types/jasmine": "~4.3.0",
|
||||||
"jasmine-core": "~4.5.0",
|
"jasmine-core": "~4.5.0",
|
||||||
"karma": "~6.4.0",
|
"karma": "~6.4.0",
|
||||||
"karma-chrome-launcher": "~3.1.0",
|
"karma-chrome-launcher": "~3.1.0",
|
||||||
"karma-coverage": "~2.2.0",
|
"karma-coverage": "~2.2.0",
|
||||||
"karma-jasmine": "~5.1.0",
|
"karma-jasmine": "~5.1.0",
|
||||||
"karma-jasmine-html-reporter": "~2.0.0",
|
"karma-jasmine-html-reporter": "~2.0.0",
|
||||||
"typescript": "~5.6.3"
|
"typescript": "~5.6.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
|
|||||||
@@ -1,35 +1,35 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed } from '@angular/core/testing';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
describe('AppComponent', () => {
|
describe('AppComponent', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
RouterTestingModule
|
RouterTestingModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent
|
AppComponent
|
||||||
],
|
],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create the app', () => {
|
it('should create the app', () => {
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
const app = fixture.componentInstance;
|
const app = fixture.componentInstance;
|
||||||
expect(app).toBeTruthy();
|
expect(app).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should have as title 'Angular15'`, () => {
|
it(`should have as title 'Angular15'`, () => {
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
const app = fixture.componentInstance;
|
const app = fixture.componentInstance;
|
||||||
expect(app.title).toEqual('Angular15');
|
expect(app.title).toEqual('Angular15');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render title', () => {
|
it('should render title', () => {
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const compiled = fixture.nativeElement as HTMLElement;
|
const compiled = fixture.nativeElement as HTMLElement;
|
||||||
expect(compiled.querySelector('.content span')?.textContent).toContain('Angular15 app is running!');
|
expect(compiled.querySelector('.content span')?.textContent).toContain('Angular15 app is running!');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { RouterOutlet } from '@angular/router';
|
import { RouterOutlet } from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
imports: [RouterOutlet],
|
imports: [RouterOutlet],
|
||||||
templateUrl: './app.component.html'
|
templateUrl: './app.component.html'
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
title = 'Modernize Angular Admin Template';
|
title = 'Modernize Angular Admin Template';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,55 +1,55 @@
|
|||||||
import {
|
import {
|
||||||
ApplicationConfig,
|
ApplicationConfig,
|
||||||
provideZoneChangeDetection,
|
provideZoneChangeDetection,
|
||||||
importProvidersFrom,
|
importProvidersFrom,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import {
|
import {
|
||||||
HttpClient,
|
HttpClient,
|
||||||
provideHttpClient,
|
provideHttpClient,
|
||||||
withInterceptorsFromDi,
|
withInterceptorsFromDi,
|
||||||
} from '@angular/common/http';
|
} from '@angular/common/http';
|
||||||
import { routes } from './app.routes';
|
import { routes } from './app.routes';
|
||||||
import {
|
import {
|
||||||
provideRouter,
|
provideRouter,
|
||||||
withComponentInputBinding,
|
withComponentInputBinding,
|
||||||
withInMemoryScrolling,
|
withInMemoryScrolling,
|
||||||
} from '@angular/router';
|
} from '@angular/router';
|
||||||
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
|
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
|
||||||
import { provideClientHydration } from '@angular/platform-browser';
|
import { provideClientHydration } from '@angular/platform-browser';
|
||||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||||
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
||||||
|
|
||||||
// icons
|
// icons
|
||||||
import { TablerIconsModule } from 'angular-tabler-icons';
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
import * as TablerIcons from 'angular-tabler-icons/icons';
|
import * as TablerIcons from 'angular-tabler-icons/icons';
|
||||||
|
|
||||||
// perfect scrollbar
|
// perfect scrollbar
|
||||||
import { NgScrollbarModule } from 'ngx-scrollbar';
|
import { NgScrollbarModule } from 'ngx-scrollbar';
|
||||||
|
|
||||||
//Import all material modules
|
//Import all material modules
|
||||||
import { MaterialModule } from './material.module';
|
import { MaterialModule } from './material.module';
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
|
||||||
export const appConfig: ApplicationConfig = {
|
export const appConfig: ApplicationConfig = {
|
||||||
providers: [
|
providers: [
|
||||||
provideZoneChangeDetection({ eventCoalescing: true }),
|
provideZoneChangeDetection({ eventCoalescing: true }),
|
||||||
provideRouter(
|
provideRouter(
|
||||||
routes,
|
routes,
|
||||||
withInMemoryScrolling({
|
withInMemoryScrolling({
|
||||||
scrollPositionRestoration: 'enabled',
|
scrollPositionRestoration: 'enabled',
|
||||||
anchorScrolling: 'enabled',
|
anchorScrolling: 'enabled',
|
||||||
}),
|
}),
|
||||||
withComponentInputBinding()
|
withComponentInputBinding()
|
||||||
),
|
),
|
||||||
provideHttpClient(withInterceptorsFromDi()),
|
provideHttpClient(withInterceptorsFromDi()),
|
||||||
provideClientHydration(),
|
provideClientHydration(),
|
||||||
provideAnimationsAsync(),
|
provideAnimationsAsync(),
|
||||||
importProvidersFrom(
|
importProvidersFrom(
|
||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
MaterialModule,
|
MaterialModule,
|
||||||
TablerIconsModule.pick(TablerIcons),
|
TablerIconsModule.pick(TablerIcons),
|
||||||
NgScrollbarModule,
|
NgScrollbarModule,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,51 +1,51 @@
|
|||||||
import { Routes } from '@angular/router';
|
import { Routes } from '@angular/router';
|
||||||
import { BlankComponent } from './layouts/blank/blank.component';
|
import { BlankComponent } from './layouts/blank/blank.component';
|
||||||
import { FullComponent } from './layouts/full/full.component';
|
import { FullComponent } from './layouts/full/full.component';
|
||||||
|
|
||||||
export const routes: Routes = [
|
export const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: FullComponent,
|
component: FullComponent,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
redirectTo: '/dashboard',
|
redirectTo: '/dashboard',
|
||||||
pathMatch: 'full',
|
pathMatch: 'full',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'dashboard',
|
path: 'dashboard',
|
||||||
loadChildren: () =>
|
loadChildren: () =>
|
||||||
import('./pages/pages.routes').then((m) => m.PagesRoutes),
|
import('./pages/pages.routes').then((m) => m.PagesRoutes),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'ui-components',
|
path: 'ui-components',
|
||||||
loadChildren: () =>
|
loadChildren: () =>
|
||||||
import('./pages/ui-components/ui-components.routes').then(
|
import('./pages/ui-components/ui-components.routes').then(
|
||||||
(m) => m.UiComponentsRoutes
|
(m) => m.UiComponentsRoutes
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'extra',
|
path: 'extra',
|
||||||
loadChildren: () =>
|
loadChildren: () =>
|
||||||
import('./pages/extra/extra.routes').then((m) => m.ExtraRoutes),
|
import('./pages/extra/extra.routes').then((m) => m.ExtraRoutes),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: BlankComponent,
|
component: BlankComponent,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'authentication',
|
path: 'authentication',
|
||||||
loadChildren: () =>
|
loadChildren: () =>
|
||||||
import('./pages/authentication/authentication.routes').then(
|
import('./pages/authentication/authentication.routes').then(
|
||||||
(m) => m.AuthenticationRoutes
|
(m) => m.AuthenticationRoutes
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '**',
|
path: '**',
|
||||||
redirectTo: 'authentication/error',
|
redirectTo: 'authentication/error',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
@for(productcard of productcards; track productcards) {
|
@for(productcard of productcards; track productcards) {
|
||||||
<div class="col-sm-6 col-lg-3">
|
<div class="col-sm-6 col-lg-3">
|
||||||
<mat-card class="cardWithShadow productcard overflow-hidden">
|
<mat-card class="cardWithShadow productcard overflow-hidden">
|
||||||
<a routerLink="/widgets/cards">
|
<a routerLink="/widgets/cards">
|
||||||
<img src="{{ productcard.imgSrc }}" alt="imgSrc" class="w-100" mat-card-image />
|
<img src="{{ productcard.imgSrc }}" alt="imgSrc" class="w-100" mat-card-image />
|
||||||
</a>
|
</a>
|
||||||
<mat-card-content class="p-b-24 p-t-12 position-relative">
|
<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">
|
<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>
|
<i-tabler name="basket" class="icon-16"></i-tabler>
|
||||||
</button>
|
</button>
|
||||||
<mat-card-title class="mat-headline-2 f-s-16 m-b-4">{{
|
<mat-card-title class="mat-headline-2 f-s-16 m-b-4">{{
|
||||||
productcard.title
|
productcard.title
|
||||||
}}</mat-card-title>
|
}}</mat-card-title>
|
||||||
<div class="d-flex align-items-center justify-content-between">
|
<div class="d-flex align-items-center justify-content-between">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<h6 class="f-w-600 f-s-16">${{ productcard.price }}</h6>
|
<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>
|
<span class="f-s-14 m-l-4 text-decoration-line-through">${{ productcard.rprice }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="m-l-auto d-flex gap-4">
|
<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>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@@ -1,53 +1,53 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { MatCardModule } from '@angular/material/card';
|
import { MatCardModule } from '@angular/material/card';
|
||||||
import { TablerIconsModule } from 'angular-tabler-icons';
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
|
|
||||||
// ecommerce card
|
// ecommerce card
|
||||||
interface productCards {
|
interface productCards {
|
||||||
id: number;
|
id: number;
|
||||||
imgSrc: string;
|
imgSrc: string;
|
||||||
title: string;
|
title: string;
|
||||||
price: string;
|
price: string;
|
||||||
rprice: string;
|
rprice: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-blog-card',
|
selector: 'app-blog-card',
|
||||||
imports: [MatCardModule, TablerIconsModule, MatButtonModule],
|
imports: [MatCardModule, TablerIconsModule, MatButtonModule],
|
||||||
templateUrl: './blog-card.component.html',
|
templateUrl: './blog-card.component.html',
|
||||||
})
|
})
|
||||||
export class AppBlogCardsComponent {
|
export class AppBlogCardsComponent {
|
||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
productcards: productCards[] = [
|
productcards: productCards[] = [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
imgSrc: '/assets/images/products/s4.jpg',
|
imgSrc: '/assets/images/products/s4.jpg',
|
||||||
title: 'Boat Headphone',
|
title: 'Boat Headphone',
|
||||||
price: '285',
|
price: '285',
|
||||||
rprice: '375',
|
rprice: '375',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
imgSrc: '/assets/images/products/s5.jpg',
|
imgSrc: '/assets/images/products/s5.jpg',
|
||||||
title: 'MacBook Air Pro',
|
title: 'MacBook Air Pro',
|
||||||
price: '285',
|
price: '285',
|
||||||
rprice: '375',
|
rprice: '375',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
imgSrc: '/assets/images/products/s7.jpg',
|
imgSrc: '/assets/images/products/s7.jpg',
|
||||||
title: 'Red Valvet Dress',
|
title: 'Red Valvet Dress',
|
||||||
price: '285',
|
price: '285',
|
||||||
rprice: '375',
|
rprice: '375',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 4,
|
id: 4,
|
||||||
imgSrc: '/assets/images/products/s11.jpg',
|
imgSrc: '/assets/images/products/s11.jpg',
|
||||||
title: 'Cute Soft Teddybear',
|
title: 'Cute Soft Teddybear',
|
||||||
price: '285',
|
price: '285',
|
||||||
rprice: '375',
|
rprice: '375',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
<mat-card class="cardWithShadow overflow-hidden">
|
<mat-card class="cardWithShadow overflow-hidden">
|
||||||
<mat-card-content class="p-b-0">
|
<mat-card-content class="p-b-0">
|
||||||
<div class="d-flex align-items-center m-b-8">
|
<div class="d-flex align-items-center m-b-8">
|
||||||
<mat-card-title>Monthly Earnings</mat-card-title>
|
<mat-card-title>Monthly Earnings</mat-card-title>
|
||||||
<div class="m-l-auto">
|
<div class="m-l-auto">
|
||||||
<button mat-fab class="icon-48 bg-secondary ">
|
<button mat-fab class="icon-48 bg-secondary ">
|
||||||
<i-tabler name="currency-dollar" class="text-white d-flex"></i-tabler>
|
<i-tabler name="currency-dollar" class="text-white d-flex"></i-tabler>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h4 class="f-s-24 m-b-6">$6,820</h4>
|
<h4 class="f-s-24 m-b-6">$6,820</h4>
|
||||||
<div class="d-flex align-items-center m-t-16">
|
<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">
|
<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>
|
<i-tabler name="arrow-down-right" class="icon-20 d-flex align-items-center"></i-tabler>
|
||||||
</button>
|
</button>
|
||||||
<div class="f-s-14 f-w-600 m-l-12">+9%</div>
|
<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 class="f-s-14 m-l-4">last year</div>
|
||||||
</div>
|
</div>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<apx-chart [series]="monthlyChart.series" [dataLabels]="monthlyChart.dataLabels" [chart]="monthlyChart.chart"
|
<apx-chart [series]="monthlyChart.series" [dataLabels]="monthlyChart.dataLabels" [chart]="monthlyChart.chart"
|
||||||
[legend]="monthlyChart.legend" [colors]="monthlyChart.colors" [stroke]="monthlyChart.stroke"
|
[legend]="monthlyChart.legend" [colors]="monthlyChart.colors" [stroke]="monthlyChart.stroke"
|
||||||
[tooltip]="monthlyChart.tooltip" [plotOptions]="monthlyChart.plotOptions"
|
[tooltip]="monthlyChart.tooltip" [plotOptions]="monthlyChart.plotOptions"
|
||||||
[responsive]="monthlyChart.responsive"></apx-chart>
|
[responsive]="monthlyChart.responsive"></apx-chart>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
@@ -1,81 +1,81 @@
|
|||||||
import { Component, ViewChild } from '@angular/core';
|
import { Component, ViewChild } from '@angular/core';
|
||||||
import {
|
import {
|
||||||
ApexChart,
|
ApexChart,
|
||||||
ChartComponent,
|
ChartComponent,
|
||||||
ApexDataLabels,
|
ApexDataLabels,
|
||||||
ApexLegend,
|
ApexLegend,
|
||||||
ApexStroke,
|
ApexStroke,
|
||||||
ApexTooltip,
|
ApexTooltip,
|
||||||
ApexAxisChartSeries,
|
ApexAxisChartSeries,
|
||||||
ApexPlotOptions,
|
ApexPlotOptions,
|
||||||
ApexResponsive,
|
ApexResponsive,
|
||||||
NgApexchartsModule,
|
NgApexchartsModule,
|
||||||
} from 'ng-apexcharts';
|
} from 'ng-apexcharts';
|
||||||
|
|
||||||
import { TablerIconsModule } from 'angular-tabler-icons';
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
import { MaterialModule } from 'src/app/material.module';
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
|
||||||
export interface monthlyChart {
|
export interface monthlyChart {
|
||||||
series: ApexAxisChartSeries;
|
series: ApexAxisChartSeries;
|
||||||
chart: ApexChart;
|
chart: ApexChart;
|
||||||
dataLabels: ApexDataLabels;
|
dataLabels: ApexDataLabels;
|
||||||
plotOptions: ApexPlotOptions;
|
plotOptions: ApexPlotOptions;
|
||||||
tooltip: ApexTooltip;
|
tooltip: ApexTooltip;
|
||||||
stroke: ApexStroke;
|
stroke: ApexStroke;
|
||||||
legend: ApexLegend;
|
legend: ApexLegend;
|
||||||
responsive: ApexResponsive;
|
responsive: ApexResponsive;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-monthly-earnings',
|
selector: 'app-monthly-earnings',
|
||||||
imports: [NgApexchartsModule, MaterialModule, TablerIconsModule],
|
imports: [NgApexchartsModule, MaterialModule, TablerIconsModule],
|
||||||
templateUrl: './monthly-earnings.component.html',
|
templateUrl: './monthly-earnings.component.html',
|
||||||
})
|
})
|
||||||
export class AppMonthlyEarningsComponent {
|
export class AppMonthlyEarningsComponent {
|
||||||
@ViewChild('chart') chart: ChartComponent = Object.create(null);
|
@ViewChild('chart') chart: ChartComponent = Object.create(null);
|
||||||
public monthlyChart!: Partial<monthlyChart> | any;
|
public monthlyChart!: Partial<monthlyChart> | any;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.monthlyChart = {
|
this.monthlyChart = {
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: '',
|
name: '',
|
||||||
color: '#49BEFF',
|
color: '#49BEFF',
|
||||||
data: [25, 66, 20, 40, 12, 58, 20],
|
data: [25, 66, 20, 40, 12, 58, 20],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
chart: {
|
chart: {
|
||||||
type: 'area',
|
type: 'area',
|
||||||
fontFamily: "'Plus Jakarta Sans', sans-serif;",
|
fontFamily: "'Plus Jakarta Sans', sans-serif;",
|
||||||
foreColor: '#adb0bb',
|
foreColor: '#adb0bb',
|
||||||
toolbar: {
|
toolbar: {
|
||||||
show: false,
|
show: false,
|
||||||
},
|
},
|
||||||
height: 85,
|
height: 85,
|
||||||
sparkline: {
|
sparkline: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
group: 'sparklines',
|
group: 'sparklines',
|
||||||
},
|
},
|
||||||
stroke: {
|
stroke: {
|
||||||
curve: 'smooth',
|
curve: 'smooth',
|
||||||
width: 2,
|
width: 2,
|
||||||
},
|
},
|
||||||
fill: {
|
fill: {
|
||||||
colors: ['#E8F7FF'],
|
colors: ['#E8F7FF'],
|
||||||
type: 'solid',
|
type: 'solid',
|
||||||
opacity: 0.05,
|
opacity: 0.05,
|
||||||
},
|
},
|
||||||
markers: {
|
markers: {
|
||||||
size: 0,
|
size: 0,
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
theme: 'dark',
|
theme: 'dark',
|
||||||
x: {
|
x: {
|
||||||
show: false,
|
show: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,98 +1,98 @@
|
|||||||
<mat-card class="cardWithShadow">
|
<mat-card class="cardWithShadow">
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<div class="m-r-auto">
|
<div class="m-r-auto">
|
||||||
<mat-card-title>Top Projects</mat-card-title>
|
<mat-card-title>Top Projects</mat-card-title>
|
||||||
<mat-card-subtitle>Best Products</mat-card-subtitle>
|
<mat-card-subtitle>Best Products</mat-card-subtitle>
|
||||||
</div>
|
</div>
|
||||||
<mat-form-field class="theme-select" appearance="outline">
|
<mat-form-field class="theme-select" appearance="outline">
|
||||||
<mat-select value="mar">
|
<mat-select value="mar">
|
||||||
@for(month of months; track month.value) {
|
@for(month of months; track month.value) {
|
||||||
<mat-option [value]="month.value">
|
<mat-option [value]="month.value">
|
||||||
{{ month.viewValue }}
|
{{ month.viewValue }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
}
|
}
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table mat-table [dataSource]="dataSource" class="w-100">
|
<table mat-table [dataSource]="dataSource" class="w-100">
|
||||||
<!-- Position Column -->
|
<!-- Position Column -->
|
||||||
<ng-container matColumnDef="product">
|
<ng-container matColumnDef="product">
|
||||||
<th mat-header-cell *matHeaderCellDef class="f-w-600 f-s-14 p-l-0">
|
<th mat-header-cell *matHeaderCellDef class="f-w-600 f-s-14 p-l-0">
|
||||||
Product
|
Product
|
||||||
</th>
|
</th>
|
||||||
<td mat-cell *matCellDef="let element" class="p-l-0">
|
<td mat-cell *matCellDef="let element" class="p-l-0">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<img [src]="element.imagePath" alt="users" width="48" class="rounded" />
|
<img [src]="element.imagePath" alt="users" width="48" class="rounded" />
|
||||||
<div class="m-l-16">
|
<div class="m-l-16">
|
||||||
<h6 class="f-s-14 f-w-600">
|
<h6 class="f-s-14 f-w-600">
|
||||||
{{ element.pname }}
|
{{ element.pname }}
|
||||||
</h6>
|
</h6>
|
||||||
<span class=" f-s-12">
|
<span class=" f-s-12">
|
||||||
{{ element.category }}
|
{{ element.category }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<!-- Name Column -->
|
<!-- Name Column -->
|
||||||
<ng-container matColumnDef="progress">
|
<ng-container matColumnDef="progress">
|
||||||
<th mat-header-cell *matHeaderCellDef class="f-w-600 f-s-14">
|
<th mat-header-cell *matHeaderCellDef class="f-w-600 f-s-14">
|
||||||
Progress
|
Progress
|
||||||
</th>
|
</th>
|
||||||
<td mat-cell *matCellDef="let element">
|
<td mat-cell *matCellDef="let element">
|
||||||
{{ element.progress }}%
|
{{ element.progress }}%
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<!-- Weight Column -->
|
<!-- Weight Column -->
|
||||||
<ng-container matColumnDef="status">
|
<ng-container matColumnDef="status">
|
||||||
<th mat-header-cell *matHeaderCellDef class="f-w-600 f-s-14">
|
<th mat-header-cell *matHeaderCellDef class="f-w-600 f-s-14">
|
||||||
Status
|
Status
|
||||||
</th>
|
</th>
|
||||||
<td mat-cell *matCellDef="let element">
|
<td mat-cell *matCellDef="let element">
|
||||||
@if(element.status == 'low') {
|
@if(element.status == 'low') {
|
||||||
<span class="bg-light-success text-success rounded f-w-600 p-6 p-y-4 f-s-12">
|
<span class="bg-light-success text-success rounded f-w-600 p-6 p-y-4 f-s-12">
|
||||||
{{ element.status | titlecase }}
|
{{ element.status | titlecase }}
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if(element.status == 'medium') {
|
@if(element.status == 'medium') {
|
||||||
<span class="bg-light-warning text-warning rounded f-w-600 p-6 p-y-4 f-s-12">
|
<span class="bg-light-warning text-warning rounded f-w-600 p-6 p-y-4 f-s-12">
|
||||||
{{ element.status | titlecase }}
|
{{ element.status | titlecase }}
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if(element.status == 'high') {
|
@if(element.status == 'high') {
|
||||||
<span class="bg-light-primary text-primary rounded f-w-600 p-6 p-y-4 f-s-12">
|
<span class="bg-light-primary text-primary rounded f-w-600 p-6 p-y-4 f-s-12">
|
||||||
{{ element.status | titlecase }}
|
{{ element.status | titlecase }}
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if(element.status == 'critical') {
|
@if(element.status == 'critical') {
|
||||||
<span class="bg-light-error text-error rounded f-w-600 p-6 p-y-4 f-s-12">
|
<span class="bg-light-error text-error rounded f-w-600 p-6 p-y-4 f-s-12">
|
||||||
{{ element.status | titlecase }}
|
{{ element.status | titlecase }}
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<!-- Symbol Column -->
|
<!-- Symbol Column -->
|
||||||
<ng-container matColumnDef="sales">
|
<ng-container matColumnDef="sales">
|
||||||
<th mat-header-cell *matHeaderCellDef class="f-w-600 f-s-14">
|
<th mat-header-cell *matHeaderCellDef class="f-w-600 f-s-14">
|
||||||
Sales
|
Sales
|
||||||
</th>
|
</th>
|
||||||
<td mat-cell *matCellDef="let element">
|
<td mat-cell *matCellDef="let element">
|
||||||
${{ element.sales }}k
|
${{ element.sales }}k
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
@@ -1,80 +1,80 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { NgApexchartsModule } from 'ng-apexcharts';
|
import { NgApexchartsModule } from 'ng-apexcharts';
|
||||||
import { TablerIconsModule } from 'angular-tabler-icons';
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { MaterialModule } from 'src/app/material.module';
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
|
||||||
export interface performanceData {
|
export interface performanceData {
|
||||||
id: number;
|
id: number;
|
||||||
imagePath: string;
|
imagePath: string;
|
||||||
pname: string;
|
pname: string;
|
||||||
category: string;
|
category: string;
|
||||||
progress: number;
|
progress: number;
|
||||||
sales: number;
|
sales: number;
|
||||||
status: string;
|
status: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ELEMENT_DATA: performanceData[] = [
|
const ELEMENT_DATA: performanceData[] = [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
imagePath: 'assets/images/products/s6.jpg',
|
imagePath: 'assets/images/products/s6.jpg',
|
||||||
pname: 'Gaming Console',
|
pname: 'Gaming Console',
|
||||||
category: 'Electronics',
|
category: 'Electronics',
|
||||||
progress: 78.5,
|
progress: 78.5,
|
||||||
sales: 3.9,
|
sales: 3.9,
|
||||||
status: 'low',
|
status: 'low',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
imagePath: 'assets/images/products/s9.jpg',
|
imagePath: 'assets/images/products/s9.jpg',
|
||||||
pname: 'Leather Purse',
|
pname: 'Leather Purse',
|
||||||
category: 'Fashion',
|
category: 'Fashion',
|
||||||
progress: 58.6,
|
progress: 58.6,
|
||||||
sales: 3.5,
|
sales: 3.5,
|
||||||
status: 'medium',
|
status: 'medium',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
imagePath: 'assets/images/products/s7.jpg',
|
imagePath: 'assets/images/products/s7.jpg',
|
||||||
pname: 'Red Velvate Dress',
|
pname: 'Red Velvate Dress',
|
||||||
category: 'Womens Fashion',
|
category: 'Womens Fashion',
|
||||||
progress: 25,
|
progress: 25,
|
||||||
sales: 3.8,
|
sales: 3.8,
|
||||||
status: 'high',
|
status: 'high',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 4,
|
id: 4,
|
||||||
imagePath: 'assets/images/products/s4.jpg',
|
imagePath: 'assets/images/products/s4.jpg',
|
||||||
pname: 'Headphone Boat',
|
pname: 'Headphone Boat',
|
||||||
category: 'Electronics',
|
category: 'Electronics',
|
||||||
progress: 96.3,
|
progress: 96.3,
|
||||||
sales: 3.54,
|
sales: 3.54,
|
||||||
status: 'critical',
|
status: 'critical',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
interface month {
|
interface month {
|
||||||
value: string;
|
value: string;
|
||||||
viewValue: string;
|
viewValue: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-product-performance',
|
selector: 'app-product-performance',
|
||||||
imports: [
|
imports: [
|
||||||
NgApexchartsModule,
|
NgApexchartsModule,
|
||||||
MaterialModule,
|
MaterialModule,
|
||||||
TablerIconsModule,
|
TablerIconsModule,
|
||||||
CommonModule,
|
CommonModule,
|
||||||
],
|
],
|
||||||
templateUrl: './product-performance.component.html',
|
templateUrl: './product-performance.component.html',
|
||||||
})
|
})
|
||||||
export class AppProductPerformanceComponent {
|
export class AppProductPerformanceComponent {
|
||||||
displayedColumns: string[] = ['product', 'progress', 'status', 'sales'];
|
displayedColumns: string[] = ['product', 'progress', 'status', 'sales'];
|
||||||
dataSource = ELEMENT_DATA;
|
dataSource = ELEMENT_DATA;
|
||||||
|
|
||||||
months: month[] = [
|
months: month[] = [
|
||||||
{ value: 'mar', viewValue: 'March 2025' },
|
{ value: 'mar', viewValue: 'March 2025' },
|
||||||
{ value: 'apr', viewValue: 'April 2025' },
|
{ value: 'apr', viewValue: 'April 2025' },
|
||||||
{ value: 'june', viewValue: 'June 2025' },
|
{ value: 'june', viewValue: 'June 2025' },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,33 @@
|
|||||||
<mat-card class="cardWithShadow">
|
<mat-card class="cardWithShadow">
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<mat-card-title>Recent Transactions</mat-card-title>
|
<mat-card-title>Recent Transactions</mat-card-title>
|
||||||
|
|
||||||
<div class="timeline m-t-24">
|
<div class="timeline m-t-24">
|
||||||
@for(stat of stats; track stat.title) {
|
@for(stat of stats; track stat.title) {
|
||||||
<div class="timeline-item d-flex overflow-hidden">
|
<div class="timeline-item d-flex overflow-hidden">
|
||||||
<div class="time text-right f-s-14">{{ stat.time }}</div>
|
<div class="time text-right f-s-14">{{ stat.time }}</div>
|
||||||
<div class="point d-flex align-items-center">
|
<div class="point d-flex align-items-center">
|
||||||
<span class="timeline-badge border-{{ stat.color }} m-y-8"></span>
|
<span class="timeline-badge border-{{ stat.color }} m-y-8"></span>
|
||||||
<span class="timline-border d-block"></span>
|
<span class="timline-border d-block"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="desc">
|
<div class="desc">
|
||||||
@if(stat.subtext) {
|
@if(stat.subtext) {
|
||||||
<span class="f-s-14 lh-20">{{ stat.subtext }}</span>
|
<span class="f-s-14 lh-20">{{ stat.subtext }}</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if(stat.title) {
|
@if(stat.title) {
|
||||||
<span class="f-s-14 lh-20 f-w-600 d-block">{{
|
<span class="f-s-14 lh-20 f-w-600 d-block">{{
|
||||||
stat.title
|
stat.title
|
||||||
}}</span>
|
}}</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if(stat.link) {
|
@if(stat.link) {
|
||||||
<a href="#" class="text-primary text-decoration-none f-s-14">#ML-3467</a>
|
<a href="#" class="text-primary text-decoration-none f-s-14">#ML-3467</a>
|
||||||
}
|
}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
@@ -1,62 +1,62 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { NgApexchartsModule } from 'ng-apexcharts';
|
import { NgApexchartsModule } from 'ng-apexcharts';
|
||||||
import { MaterialModule } from 'src/app/material.module';
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
|
||||||
|
|
||||||
interface stats {
|
interface stats {
|
||||||
id: number;
|
id: number;
|
||||||
time: string;
|
time: string;
|
||||||
color: string;
|
color: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
subtext?: string;
|
subtext?: string;
|
||||||
link?: string;
|
link?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-recent-transactions',
|
selector: 'app-recent-transactions',
|
||||||
imports: [NgApexchartsModule, MaterialModule],
|
imports: [NgApexchartsModule, MaterialModule],
|
||||||
templateUrl: './recent-transactions.component.html',
|
templateUrl: './recent-transactions.component.html',
|
||||||
})
|
})
|
||||||
export class AppRecentTransactionsComponent {
|
export class AppRecentTransactionsComponent {
|
||||||
stats: stats[] = [
|
stats: stats[] = [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
time: '09.30 am',
|
time: '09.30 am',
|
||||||
color: 'primary',
|
color: 'primary',
|
||||||
subtext: 'Payment received from John Doe of $385.90',
|
subtext: 'Payment received from John Doe of $385.90',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
time: '10.30 am',
|
time: '10.30 am',
|
||||||
color: 'accent',
|
color: 'accent',
|
||||||
title: 'New sale recorded',
|
title: 'New sale recorded',
|
||||||
link: '#ML-3467',
|
link: '#ML-3467',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
time: '12.30 pm',
|
time: '12.30 pm',
|
||||||
color: 'success',
|
color: 'success',
|
||||||
subtext: 'Payment was made of $64.95 to Michael',
|
subtext: 'Payment was made of $64.95 to Michael',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 4,
|
id: 4,
|
||||||
time: '12.30 pm',
|
time: '12.30 pm',
|
||||||
color: 'warning',
|
color: 'warning',
|
||||||
title: 'New sale recorded',
|
title: 'New sale recorded',
|
||||||
link: '#ML-3467',
|
link: '#ML-3467',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 5,
|
id: 5,
|
||||||
time: '12.30 pm',
|
time: '12.30 pm',
|
||||||
color: 'error',
|
color: 'error',
|
||||||
title: 'New arrival recorded',
|
title: 'New arrival recorded',
|
||||||
link: '#ML-3467',
|
link: '#ML-3467',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 6,
|
id: 6,
|
||||||
time: '12.30 pm',
|
time: '12.30 pm',
|
||||||
color: 'success',
|
color: 'success',
|
||||||
subtext: 'Payment Done',
|
subtext: 'Payment Done',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
<mat-card class="cardWithShadow">
|
<mat-card class="cardWithShadow">
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<div class="d-flex w-100">
|
<div class="d-flex w-100">
|
||||||
<mat-card-title>Sales Overview</mat-card-title>
|
<mat-card-title>Sales Overview</mat-card-title>
|
||||||
<div class="m-l-auto">
|
<div class="m-l-auto">
|
||||||
<mat-form-field class="theme-select" appearance="outline">
|
<mat-form-field class="theme-select" appearance="outline">
|
||||||
<mat-select value="mar">
|
<mat-select value="mar">
|
||||||
@for(month of months; track month.viewValue ) {
|
@for(month of months; track month.viewValue ) {
|
||||||
<mat-option [value]="month.value">
|
<mat-option [value]="month.value">
|
||||||
{{ month.viewValue }}
|
{{ month.viewValue }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
}
|
}
|
||||||
</mat-select>
|
</mat-select>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<apx-chart [series]="salesOverviewChart.series" [dataLabels]="salesOverviewChart.dataLabels"
|
<apx-chart [series]="salesOverviewChart.series" [dataLabels]="salesOverviewChart.dataLabels"
|
||||||
[chart]="salesOverviewChart.chart" [legend]="salesOverviewChart.legend" [xaxis]="salesOverviewChart.xaxis"
|
[chart]="salesOverviewChart.chart" [legend]="salesOverviewChart.legend" [xaxis]="salesOverviewChart.xaxis"
|
||||||
[yaxis]="salesOverviewChart.yaxis" [grid]="salesOverviewChart.grid" [stroke]="salesOverviewChart.stroke"
|
[yaxis]="salesOverviewChart.yaxis" [grid]="salesOverviewChart.grid" [stroke]="salesOverviewChart.stroke"
|
||||||
[tooltip]="salesOverviewChart.tooltip" [plotOptions]="salesOverviewChart.plotOptions"></apx-chart>
|
[tooltip]="salesOverviewChart.tooltip" [plotOptions]="salesOverviewChart.plotOptions"></apx-chart>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
@@ -1,153 +1,153 @@
|
|||||||
import { Component, ViewChild } from '@angular/core';
|
import { Component, ViewChild } from '@angular/core';
|
||||||
import { TablerIconsModule } from 'angular-tabler-icons';
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
import { MaterialModule } from 'src/app/material.module';
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ApexChart,
|
ApexChart,
|
||||||
ChartComponent,
|
ChartComponent,
|
||||||
ApexDataLabels,
|
ApexDataLabels,
|
||||||
ApexLegend,
|
ApexLegend,
|
||||||
ApexStroke,
|
ApexStroke,
|
||||||
ApexTooltip,
|
ApexTooltip,
|
||||||
ApexAxisChartSeries,
|
ApexAxisChartSeries,
|
||||||
ApexXAxis,
|
ApexXAxis,
|
||||||
ApexYAxis,
|
ApexYAxis,
|
||||||
ApexGrid,
|
ApexGrid,
|
||||||
ApexPlotOptions,
|
ApexPlotOptions,
|
||||||
ApexFill,
|
ApexFill,
|
||||||
ApexMarkers,
|
ApexMarkers,
|
||||||
ApexResponsive,
|
ApexResponsive,
|
||||||
NgApexchartsModule,
|
NgApexchartsModule,
|
||||||
} from 'ng-apexcharts';
|
} from 'ng-apexcharts';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
|
||||||
interface month {
|
interface month {
|
||||||
value: string;
|
value: string;
|
||||||
viewValue: string;
|
viewValue: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface salesOverviewChart {
|
export interface salesOverviewChart {
|
||||||
series: ApexAxisChartSeries;
|
series: ApexAxisChartSeries;
|
||||||
chart: ApexChart;
|
chart: ApexChart;
|
||||||
dataLabels: ApexDataLabels;
|
dataLabels: ApexDataLabels;
|
||||||
plotOptions: ApexPlotOptions;
|
plotOptions: ApexPlotOptions;
|
||||||
yaxis: ApexYAxis;
|
yaxis: ApexYAxis;
|
||||||
xaxis: ApexXAxis;
|
xaxis: ApexXAxis;
|
||||||
fill: ApexFill;
|
fill: ApexFill;
|
||||||
tooltip: ApexTooltip;
|
tooltip: ApexTooltip;
|
||||||
stroke: ApexStroke;
|
stroke: ApexStroke;
|
||||||
legend: ApexLegend;
|
legend: ApexLegend;
|
||||||
grid: ApexGrid;
|
grid: ApexGrid;
|
||||||
marker: ApexMarkers;
|
marker: ApexMarkers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-sales-overview',
|
selector: 'app-sales-overview',
|
||||||
imports: [MaterialModule, TablerIconsModule, NgApexchartsModule, MatButtonModule],
|
imports: [MaterialModule, TablerIconsModule, NgApexchartsModule, MatButtonModule],
|
||||||
templateUrl: './sales-overview.component.html',
|
templateUrl: './sales-overview.component.html',
|
||||||
})
|
})
|
||||||
export class AppSalesOverviewComponent {
|
export class AppSalesOverviewComponent {
|
||||||
|
|
||||||
@ViewChild('chart') chart: ChartComponent = Object.create(null);
|
@ViewChild('chart') chart: ChartComponent = Object.create(null);
|
||||||
|
|
||||||
public salesOverviewChart!: Partial<salesOverviewChart> | any;
|
public salesOverviewChart!: Partial<salesOverviewChart> | any;
|
||||||
|
|
||||||
months: month[] = [
|
months: month[] = [
|
||||||
{ value: 'mar', viewValue: 'Sep 2025' },
|
{ value: 'mar', viewValue: 'Sep 2025' },
|
||||||
{ value: 'apr', viewValue: 'Oct 2025' },
|
{ value: 'apr', viewValue: 'Oct 2025' },
|
||||||
{ value: 'june', viewValue: 'Nov 2025' },
|
{ value: 'june', viewValue: 'Nov 2025' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
||||||
// sales overview chart
|
// sales overview chart
|
||||||
this.salesOverviewChart = {
|
this.salesOverviewChart = {
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: 'Eanings this month',
|
name: 'Eanings this month',
|
||||||
data: [355, 390, 300, 350, 390, 180, 355, 390],
|
data: [355, 390, 300, 350, 390, 180, 355, 390],
|
||||||
color: '#5D87FF',
|
color: '#5D87FF',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Expense this month',
|
name: 'Expense this month',
|
||||||
data: [280, 250, 325, 215, 250, 310, 280, 250],
|
data: [280, 250, 325, 215, 250, 310, 280, 250],
|
||||||
color: '#49BEFF',
|
color: '#49BEFF',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
grid: {
|
grid: {
|
||||||
borderColor: 'rgba(0,0,0,0.1)',
|
borderColor: 'rgba(0,0,0,0.1)',
|
||||||
strokeDashArray: 3,
|
strokeDashArray: 3,
|
||||||
xaxis: {
|
xaxis: {
|
||||||
lines: {
|
lines: {
|
||||||
show: false,
|
show: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plotOptions: {
|
plotOptions: {
|
||||||
bar: { horizontal: false, columnWidth: '35%', borderRadius: [4] },
|
bar: { horizontal: false, columnWidth: '35%', borderRadius: [4] },
|
||||||
},
|
},
|
||||||
chart: {
|
chart: {
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
height: 390,
|
height: 390,
|
||||||
offsetX: -15,
|
offsetX: -15,
|
||||||
toolbar: { show: false },
|
toolbar: { show: false },
|
||||||
foreColor: '#adb0bb',
|
foreColor: '#adb0bb',
|
||||||
fontFamily: 'inherit',
|
fontFamily: 'inherit',
|
||||||
sparkline: { enabled: false },
|
sparkline: { enabled: false },
|
||||||
},
|
},
|
||||||
dataLabels: { enabled: false },
|
dataLabels: { enabled: false },
|
||||||
markers: { size: 0 },
|
markers: { size: 0 },
|
||||||
legend: { show: false },
|
legend: { show: false },
|
||||||
xaxis: {
|
xaxis: {
|
||||||
type: 'category',
|
type: 'category',
|
||||||
categories: [
|
categories: [
|
||||||
'16/08',
|
'16/08',
|
||||||
'17/08',
|
'17/08',
|
||||||
'18/08',
|
'18/08',
|
||||||
'19/08',
|
'19/08',
|
||||||
'20/08',
|
'20/08',
|
||||||
'21/08',
|
'21/08',
|
||||||
'22/08',
|
'22/08',
|
||||||
'23/08',
|
'23/08',
|
||||||
],
|
],
|
||||||
labels: {
|
labels: {
|
||||||
style: { cssClass: 'grey--text lighten-2--text fill-color' },
|
style: { cssClass: 'grey--text lighten-2--text fill-color' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
yaxis: {
|
yaxis: {
|
||||||
show: true,
|
show: true,
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 400,
|
max: 400,
|
||||||
tickAmount: 4,
|
tickAmount: 4,
|
||||||
labels: {
|
labels: {
|
||||||
style: {
|
style: {
|
||||||
cssClass: 'grey--text lighten-2--text fill-color',
|
cssClass: 'grey--text lighten-2--text fill-color',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
stroke: {
|
stroke: {
|
||||||
show: true,
|
show: true,
|
||||||
width: 3,
|
width: 3,
|
||||||
lineCap: 'butt',
|
lineCap: 'butt',
|
||||||
colors: ['transparent'],
|
colors: ['transparent'],
|
||||||
},
|
},
|
||||||
tooltip: { theme: 'light' },
|
tooltip: { theme: 'light' },
|
||||||
|
|
||||||
responsive: [
|
responsive: [
|
||||||
{
|
{
|
||||||
breakpoint: 600,
|
breakpoint: 600,
|
||||||
options: {
|
options: {
|
||||||
plotOptions: {
|
plotOptions: {
|
||||||
bar: {
|
bar: {
|
||||||
borderRadius: 3,
|
borderRadius: 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,34 @@
|
|||||||
<mat-card class="cardWithShadow">
|
<mat-card class="cardWithShadow">
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<mat-card-title>Yearly Breakup</mat-card-title>
|
<mat-card-title>Yearly Breakup</mat-card-title>
|
||||||
<div class="row m-t-24">
|
<div class="row m-t-24">
|
||||||
<div class="col-7">
|
<div class="col-7">
|
||||||
<h4 class="f-s-24">$36,358</h4>
|
<h4 class="f-s-24">$36,358</h4>
|
||||||
<div class="d-flex align-items-center m-t-16">
|
<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">
|
<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>
|
<i-tabler name="arrow-up-right" class="icon-20 d-flex align-items-center"></i-tabler>
|
||||||
</button>
|
</button>
|
||||||
<div class="f-w-600 m-l-12 f-s-14">+9%</div>
|
<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 class="m-l-4 f-s-14">last year</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="d-flex align-items-center m-t-32">
|
<div class="d-flex align-items-center m-t-32">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<i-tabler name="circle-filled" class="text-primary icon-12 d-flex"></i-tabler>
|
<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 class="m-l-12 f-s-14">2025</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex align-items-center m-l-16">
|
<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>
|
<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 class="m-l-12 f-s-14">2024</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-5 d-flex align-items-start">
|
<div class="col-5 d-flex align-items-start">
|
||||||
<apx-chart [series]="yearlyChart.series" [dataLabels]="yearlyChart.dataLabels"
|
<apx-chart [series]="yearlyChart.series" [dataLabels]="yearlyChart.dataLabels"
|
||||||
[chart]="yearlyChart.chart" [legend]="yearlyChart.legend" [colors]="yearlyChart.colors"
|
[chart]="yearlyChart.chart" [legend]="yearlyChart.legend" [colors]="yearlyChart.colors"
|
||||||
[stroke]="yearlyChart.stroke" [tooltip]="yearlyChart.tooltip"
|
[stroke]="yearlyChart.stroke" [tooltip]="yearlyChart.tooltip"
|
||||||
[plotOptions]="yearlyChart.plotOptions" [responsive]="yearlyChart.responsive"></apx-chart>
|
[plotOptions]="yearlyChart.plotOptions" [responsive]="yearlyChart.responsive"></apx-chart>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
@@ -1,101 +1,101 @@
|
|||||||
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
|
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
|
||||||
import { TablerIconsModule } from 'angular-tabler-icons';
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
import {
|
import {
|
||||||
ApexChart,
|
ApexChart,
|
||||||
ChartComponent,
|
ChartComponent,
|
||||||
ApexDataLabels,
|
ApexDataLabels,
|
||||||
ApexLegend,
|
ApexLegend,
|
||||||
ApexStroke,
|
ApexStroke,
|
||||||
ApexTooltip,
|
ApexTooltip,
|
||||||
ApexAxisChartSeries,
|
ApexAxisChartSeries,
|
||||||
ApexXAxis,
|
ApexXAxis,
|
||||||
ApexYAxis,
|
ApexYAxis,
|
||||||
ApexGrid,
|
ApexGrid,
|
||||||
ApexPlotOptions,
|
ApexPlotOptions,
|
||||||
ApexFill,
|
ApexFill,
|
||||||
ApexMarkers,
|
ApexMarkers,
|
||||||
ApexResponsive,
|
ApexResponsive,
|
||||||
NgApexchartsModule,
|
NgApexchartsModule,
|
||||||
} from 'ng-apexcharts';
|
} from 'ng-apexcharts';
|
||||||
import { MaterialModule } from 'src/app/material.module';
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
|
||||||
|
|
||||||
export interface yearlyChart {
|
export interface yearlyChart {
|
||||||
series: ApexAxisChartSeries;
|
series: ApexAxisChartSeries;
|
||||||
chart: ApexChart;
|
chart: ApexChart;
|
||||||
dataLabels: ApexDataLabels;
|
dataLabels: ApexDataLabels;
|
||||||
plotOptions: ApexPlotOptions;
|
plotOptions: ApexPlotOptions;
|
||||||
tooltip: ApexTooltip;
|
tooltip: ApexTooltip;
|
||||||
stroke: ApexStroke;
|
stroke: ApexStroke;
|
||||||
legend: ApexLegend;
|
legend: ApexLegend;
|
||||||
responsive: ApexResponsive;
|
responsive: ApexResponsive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-yearly-breakup',
|
selector: 'app-yearly-breakup',
|
||||||
templateUrl: './yearly-breakup.component.html',
|
templateUrl: './yearly-breakup.component.html',
|
||||||
imports: [MaterialModule, NgApexchartsModule, TablerIconsModule],
|
imports: [MaterialModule, NgApexchartsModule, TablerIconsModule],
|
||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
})
|
})
|
||||||
export class AppYearlyBreakupComponent {
|
export class AppYearlyBreakupComponent {
|
||||||
@ViewChild('chart') chart: ChartComponent = Object.create(null);
|
@ViewChild('chart') chart: ChartComponent = Object.create(null);
|
||||||
|
|
||||||
public yearlyChart!: Partial<yearlyChart> | any;
|
public yearlyChart!: Partial<yearlyChart> | any;
|
||||||
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
||||||
this.yearlyChart = {
|
this.yearlyChart = {
|
||||||
|
|
||||||
color: "#adb5bd",
|
color: "#adb5bd",
|
||||||
series: [38, 40, 25],
|
series: [38, 40, 25],
|
||||||
labels: ["2025", "2024", "2023"],
|
labels: ["2025", "2024", "2023"],
|
||||||
chart: {
|
chart: {
|
||||||
width: 125,
|
width: 125,
|
||||||
type: "donut",
|
type: "donut",
|
||||||
fontFamily: "inherit",
|
fontFamily: "inherit",
|
||||||
foreColor: "#adb0bb",
|
foreColor: "#adb0bb",
|
||||||
},
|
},
|
||||||
plotOptions: {
|
plotOptions: {
|
||||||
pie: {
|
pie: {
|
||||||
startAngle: 0,
|
startAngle: 0,
|
||||||
endAngle: 360,
|
endAngle: 360,
|
||||||
donut: {
|
donut: {
|
||||||
size: "75%",
|
size: "75%",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
stroke: {
|
stroke: {
|
||||||
show: false,
|
show: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
dataLabels: {
|
dataLabels: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
legend: {
|
legend: {
|
||||||
show: false,
|
show: false,
|
||||||
},
|
},
|
||||||
colors: ['#5D87FF', '#ECF2FF', '#F9F9FD'],
|
colors: ['#5D87FF', '#ECF2FF', '#F9F9FD'],
|
||||||
|
|
||||||
responsive: [
|
responsive: [
|
||||||
{
|
{
|
||||||
breakpoint: 991,
|
breakpoint: 991,
|
||||||
options: {
|
options: {
|
||||||
chart: {
|
chart: {
|
||||||
width: 120,
|
width: 120,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
tooltip: {
|
tooltip: {
|
||||||
theme: "dark",
|
theme: "dark",
|
||||||
fillSeriesColor: false,
|
fillSeriesColor: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
export interface AppSettings {
|
export interface AppSettings {
|
||||||
|
|
||||||
sidenavOpened: boolean;
|
sidenavOpened: boolean;
|
||||||
sidenavCollapsed: boolean;
|
sidenavCollapsed: boolean;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaults: AppSettings = {
|
export const defaults: AppSettings = {
|
||||||
sidenavOpened: true,
|
sidenavOpened: true,
|
||||||
sidenavCollapsed: true,
|
sidenavCollapsed: true,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<!-- ============================================================== -->
|
<!-- ============================================================== -->
|
||||||
<!-- Only router without any element -->
|
<!-- Only router without any element -->
|
||||||
<!-- ============================================================== -->
|
<!-- ============================================================== -->
|
||||||
<mat-sidenav-container dir="ltr" class="light-theme">
|
<mat-sidenav-container dir="ltr" class="light-theme">
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
</mat-sidenav-container>
|
</mat-sidenav-container>
|
||||||
@@ -1,23 +1,23 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { CoreService } from 'src/app/services/core.service';
|
import { CoreService } from 'src/app/services/core.service';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { RouterOutlet } from '@angular/router';
|
import { RouterOutlet } from '@angular/router';
|
||||||
import { MaterialModule } from 'src/app/material.module';
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-blank',
|
selector: 'app-blank',
|
||||||
templateUrl: './blank.component.html',
|
templateUrl: './blank.component.html',
|
||||||
styleUrls: [],
|
styleUrls: [],
|
||||||
imports: [RouterOutlet, MaterialModule, CommonModule],
|
imports: [RouterOutlet, MaterialModule, CommonModule],
|
||||||
})
|
})
|
||||||
export class BlankComponent {
|
export class BlankComponent {
|
||||||
private htmlElement!: HTMLHtmlElement;
|
private htmlElement!: HTMLHtmlElement;
|
||||||
|
|
||||||
options = this.settings.getOptions();
|
options = this.settings.getOptions();
|
||||||
|
|
||||||
constructor(private settings: CoreService) {
|
constructor(private settings: CoreService) {
|
||||||
this.htmlElement = document.querySelector('html')!;
|
this.htmlElement = document.querySelector('html')!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,59 +1,59 @@
|
|||||||
|
|
||||||
<app-topstrip></app-topstrip>
|
<app-topstrip></app-topstrip>
|
||||||
<mat-sidenav-container class="mainWrapper blue_theme light-theme" autosize autoFocus dir="ltr">
|
<mat-sidenav-container class="mainWrapper blue_theme light-theme" autosize autoFocus dir="ltr">
|
||||||
<!-- ============================================================== -->
|
<!-- ============================================================== -->
|
||||||
<!-- Vertical Sidebar -->
|
<!-- Vertical Sidebar -->
|
||||||
<!-- ============================================================== -->
|
<!-- ============================================================== -->
|
||||||
<mat-sidenav #leftsidenav [mode]="isOver ? 'over' : 'side'" [opened]="!isOver"
|
<mat-sidenav #leftsidenav [mode]="isOver ? 'over' : 'side'" [opened]="!isOver"
|
||||||
(openedChange)="onSidenavOpenedChange($event)" (closedStart)="onSidenavClosedStart()" class="sidebarNav">
|
(openedChange)="onSidenavOpenedChange($event)" (closedStart)="onSidenavClosedStart()" class="sidebarNav">
|
||||||
<div class="flex-layout">
|
<div class="flex-layout">
|
||||||
<app-sidebar (toggleMobileNav)="sidenav.toggle()" [showToggle]="isOver"></app-sidebar>
|
<app-sidebar (toggleMobileNav)="sidenav.toggle()" [showToggle]="isOver"></app-sidebar>
|
||||||
<ng-scrollbar class="position-relative" style="height: 100%">
|
<ng-scrollbar class="position-relative" style="height: 100%">
|
||||||
<mat-nav-list class="sidebar-list">
|
<mat-nav-list class="sidebar-list">
|
||||||
@for(item of navItems; track item) {
|
@for(item of navItems; track item) {
|
||||||
<app-nav-item [item]="item" (notify)="sidenav.toggle()">
|
<app-nav-item [item]="item" (notify)="sidenav.toggle()">
|
||||||
</app-nav-item>
|
</app-nav-item>
|
||||||
}
|
}
|
||||||
</mat-nav-list>
|
</mat-nav-list>
|
||||||
</ng-scrollbar>
|
</ng-scrollbar>
|
||||||
<div class="p-24">
|
<div class="p-24">
|
||||||
<div class="bg-light-secondary d-flex align-items-center gap-4 rounded p-20 m-t-20">
|
<div class="bg-light-secondary d-flex align-items-center gap-4 rounded p-20 m-t-20">
|
||||||
<div>
|
<div>
|
||||||
<h5 class="f-s-16 f-w-600 m-b-8">
|
<h5 class="f-s-16 f-w-600 m-b-8">
|
||||||
Check Pro <br> Version
|
Check Pro <br> Version
|
||||||
</h5>
|
</h5>
|
||||||
<a mat-flat-button
|
<a mat-flat-button
|
||||||
href="https://adminmart.com/product/modernize-angular-material-dashboard/?ref=56#product-demo-section" target="_blank"
|
href="https://adminmart.com/product/modernize-angular-material-dashboard/?ref=56#product-demo-section" target="_blank"
|
||||||
class="d-flex justify-content-center bg-secondary">
|
class="d-flex justify-content-center bg-secondary">
|
||||||
Check
|
Check
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<img src="/assets/images/backgrounds/rocket.png" alt="imgae" class="side-img m-t--48 m-r--8" />
|
<img src="/assets/images/backgrounds/rocket.png" alt="imgae" class="side-img m-t--48 m-r--8" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</mat-sidenav>
|
</mat-sidenav>
|
||||||
|
|
||||||
<!-- ============================================================== -->
|
<!-- ============================================================== -->
|
||||||
<!-- Main Content -->
|
<!-- Main Content -->
|
||||||
<!-- ============================================================== -->
|
<!-- ============================================================== -->
|
||||||
<mat-sidenav-content class="contentWrapper" #content>
|
<mat-sidenav-content class="contentWrapper" #content>
|
||||||
<!-- ============================================================== -->
|
<!-- ============================================================== -->
|
||||||
<!-- VerticalHeader -->
|
<!-- VerticalHeader -->
|
||||||
<!-- ============================================================== -->
|
<!-- ============================================================== -->
|
||||||
|
|
||||||
<app-header [showToggle]="!isOver" (toggleMobileNav)="sidenav.toggle()"></app-header>
|
<app-header [showToggle]="!isOver" (toggleMobileNav)="sidenav.toggle()"></app-header>
|
||||||
|
|
||||||
<main class="pageWrapper maxWidth">
|
<main class="pageWrapper maxWidth">
|
||||||
<!-- ============================================================== -->
|
<!-- ============================================================== -->
|
||||||
<!-- Outlet -->
|
<!-- Outlet -->
|
||||||
<!-- ============================================================== -->
|
<!-- ============================================================== -->
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<div class="p-16 p-b-30 text-center">
|
<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>
|
Design & Developed by <a class="text-decoration-none" href="https://adminmart.com/" target="_blank">AdminMart.com</a>
|
||||||
</div>
|
</div>
|
||||||
</mat-sidenav-content>
|
</mat-sidenav-content>
|
||||||
|
|
||||||
</mat-sidenav-container>
|
</mat-sidenav-container>
|
||||||
@@ -1,117 +1,117 @@
|
|||||||
import { BreakpointObserver, MediaMatcher } from '@angular/cdk/layout';
|
import { BreakpointObserver, MediaMatcher } from '@angular/cdk/layout';
|
||||||
import { Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
|
import { Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { MatSidenav, MatSidenavContent } from '@angular/material/sidenav';
|
import { MatSidenav, MatSidenavContent } from '@angular/material/sidenav';
|
||||||
import { CoreService } from 'src/app/services/core.service';
|
import { CoreService } from 'src/app/services/core.service';
|
||||||
|
|
||||||
import { filter } from 'rxjs/operators';
|
import { filter } from 'rxjs/operators';
|
||||||
import { NavigationEnd, Router } from '@angular/router';
|
import { NavigationEnd, Router } from '@angular/router';
|
||||||
import { NavService } from '../../services/nav.service';
|
import { NavService } from '../../services/nav.service';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { MaterialModule } from 'src/app/material.module';
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NgScrollbarModule } from 'ngx-scrollbar';
|
import { NgScrollbarModule } from 'ngx-scrollbar';
|
||||||
import { TablerIconsModule } from 'angular-tabler-icons';
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
import { HeaderComponent } from './header/header.component';
|
import { HeaderComponent } from './header/header.component';
|
||||||
import { SidebarComponent } from './sidebar/sidebar.component';
|
import { SidebarComponent } from './sidebar/sidebar.component';
|
||||||
import { AppNavItemComponent } from './sidebar/nav-item/nav-item.component';
|
import { AppNavItemComponent } from './sidebar/nav-item/nav-item.component';
|
||||||
import { navItems } from './sidebar/sidebar-data';
|
import { navItems } from './sidebar/sidebar-data';
|
||||||
import { AppTopstripComponent } from './top-strip/topstrip.component';
|
import { AppTopstripComponent } from './top-strip/topstrip.component';
|
||||||
|
|
||||||
|
|
||||||
const MOBILE_VIEW = 'screen and (max-width: 768px)';
|
const MOBILE_VIEW = 'screen and (max-width: 768px)';
|
||||||
const TABLET_VIEW = 'screen and (min-width: 769px) and (max-width: 1024px)';
|
const TABLET_VIEW = 'screen and (min-width: 769px) and (max-width: 1024px)';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-full',
|
selector: 'app-full',
|
||||||
imports: [
|
imports: [
|
||||||
RouterModule,
|
RouterModule,
|
||||||
AppNavItemComponent,
|
AppNavItemComponent,
|
||||||
MaterialModule,
|
MaterialModule,
|
||||||
CommonModule,
|
CommonModule,
|
||||||
SidebarComponent,
|
SidebarComponent,
|
||||||
NgScrollbarModule,
|
NgScrollbarModule,
|
||||||
TablerIconsModule,
|
TablerIconsModule,
|
||||||
HeaderComponent,
|
HeaderComponent,
|
||||||
AppTopstripComponent
|
AppTopstripComponent
|
||||||
],
|
],
|
||||||
templateUrl: './full.component.html',
|
templateUrl: './full.component.html',
|
||||||
styleUrls: [],
|
styleUrls: [],
|
||||||
encapsulation: ViewEncapsulation.None
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class FullComponent implements OnInit {
|
export class FullComponent implements OnInit {
|
||||||
navItems = navItems;
|
navItems = navItems;
|
||||||
|
|
||||||
@ViewChild('leftsidenav')
|
@ViewChild('leftsidenav')
|
||||||
public sidenav: MatSidenav;
|
public sidenav: MatSidenav;
|
||||||
resView = false;
|
resView = false;
|
||||||
@ViewChild('content', { static: true }) content!: MatSidenavContent;
|
@ViewChild('content', { static: true }) content!: MatSidenavContent;
|
||||||
//get options from service
|
//get options from service
|
||||||
options = this.settings.getOptions();
|
options = this.settings.getOptions();
|
||||||
private layoutChangesSubscription = Subscription.EMPTY;
|
private layoutChangesSubscription = Subscription.EMPTY;
|
||||||
private isMobileScreen = false;
|
private isMobileScreen = false;
|
||||||
private isContentWidthFixed = true;
|
private isContentWidthFixed = true;
|
||||||
private isCollapsedWidthFixed = false;
|
private isCollapsedWidthFixed = false;
|
||||||
private htmlElement!: HTMLHtmlElement;
|
private htmlElement!: HTMLHtmlElement;
|
||||||
|
|
||||||
get isOver(): boolean {
|
get isOver(): boolean {
|
||||||
return this.isMobileScreen;
|
return this.isMobileScreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private settings: CoreService,
|
private settings: CoreService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private breakpointObserver: BreakpointObserver,
|
private breakpointObserver: BreakpointObserver,
|
||||||
) {
|
) {
|
||||||
this.htmlElement = document.querySelector('html')!;
|
this.htmlElement = document.querySelector('html')!;
|
||||||
this.layoutChangesSubscription = this.breakpointObserver
|
this.layoutChangesSubscription = this.breakpointObserver
|
||||||
.observe([MOBILE_VIEW, TABLET_VIEW])
|
.observe([MOBILE_VIEW, TABLET_VIEW])
|
||||||
.subscribe((state) => {
|
.subscribe((state) => {
|
||||||
// SidenavOpened must be reset true when layout changes
|
// SidenavOpened must be reset true when layout changes
|
||||||
this.options.sidenavOpened = true;
|
this.options.sidenavOpened = true;
|
||||||
this.isMobileScreen = state.breakpoints[MOBILE_VIEW];
|
this.isMobileScreen = state.breakpoints[MOBILE_VIEW];
|
||||||
if (this.options.sidenavCollapsed == false) {
|
if (this.options.sidenavCollapsed == false) {
|
||||||
this.options.sidenavCollapsed = state.breakpoints[TABLET_VIEW];
|
this.options.sidenavCollapsed = state.breakpoints[TABLET_VIEW];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initialize project theme with options
|
// Initialize project theme with options
|
||||||
|
|
||||||
|
|
||||||
// This is for scroll to top
|
// This is for scroll to top
|
||||||
this.router.events
|
this.router.events
|
||||||
.pipe(filter((event) => event instanceof NavigationEnd))
|
.pipe(filter((event) => event instanceof NavigationEnd))
|
||||||
.subscribe((e) => {
|
.subscribe((e) => {
|
||||||
this.content.scrollTo({ top: 0 });
|
this.content.scrollTo({ top: 0 });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void { }
|
ngOnInit(): void { }
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.layoutChangesSubscription.unsubscribe();
|
this.layoutChangesSubscription.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleCollapsed() {
|
toggleCollapsed() {
|
||||||
this.isContentWidthFixed = false;
|
this.isContentWidthFixed = false;
|
||||||
this.options.sidenavCollapsed = !this.options.sidenavCollapsed;
|
this.options.sidenavCollapsed = !this.options.sidenavCollapsed;
|
||||||
this.resetCollapsedState();
|
this.resetCollapsedState();
|
||||||
}
|
}
|
||||||
|
|
||||||
resetCollapsedState(timer = 400) {
|
resetCollapsedState(timer = 400) {
|
||||||
setTimeout(() => this.settings.setOptions(this.options), timer);
|
setTimeout(() => this.settings.setOptions(this.options), timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
onSidenavClosedStart() {
|
onSidenavClosedStart() {
|
||||||
this.isContentWidthFixed = false;
|
this.isContentWidthFixed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
onSidenavOpenedChange(isOpened: boolean) {
|
onSidenavOpenedChange(isOpened: boolean) {
|
||||||
this.isCollapsedWidthFixed = !this.isOver;
|
this.isCollapsedWidthFixed = !this.isOver;
|
||||||
this.options.sidenavOpened = isOpened;
|
this.options.sidenavOpened = isOpened;
|
||||||
//this.settings.setOptions(this.options);
|
//this.settings.setOptions(this.options);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,48 +1,48 @@
|
|||||||
<mat-toolbar class="topbar gap-10">
|
<mat-toolbar class="topbar gap-10">
|
||||||
|
|
||||||
<!-- Mobile Menu -->
|
<!-- Mobile Menu -->
|
||||||
|
|
||||||
<button mat-icon-button (click)="toggleMobileNav.emit()" class="d-flex d-lg-none justify-content-center">
|
<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>
|
<i-tabler name="menu-2" class="icon-20 d-flex"></i-tabler>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button mat-icon-button [matMenuTriggerFor]="menu" aria-label="Notifications">
|
<button mat-icon-button [matMenuTriggerFor]="menu" aria-label="Notifications">
|
||||||
<i-tabler class="d-flex" name="bell" matBadge="1" matBadgeColor="primary"></i-tabler>
|
<i-tabler class="d-flex" name="bell" matBadge="1" matBadgeColor="primary"></i-tabler>
|
||||||
</button>
|
</button>
|
||||||
<mat-menu #menu="matMenu">
|
<mat-menu #menu="matMenu">
|
||||||
<button mat-menu-item>Item 1</button>
|
<button mat-menu-item>Item 1</button>
|
||||||
<button mat-menu-item>Item 2</button>
|
<button mat-menu-item>Item 2</button>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
|
|
||||||
|
|
||||||
<span class="flex-1-auto"></span>
|
<span class="flex-1-auto"></span>
|
||||||
|
|
||||||
<!-- --------------------------------------------------------------- -->
|
<!-- --------------------------------------------------------------- -->
|
||||||
<!-- profile Dropdown -->
|
<!-- profile Dropdown -->
|
||||||
<!-- --------------------------------------------------------------- -->
|
<!-- --------------------------------------------------------------- -->
|
||||||
<a mat-flat-button href="https://adminmart.com/product/modernize-angular-admin-dashboard/?ref=56#product-demo-section"
|
<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">
|
target="_blank" class="d-flex justify-content-center bg-success">
|
||||||
Check Pro Template
|
Check Pro Template
|
||||||
</a>
|
</a>
|
||||||
<button mat-mini-fab [matMenuTriggerFor]="profilemenu" aria-label="Notifications">
|
<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" />
|
<img src="/assets/images/profile/user-1.jpg" class="rounded-circle object-cover d-block" width="35" />
|
||||||
</button>
|
</button>
|
||||||
<mat-menu #profilemenu="matMenu" class="cardWithShadow topbar-dd">
|
<mat-menu #profilemenu="matMenu" class="cardWithShadow topbar-dd">
|
||||||
<button mat-menu-item>
|
<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
|
<mat-icon class="d-flex align-items-center"><i-tabler name="user" class="icon-18 d-flex"></i-tabler></mat-icon>My
|
||||||
Profile
|
Profile
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item>
|
<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
|
<mat-icon class="d-flex align-items-center"><i-tabler name="mail" class="icon-18 d-flex"></i-tabler></mat-icon>My
|
||||||
Account
|
Account
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item>
|
<button mat-menu-item>
|
||||||
<mat-icon class="d-flex align-items-center"><i-tabler name="list-check"
|
<mat-icon class="d-flex align-items-center"><i-tabler name="list-check"
|
||||||
class="icon-18 d-flex"></i-tabler></mat-icon>My Task
|
class="icon-18 d-flex"></i-tabler></mat-icon>My Task
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="p-x-12 m-t-12">
|
<div class="p-x-12 m-t-12">
|
||||||
<a [routerLink]="['/authentication/login']" mat-stroked-button class="w-100">Logout</a>
|
<a [routerLink]="['/authentication/login']" mat-stroked-button class="w-100">Logout</a>
|
||||||
</div>
|
</div>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
</mat-toolbar>
|
</mat-toolbar>
|
||||||
@@ -1,30 +1,30 @@
|
|||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
Output,
|
Output,
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
Input,
|
Input,
|
||||||
ViewEncapsulation,
|
ViewEncapsulation,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { TablerIconsModule } from 'angular-tabler-icons';
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
import { MaterialModule } from 'src/app/material.module';
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NgScrollbarModule } from 'ngx-scrollbar';
|
import { NgScrollbarModule } from 'ngx-scrollbar';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-header',
|
selector: 'app-header',
|
||||||
imports: [
|
imports: [
|
||||||
RouterModule,
|
RouterModule,
|
||||||
CommonModule,
|
CommonModule,
|
||||||
NgScrollbarModule,
|
NgScrollbarModule,
|
||||||
TablerIconsModule,
|
TablerIconsModule,
|
||||||
MaterialModule,
|
MaterialModule,
|
||||||
],
|
],
|
||||||
templateUrl: './header.component.html',
|
templateUrl: './header.component.html',
|
||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
})
|
})
|
||||||
export class HeaderComponent {
|
export class HeaderComponent {
|
||||||
@Input() showToggle = true;
|
@Input() showToggle = true;
|
||||||
@Input() toggleChecked = false;
|
@Input() toggleChecked = false;
|
||||||
@Output() toggleMobileNav = new EventEmitter<void>();
|
@Output() toggleMobileNav = new EventEmitter<void>();
|
||||||
}
|
}
|
||||||
@@ -1,20 +1,20 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { CoreService } from 'src/app/services/core.service';
|
import { CoreService } from 'src/app/services/core.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-branding',
|
selector: 'app-branding',
|
||||||
imports: [],
|
imports: [],
|
||||||
template: `
|
template: `
|
||||||
<a href="/" class="logodark">
|
<a href="/" class="logodark">
|
||||||
<img
|
<img
|
||||||
src="./assets/images/logos/dark-logo.svg"
|
src="./assets/images/logos/dark-logo.svg"
|
||||||
class="align-middle m-2"
|
class="align-middle m-2"
|
||||||
alt="logo"
|
alt="logo"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
export class BrandingComponent {
|
export class BrandingComponent {
|
||||||
options = this.settings.getOptions();
|
options = this.settings.getOptions();
|
||||||
constructor(private settings: CoreService) {}
|
constructor(private settings: CoreService) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,48 +1,48 @@
|
|||||||
@if(item.navCap){
|
@if(item.navCap){
|
||||||
<div mat-subheader class="nav-caption">
|
<div mat-subheader class="nav-caption">
|
||||||
{{ item.navCap }}
|
{{ item.navCap }}
|
||||||
</div>
|
</div>
|
||||||
} @if(!item.navCap && !item.external) {
|
} @if(!item.navCap && !item.external) {
|
||||||
<a mat-list-item (click)="onItemSelected(item)" [ngClass]="{
|
<a mat-list-item (click)="onItemSelected(item)" [ngClass]="{
|
||||||
activeMenu: item.route ? router.isActive(item.route, true) : false,
|
activeMenu: item.route ? router.isActive(item.route, true) : false,
|
||||||
expanded: expanded,
|
expanded: expanded,
|
||||||
disabled: item.disabled
|
disabled: item.disabled
|
||||||
}" class="menu-list-item">
|
}" class="menu-list-item">
|
||||||
<i-tabler class="routeIcon" name="{{ item.iconName }}" matListItemIcon></i-tabler>
|
<i-tabler class="routeIcon" name="{{ item.iconName }}" matListItemIcon></i-tabler>
|
||||||
<span class="hide-menu">{{ item.displayName }}</span>
|
<span class="hide-menu">{{ item.displayName }}</span>
|
||||||
|
|
||||||
@if(item.children && item.children.length) {
|
@if(item.children && item.children.length) {
|
||||||
<span class="arrow-icon" fxFlex>
|
<span class="arrow-icon" fxFlex>
|
||||||
<span fxFlex></span>
|
<span fxFlex></span>
|
||||||
@if(item.chip) {
|
@if(item.chip) {
|
||||||
<span>
|
<span>
|
||||||
<span class="{{ item.chipClass }} p-x-8 p-y-4 item-chip f-w-500 rounded-pill ">{{ item.chipContent }}</span>
|
<span class="{{ item.chipClass }} p-x-8 p-y-4 item-chip f-w-500 rounded-pill ">{{ item.chipContent }}</span>
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
<mat-icon [@indicatorRotate]="expanded ? 'expanded' : 'collapsed'">
|
<mat-icon [@indicatorRotate]="expanded ? 'expanded' : 'collapsed'">
|
||||||
expand_more
|
expand_more
|
||||||
</mat-icon>
|
</mat-icon>
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
|
|
||||||
<!-- external Link -->
|
<!-- external Link -->
|
||||||
|
|
||||||
@if(!item.navCap && item.external) {
|
@if(!item.navCap && item.external) {
|
||||||
<mat-list-item (click)="openExternalLink(item.route)" class="menu-list-item" target="_blank">
|
<mat-list-item (click)="openExternalLink(item.route)" class="menu-list-item" target="_blank">
|
||||||
<i-tabler class="routeIcon" name="{{ item.iconName }}" matListItemIcon></i-tabler>
|
<i-tabler class="routeIcon" name="{{ item.iconName }}" matListItemIcon></i-tabler>
|
||||||
<span class="hide-menu">{{ item.displayName }} </span>
|
<span class="hide-menu">{{ item.displayName }} </span>
|
||||||
@if(item.chip) {
|
@if(item.chip) {
|
||||||
<span>
|
<span>
|
||||||
<span class="{{ item.chipClass }} p-x-8 p-y-4 item-chip f-w-500 rounded-pill ">{{ item.chipContent }}</span>
|
<span class="{{ item.chipClass }} p-x-8 p-y-4 item-chip f-w-500 rounded-pill ">{{ item.chipContent }}</span>
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
</mat-list-item>
|
</mat-list-item>
|
||||||
}
|
}
|
||||||
|
|
||||||
<!-- children -->
|
<!-- children -->
|
||||||
@if(expanded) { @for(child of item.children; track child) {
|
@if(expanded) { @for(child of item.children; track child) {
|
||||||
<app-nav-item [item]="child" (click)="onSubItemSelected(child)" [depth]="depth + 1">
|
<app-nav-item [item]="child" (click)="onSubItemSelected(child)" [depth]="depth + 1">
|
||||||
</app-nav-item>
|
</app-nav-item>
|
||||||
} }
|
} }
|
||||||
@@ -1,77 +1,77 @@
|
|||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
HostBinding,
|
HostBinding,
|
||||||
Input,
|
Input,
|
||||||
OnChanges,
|
OnChanges,
|
||||||
Output,
|
Output,
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { NavItem } from './nav-item';
|
import { NavItem } from './nav-item';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { NavService } from '../../../../services/nav.service';
|
import { NavService } from '../../../../services/nav.service';
|
||||||
|
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { TablerIconsModule } from 'angular-tabler-icons';
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
import { MaterialModule } from 'src/app/material.module';
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-nav-item',
|
selector: 'app-nav-item',
|
||||||
imports: [TranslateModule, TablerIconsModule, MaterialModule, CommonModule],
|
imports: [TranslateModule, TablerIconsModule, MaterialModule, CommonModule],
|
||||||
templateUrl: './nav-item.component.html',
|
templateUrl: './nav-item.component.html',
|
||||||
styleUrls: [],
|
styleUrls: [],
|
||||||
})
|
})
|
||||||
export class AppNavItemComponent implements OnChanges {
|
export class AppNavItemComponent implements OnChanges {
|
||||||
@Output() notify: EventEmitter<boolean> = new EventEmitter<boolean>();
|
@Output() notify: EventEmitter<boolean> = new EventEmitter<boolean>();
|
||||||
|
|
||||||
@Input() item: NavItem | any;
|
@Input() item: NavItem | any;
|
||||||
|
|
||||||
expanded: any = false;
|
expanded: any = false;
|
||||||
|
|
||||||
@HostBinding('attr.aria-expanded') ariaExpanded = this.expanded;
|
@HostBinding('attr.aria-expanded') ariaExpanded = this.expanded;
|
||||||
@Input() depth: any;
|
@Input() depth: any;
|
||||||
|
|
||||||
constructor(public navService: NavService, public router: Router) {}
|
constructor(public navService: NavService, public router: Router) {}
|
||||||
|
|
||||||
ngOnChanges() {
|
ngOnChanges() {
|
||||||
const url = this.navService.currentUrl();
|
const url = this.navService.currentUrl();
|
||||||
if (this.item.route && url) {
|
if (this.item.route && url) {
|
||||||
this.expanded = url.indexOf(`/${this.item.route}`) === 0;
|
this.expanded = url.indexOf(`/${this.item.route}`) === 0;
|
||||||
this.ariaExpanded = this.expanded;
|
this.ariaExpanded = this.expanded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onItemSelected(item: NavItem) {
|
onItemSelected(item: NavItem) {
|
||||||
if (!item.children || !item.children.length) {
|
if (!item.children || !item.children.length) {
|
||||||
this.router.navigate([item.route]);
|
this.router.navigate([item.route]);
|
||||||
}
|
}
|
||||||
if (item.children && item.children.length) {
|
if (item.children && item.children.length) {
|
||||||
this.expanded = !this.expanded;
|
this.expanded = !this.expanded;
|
||||||
}
|
}
|
||||||
//scroll
|
//scroll
|
||||||
window.scroll({
|
window.scroll({
|
||||||
top: 0,
|
top: 0,
|
||||||
left: 0,
|
left: 0,
|
||||||
behavior: 'smooth',
|
behavior: 'smooth',
|
||||||
});
|
});
|
||||||
if (!this.expanded) {
|
if (!this.expanded) {
|
||||||
if (window.innerWidth < 1024) {
|
if (window.innerWidth < 1024) {
|
||||||
this.notify.emit();
|
this.notify.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
openExternalLink(url: string): void {
|
openExternalLink(url: string): void {
|
||||||
if (url) {
|
if (url) {
|
||||||
window.open(url, '_blank');
|
window.open(url, '_blank');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubItemSelected(item: NavItem) {
|
onSubItemSelected(item: NavItem) {
|
||||||
if (!item.children || !item.children.length) {
|
if (!item.children || !item.children.length) {
|
||||||
if (this.expanded && window.innerWidth < 1024) {
|
if (this.expanded && window.innerWidth < 1024) {
|
||||||
this.notify.emit();
|
this.notify.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
export interface NavItem {
|
export interface NavItem {
|
||||||
displayName?: string;
|
displayName?: string;
|
||||||
iconName?: string;
|
iconName?: string;
|
||||||
navCap?: string;
|
navCap?: string;
|
||||||
route?: string;
|
route?: string;
|
||||||
children?: NavItem[];
|
children?: NavItem[];
|
||||||
chip?: boolean;
|
chip?: boolean;
|
||||||
chipContent?: string;
|
chipContent?: string;
|
||||||
chipClass?: string;
|
chipClass?: string;
|
||||||
external?: boolean;
|
external?: boolean;
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,10 @@
|
|||||||
<div class="d-flex align-items-center justify-content-between">
|
<div class="d-flex align-items-center justify-content-between">
|
||||||
<div class="branding"><app-branding></app-branding></div>
|
<div class="branding"><app-branding></app-branding></div>
|
||||||
|
|
||||||
@if(showToggle) {
|
@if(showToggle) {
|
||||||
<a href="javascript:void(0)" (click)="toggleMobileNav.emit()"
|
<a href="javascript:void(0)" (click)="toggleMobileNav.emit()"
|
||||||
class="d-flex justify-content-center ng-star-inserted icon-40 align-items-center">
|
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>
|
<i-tabler name="x" class="icon-20 d-flex"></i-tabler>
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@@ -1,25 +1,25 @@
|
|||||||
import {
|
import {
|
||||||
Component,
|
Component,
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
Input,
|
Input,
|
||||||
OnInit,
|
OnInit,
|
||||||
Output,
|
Output,
|
||||||
ViewChild,
|
ViewChild,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { BrandingComponent } from './branding.component';
|
import { BrandingComponent } from './branding.component';
|
||||||
import { TablerIconsModule } from 'angular-tabler-icons';
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
import { MaterialModule } from 'src/app/material.module';
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-sidebar',
|
selector: 'app-sidebar',
|
||||||
imports: [BrandingComponent, TablerIconsModule, MaterialModule],
|
imports: [BrandingComponent, TablerIconsModule, MaterialModule],
|
||||||
templateUrl: './sidebar.component.html',
|
templateUrl: './sidebar.component.html',
|
||||||
})
|
})
|
||||||
export class SidebarComponent implements OnInit {
|
export class SidebarComponent implements OnInit {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
@Input() showToggle = true;
|
@Input() showToggle = true;
|
||||||
@Output() toggleMobileNav = new EventEmitter<void>();
|
@Output() toggleMobileNav = new EventEmitter<void>();
|
||||||
@Output() toggleCollapsed = new EventEmitter<void>();
|
@Output() toggleCollapsed = new EventEmitter<void>();
|
||||||
|
|
||||||
ngOnInit(): void {}
|
ngOnInit(): void {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,121 +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="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">
|
<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">
|
<a class="d-flex align-items-center" href="https://adminmart.com/" target="_blank">
|
||||||
<img src="/assets/images/logos/logo-adminmart.svg" alt="" width="150">
|
<img src="/assets/images/logos/logo-adminmart.svg" alt="" width="150">
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="linkbar d-none d-lg-flex align-items-center justify-content-center gap-16">
|
<div class="linkbar d-none d-lg-flex align-items-center justify-content-center gap-16">
|
||||||
<!-- Templates -->
|
<!-- Templates -->
|
||||||
<a mat-button class="link-hover p-x-0 text-white d-flex" href="https://adminmart.com/templates/angular/"
|
<a mat-button class="link-hover p-x-0 text-white d-flex" href="https://adminmart.com/templates/angular/"
|
||||||
target="_blank">
|
target="_blank">
|
||||||
<div class="d-flex align-items-center gap-8 f-s-16 f-w-400">
|
<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>
|
<i class="iconify icon-20 d-flex" data-icon="solar:window-frame-linear"></i>
|
||||||
Templates
|
Templates
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<!-- Support -->
|
<!-- Support -->
|
||||||
<a mat-button class="link-hover p-x-0 text-white d-flex" href="https://adminmart.com/support/"
|
<a mat-button class="link-hover p-x-0 text-white d-flex" href="https://adminmart.com/support/"
|
||||||
target="_blank">
|
target="_blank">
|
||||||
<div class="d-flex align-items-center gap-8 f-s-16 f-w-400">
|
<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>
|
<i class="iconify icon-20 d-flex" data-icon="solar:question-circle-linear"></i>
|
||||||
Help
|
Help
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<!-- Hire Us -->
|
<!-- Hire Us -->
|
||||||
<a mat-button class="link-hover p-x-0 text-white d-flex" href="https://adminmart.com/hire-us/"
|
<a mat-button class="link-hover p-x-0 text-white d-flex" href="https://adminmart.com/hire-us/"
|
||||||
target="_blank">
|
target="_blank">
|
||||||
<div class="d-flex align-items-center gap-8 f-s-16 f-w-400">
|
<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>
|
<i class="iconify icon-20 d-flex" data-icon="solar:case-round-linear"></i>
|
||||||
Hire Us
|
Hire Us
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="topstrip-right d-flex align-items-center justify-content-center gap-16">
|
<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>
|
<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="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">
|
<div class="d-flex justify-content-center align-items-center gap-10">
|
||||||
<!-- Live Preview -->
|
<!-- Live Preview -->
|
||||||
<button class="live-preview-drop d-flex align-items-center gap-4 text-white f-s-16 p-x-16" mat-button
|
<button class="live-preview-drop d-flex align-items-center gap-4 text-white f-s-16 p-x-16" mat-button
|
||||||
[matMenuTriggerFor]="beforeMenu">
|
[matMenuTriggerFor]="beforeMenu">
|
||||||
<div class="d-flex align-items-center gap-6">
|
<div class="d-flex align-items-center gap-6">
|
||||||
Live Preview
|
Live Preview
|
||||||
<i class="iconify icon-20 d-flex" data-icon="solar:alt-arrow-down-linear"></i>
|
<i class="iconify icon-20 d-flex" data-icon="solar:alt-arrow-down-linear"></i>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<mat-menu class="p-x-16 p-y-8 rounded-7" #beforeMenu="matMenu" xPosition="before">
|
<mat-menu class="p-x-16 p-y-8 rounded-7" #beforeMenu="matMenu" xPosition="before">
|
||||||
<a mat-menu-item class="rounded-7"
|
<a mat-menu-item class="rounded-7"
|
||||||
href="https://adminmart.com/product/modernize-angular-material-dashboard/?ref=56#product-demo-section"
|
href="https://adminmart.com/product/modernize-angular-material-dashboard/?ref=56#product-demo-section"
|
||||||
target="_blank">
|
target="_blank">
|
||||||
<div class="d-flex align-items-center gap-12 f-s-16">
|
<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">
|
<img src="/assets/images/svgs/angular-cat-icon.svg" width="18" alt="angular">
|
||||||
Angular Version
|
Angular Version
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<a mat-menu-item class="rounded-7"
|
<a mat-menu-item class="rounded-7"
|
||||||
href="https://adminmart.com/product/modernize-react-mui-dashboard-theme/?ref=56#product-demo-section"
|
href="https://adminmart.com/product/modernize-react-mui-dashboard-theme/?ref=56#product-demo-section"
|
||||||
target="_blank">
|
target="_blank">
|
||||||
<div class="d-flex align-items-center gap-12 f-s-16">
|
<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">
|
<img src="/assets/images/svgs/react-cat-icon.svg" width="18" alt="react">
|
||||||
React Version
|
React Version
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<a mat-menu-item class="rounded-7"
|
<a mat-menu-item class="rounded-7"
|
||||||
href="https://adminmart.com/product/modernize-vuetify-vue-admin-dashboard/?ref=56#product-demo-section"
|
href="https://adminmart.com/product/modernize-vuetify-vue-admin-dashboard/?ref=56#product-demo-section"
|
||||||
target="_blank">
|
target="_blank">
|
||||||
<div class="d-flex align-items-center gap-12 f-s-16">
|
<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">
|
<img src="/assets/images/svgs/vue-cat-icon.svg" width="18" alt="vueJs">
|
||||||
VueJs Version
|
VueJs Version
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<a mat-menu-item class="rounded-7"
|
<a mat-menu-item class="rounded-7"
|
||||||
href="https://adminmart.com/product/modernize-next-js-admin-dashboard/?ref=56#product-demo-section"
|
href="https://adminmart.com/product/modernize-next-js-admin-dashboard/?ref=56#product-demo-section"
|
||||||
target="_blank">
|
target="_blank">
|
||||||
<div class="d-flex align-items-center gap-12 f-s-16">
|
<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">
|
<img src="/assets/images/svgs/next-cat-icon.svg" width="18" alt="nextJs">
|
||||||
NextJs Version
|
NextJs Version
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<a mat-menu-item class="rounded-7"
|
<a mat-menu-item class="rounded-7"
|
||||||
href="https://adminmart.com/product/modernize-nuxt-js-admin-dashboard/?ref=56#product-demo-section"
|
href="https://adminmart.com/product/modernize-nuxt-js-admin-dashboard/?ref=56#product-demo-section"
|
||||||
target="_blank">
|
target="_blank">
|
||||||
<div class="d-flex align-items-center gap-12 f-s-16">
|
<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">
|
<img src="/assets/images/svgs/nuxt-cat-icon.svg" width="18" alt="nuxtJs">
|
||||||
NuxtJs Version
|
NuxtJs Version
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<a mat-menu-item class="rounded-7"
|
<a mat-menu-item class="rounded-7"
|
||||||
href="https://adminmart.com/product/modernize-tailwind-nextjs-dashboard-template/?ref=56#product-demo-section"
|
href="https://adminmart.com/product/modernize-tailwind-nextjs-dashboard-template/?ref=56#product-demo-section"
|
||||||
target="_blank">
|
target="_blank">
|
||||||
<div class="d-flex align-items-center gap-12 f-s-16">
|
<div class="d-flex align-items-center gap-12 f-s-16">
|
||||||
<img src="/assets/images/svgs/tailwindcss.svg" width="20" alt="tailwind">
|
<img src="/assets/images/svgs/tailwindcss.svg" width="20" alt="tailwind">
|
||||||
Tailwind Version
|
Tailwind Version
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<a mat-menu-item class="rounded-7"
|
<a mat-menu-item class="rounded-7"
|
||||||
href="https://adminmart.com/product/modernize-bootstrap-5-admin-template/?ref=56#product-demo-section"
|
href="https://adminmart.com/product/modernize-bootstrap-5-admin-template/?ref=56#product-demo-section"
|
||||||
target="_blank">
|
target="_blank">
|
||||||
<div class="d-flex align-items-center gap-12 f-s-16">
|
<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">
|
<img src="/assets/images/svgs/bt-cat-icon.svg" width="20" alt="bootstrap">
|
||||||
Bootstrap Version
|
Bootstrap Version
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</mat-menu>
|
</mat-menu>
|
||||||
|
|
||||||
<!-- Get Pro -->
|
<!-- Get Pro -->
|
||||||
<a mat-button class="get-pro-btn text-white p-x-16"
|
<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">
|
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">
|
<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>
|
<i class="iconify icon-18 d-flex" data-icon="solar:crown-linear"></i>
|
||||||
Get Pro
|
Get Pro
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { MatMenuModule } from '@angular/material/menu';
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
import { TablerIconsModule } from 'angular-tabler-icons';
|
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-topstrip',
|
selector: 'app-topstrip',
|
||||||
imports: [TablerIconsModule, MatButtonModule, MatMenuModule],
|
imports: [TablerIconsModule, MatButtonModule, MatMenuModule],
|
||||||
templateUrl: './topstrip.component.html',
|
templateUrl: './topstrip.component.html',
|
||||||
})
|
})
|
||||||
export class AppTopstripComponent {
|
export class AppTopstripComponent {
|
||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,85 +1,85 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
// Material Form Controls
|
// Material Form Controls
|
||||||
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
import { MatDatepickerModule } from '@angular/material/datepicker';
|
import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
import { MatInputModule } from '@angular/material/input';
|
import { MatInputModule } from '@angular/material/input';
|
||||||
import { MatRadioModule } from '@angular/material/radio';
|
import { MatRadioModule } from '@angular/material/radio';
|
||||||
import { MatSelectModule } from '@angular/material/select';
|
import { MatSelectModule } from '@angular/material/select';
|
||||||
import { MatSliderModule } from '@angular/material/slider';
|
import { MatSliderModule } from '@angular/material/slider';
|
||||||
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||||
// Material Navigation
|
// Material Navigation
|
||||||
import { MatMenuModule } from '@angular/material/menu';
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
import { MatSidenavModule } from '@angular/material/sidenav';
|
import { MatSidenavModule } from '@angular/material/sidenav';
|
||||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
// Material Layout
|
// Material Layout
|
||||||
import { MatCardModule } from '@angular/material/card';
|
import { MatCardModule } from '@angular/material/card';
|
||||||
import { MatDividerModule } from '@angular/material/divider';
|
import { MatDividerModule } from '@angular/material/divider';
|
||||||
import { MatExpansionModule } from '@angular/material/expansion';
|
import { MatExpansionModule } from '@angular/material/expansion';
|
||||||
import { MatGridListModule } from '@angular/material/grid-list';
|
import { MatGridListModule } from '@angular/material/grid-list';
|
||||||
import { MatListModule } from '@angular/material/list';
|
import { MatListModule } from '@angular/material/list';
|
||||||
import { MatStepperModule } from '@angular/material/stepper';
|
import { MatStepperModule } from '@angular/material/stepper';
|
||||||
import { MatTabsModule } from '@angular/material/tabs';
|
import { MatTabsModule } from '@angular/material/tabs';
|
||||||
import { MatTreeModule } from '@angular/material/tree';
|
import { MatTreeModule } from '@angular/material/tree';
|
||||||
// Material Buttons & Indicators
|
// Material Buttons & Indicators
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { MatButtonToggleModule } from '@angular/material/button-toggle';
|
import { MatButtonToggleModule } from '@angular/material/button-toggle';
|
||||||
import { MatBadgeModule } from '@angular/material/badge';
|
import { MatBadgeModule } from '@angular/material/badge';
|
||||||
import { MatChipsModule } from '@angular/material/chips';
|
import { MatChipsModule } from '@angular/material/chips';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||||
import { MatRippleModule } from '@angular/material/core';
|
import { MatRippleModule } from '@angular/material/core';
|
||||||
// Material Popups & Modals
|
// Material Popups & Modals
|
||||||
import { MatBottomSheetModule } from '@angular/material/bottom-sheet';
|
import { MatBottomSheetModule } from '@angular/material/bottom-sheet';
|
||||||
import { MatDialogModule } from '@angular/material/dialog';
|
import { MatDialogModule } from '@angular/material/dialog';
|
||||||
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
// Material Data tables
|
// Material Data tables
|
||||||
import { MatPaginatorModule } from '@angular/material/paginator';
|
import { MatPaginatorModule } from '@angular/material/paginator';
|
||||||
import { MatSortModule } from '@angular/material/sort';
|
import { MatSortModule } from '@angular/material/sort';
|
||||||
import { MatTableModule } from '@angular/material/table';
|
import { MatTableModule } from '@angular/material/table';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [],
|
declarations: [],
|
||||||
exports: [
|
exports: [
|
||||||
MatAutocompleteModule,
|
MatAutocompleteModule,
|
||||||
MatCheckboxModule,
|
MatCheckboxModule,
|
||||||
MatDatepickerModule,
|
MatDatepickerModule,
|
||||||
MatFormFieldModule,
|
MatFormFieldModule,
|
||||||
MatInputModule,
|
MatInputModule,
|
||||||
MatRadioModule,
|
MatRadioModule,
|
||||||
MatSelectModule,
|
MatSelectModule,
|
||||||
MatSliderModule,
|
MatSliderModule,
|
||||||
MatSlideToggleModule,
|
MatSlideToggleModule,
|
||||||
MatMenuModule,
|
MatMenuModule,
|
||||||
MatSidenavModule,
|
MatSidenavModule,
|
||||||
MatToolbarModule,
|
MatToolbarModule,
|
||||||
MatCardModule,
|
MatCardModule,
|
||||||
MatDividerModule,
|
MatDividerModule,
|
||||||
MatExpansionModule,
|
MatExpansionModule,
|
||||||
MatGridListModule,
|
MatGridListModule,
|
||||||
MatListModule,
|
MatListModule,
|
||||||
MatStepperModule,
|
MatStepperModule,
|
||||||
MatTabsModule,
|
MatTabsModule,
|
||||||
MatTreeModule,
|
MatTreeModule,
|
||||||
MatButtonModule,
|
MatButtonModule,
|
||||||
MatButtonToggleModule,
|
MatButtonToggleModule,
|
||||||
MatBadgeModule,
|
MatBadgeModule,
|
||||||
MatChipsModule,
|
MatChipsModule,
|
||||||
MatIconModule,
|
MatIconModule,
|
||||||
MatProgressSpinnerModule,
|
MatProgressSpinnerModule,
|
||||||
MatProgressBarModule,
|
MatProgressBarModule,
|
||||||
MatRippleModule,
|
MatRippleModule,
|
||||||
MatBottomSheetModule,
|
MatBottomSheetModule,
|
||||||
MatDialogModule,
|
MatDialogModule,
|
||||||
MatSnackBarModule,
|
MatSnackBarModule,
|
||||||
MatTooltipModule,
|
MatTooltipModule,
|
||||||
MatPaginatorModule,
|
MatPaginatorModule,
|
||||||
MatSortModule,
|
MatSortModule,
|
||||||
MatTableModule,
|
MatTableModule,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class MaterialModule {}
|
export class MaterialModule {}
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
import { Routes } from '@angular/router';
|
import { Routes } from '@angular/router';
|
||||||
|
|
||||||
import { AppSideLoginComponent } from './side-login/side-login.component';
|
import { AppSideLoginComponent } from './side-login/side-login.component';
|
||||||
import { AppSideRegisterComponent } from './side-register/side-register.component';
|
import { AppSideRegisterComponent } from './side-register/side-register.component';
|
||||||
|
|
||||||
export const AuthenticationRoutes: Routes = [
|
export const AuthenticationRoutes: Routes = [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'login',
|
path: 'login',
|
||||||
component: AppSideLoginComponent,
|
component: AppSideLoginComponent,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'register',
|
path: 'register',
|
||||||
component: AppSideRegisterComponent,
|
component: AppSideRegisterComponent,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,64 +1,64 @@
|
|||||||
<div class="blank-layout-container justify-content-center align-items-center bg-light">
|
<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="position-relative row w-100 h-100 bg-gredient justify-content-center">
|
||||||
<div class="col-lg-4 d-flex align-items-center">
|
<div class="col-lg-4 d-flex align-items-center">
|
||||||
<mat-card class="cardWithShadow boxed-auth">
|
<mat-card class="cardWithShadow boxed-auth">
|
||||||
<mat-card-content class="p-32">
|
<mat-card-content class="p-32">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<a [routerLink]="['/dashboard']">
|
<a [routerLink]="['/dashboard']">
|
||||||
<img src="./assets/images/logos/dark-logo.svg" class="align-middle m-2" alt="logo" />
|
<img src="./assets/images/logos/dark-logo.svg" class="align-middle m-2" alt="logo" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row m-t-24 custom-row">
|
<div class="row m-t-24 custom-row">
|
||||||
<div class="col-12 col-sm-6">
|
<div class="col-12 col-sm-6">
|
||||||
<button mat-stroked-button class="w-100">
|
<button mat-stroked-button class="w-100">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<img src="/assets/images/svgs/google-icon.svg" alt="google" width="16" class="m-r-8" />
|
<img src="/assets/images/svgs/google-icon.svg" alt="google" width="16" class="m-r-8" />
|
||||||
<span>
|
<span>
|
||||||
Sign in with Google
|
Sign in with Google
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-sm-6">
|
<div class="col-12 col-sm-6">
|
||||||
<button mat-stroked-button class="w-100 d-flex align-items-center">
|
<button mat-stroked-button class="w-100 d-flex align-items-center">
|
||||||
<div class="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" />
|
<img src="/assets/images/svgs/facebook-icon.svg" alt="facebook" width="40" class="m-r-4" />
|
||||||
Sign in with FB
|
Sign in with FB
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="or-border m-t-30">or sign in with</div>
|
<div class="or-border m-t-30">or sign in with</div>
|
||||||
|
|
||||||
<form class="m-t-30">
|
<form class="m-t-30">
|
||||||
<mat-label class="f-s-14 f-w-600 m-b-12 d-block">Username</mat-label>
|
<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">
|
<mat-form-field appearance="outline" class="w-100" color="primary">
|
||||||
<input matInput />
|
<input matInput />
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<!-- password -->
|
<!-- password -->
|
||||||
<mat-label class="f-s-14 f-w-600 m-b-12 d-block">Password</mat-label>
|
<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">
|
<mat-form-field appearance="outline" class="w-100" color="primary">
|
||||||
<input matInput type="password" />
|
<input matInput type="password" />
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<div class="d-flex align-items-center m-b-12">
|
<div class="d-flex align-items-center m-b-12">
|
||||||
<mat-checkbox color="primary">Remember this Device</mat-checkbox>
|
<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 [routerLink]="['/']" class="text-primary f-w-600 text-decoration-none m-l-auto f-s-14">Forgot Password
|
||||||
?</a>
|
?</a>
|
||||||
</div>
|
</div>
|
||||||
<a [routerLink]="['/']" mat-flat-button color="primary" class="w-100">
|
<a [routerLink]="['/']" mat-flat-button color="primary" class="w-100">
|
||||||
Sign In
|
Sign In
|
||||||
</a>
|
</a>
|
||||||
<!-- input -->
|
<!-- input -->
|
||||||
</form>
|
</form>
|
||||||
<span class="d-block f-w-500 text-center m-t-24">New to Modernize?
|
<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">
|
<a [routerLink]="['/authentication/register']" class="text-decoration-none text-primary f-w-500 f-s-14">
|
||||||
Create an account</a>
|
Create an account</a>
|
||||||
</span>
|
</span>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,31 +1,31 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { FormGroup, FormControl, Validators } from '@angular/forms';
|
import { FormGroup, FormControl, Validators } from '@angular/forms';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { MaterialModule } from 'src/app/material.module';
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { ReactiveFormsModule } from '@angular/forms';
|
import { ReactiveFormsModule } from '@angular/forms';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-side-login',
|
selector: 'app-side-login',
|
||||||
imports: [RouterModule, MaterialModule, FormsModule, ReactiveFormsModule],
|
imports: [RouterModule, MaterialModule, FormsModule, ReactiveFormsModule],
|
||||||
templateUrl: './side-login.component.html',
|
templateUrl: './side-login.component.html',
|
||||||
})
|
})
|
||||||
export class AppSideLoginComponent {
|
export class AppSideLoginComponent {
|
||||||
|
|
||||||
constructor( private router: Router) {}
|
constructor( private router: Router) {}
|
||||||
|
|
||||||
form = new FormGroup({
|
form = new FormGroup({
|
||||||
uname: new FormControl('', [Validators.required, Validators.minLength(6)]),
|
uname: new FormControl('', [Validators.required, Validators.minLength(6)]),
|
||||||
password: new FormControl('', [Validators.required]),
|
password: new FormControl('', [Validators.required]),
|
||||||
});
|
});
|
||||||
|
|
||||||
get f() {
|
get f() {
|
||||||
return this.form.controls;
|
return this.form.controls;
|
||||||
}
|
}
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
// console.log(this.form.value);
|
// console.log(this.form.value);
|
||||||
this.router.navigate(['/']);
|
this.router.navigate(['/']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,62 +1,62 @@
|
|||||||
<div class="blank-layout-container justify-content-center align-items-center bg-light">
|
<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="position-relative row w-100 h-100 bg-gredient justify-content-center">
|
||||||
<div class="col-lg-4 d-flex align-items-center">
|
<div class="col-lg-4 d-flex align-items-center">
|
||||||
<mat-card class="cardWithShadow boxed-auth">
|
<mat-card class="cardWithShadow boxed-auth">
|
||||||
<mat-card-content class="p-32">
|
<mat-card-content class="p-32">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<a [routerLink]="['/dashboard']">
|
<a [routerLink]="['/dashboard']">
|
||||||
<img src="./assets/images/logos/dark-logo.svg" class="align-middle m-2" alt="logo" />
|
<img src="./assets/images/logos/dark-logo.svg" class="align-middle m-2" alt="logo" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row m-t-24 custom-row">
|
<div class="row m-t-24 custom-row">
|
||||||
<div class="col-12 col-sm-6">
|
<div class="col-12 col-sm-6">
|
||||||
<button mat-stroked-button class="w-100">
|
<button mat-stroked-button class="w-100">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<img src="/assets/images/svgs/google-icon.svg" alt="google" width="16" class="m-r-8" />
|
<img src="/assets/images/svgs/google-icon.svg" alt="google" width="16" class="m-r-8" />
|
||||||
Sign in with Google
|
Sign in with Google
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-sm-6">
|
<div class="col-12 col-sm-6">
|
||||||
<button mat-stroked-button class="w-100 d-flex align-items-center">
|
<button mat-stroked-button class="w-100 d-flex align-items-center">
|
||||||
<div class="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" />
|
<img src="/assets/images/svgs/facebook-icon.svg" alt="facebook" width="40" class="m-r-4" />
|
||||||
Sign in with FB
|
Sign in with FB
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="or-border m-t-30">or sign up with</div>
|
<div class="or-border m-t-30">or sign up with</div>
|
||||||
|
|
||||||
<form class="m-t-30">
|
<form class="m-t-30">
|
||||||
<mat-label class="f-s-14 f-w-600 m-b-12 d-block">Name</mat-label>
|
<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">
|
<mat-form-field appearance="outline" class="w-100" color="primary">
|
||||||
<input matInput />
|
<input matInput />
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<mat-label class="f-s-14 f-w-600 m-b-12 d-block">Email Adddress</mat-label>
|
<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">
|
<mat-form-field appearance="outline" class="w-100" color="primary">
|
||||||
<input matInput type="email" />
|
<input matInput type="email" />
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<!-- password -->
|
<!-- password -->
|
||||||
<mat-label class="f-s-14 f-w-600 m-b-12 d-block">Password</mat-label>
|
<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">
|
<mat-form-field appearance="outline" class="w-100" color="primary">
|
||||||
<input matInput type="password" />
|
<input matInput type="password" />
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<a [routerLink]="['/']" mat-flat-button color="primary" class="w-100">
|
<a [routerLink]="['/']" mat-flat-button color="primary" class="w-100">
|
||||||
Sign Up
|
Sign Up
|
||||||
</a>
|
</a>
|
||||||
<!-- input -->
|
<!-- input -->
|
||||||
</form>
|
</form>
|
||||||
<span class="d-block f-w-500 text-center m-t-24">Already have an Account?
|
<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">
|
<a [routerLink]="['/authentication/login']" class="text-decoration-none text-primary f-w-500 f-s-14">
|
||||||
Sign In</a>
|
Sign In</a>
|
||||||
</span>
|
</span>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,33 +1,33 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { CoreService } from 'src/app/services/core.service';
|
import { CoreService } from 'src/app/services/core.service';
|
||||||
import { FormGroup, FormControl, Validators } from '@angular/forms';
|
import { FormGroup, FormControl, Validators } from '@angular/forms';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { MaterialModule } from 'src/app/material.module';
|
import { MaterialModule } from 'src/app/material.module';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-side-register',
|
selector: 'app-side-register',
|
||||||
imports: [RouterModule, MaterialModule, FormsModule, ReactiveFormsModule],
|
imports: [RouterModule, MaterialModule, FormsModule, ReactiveFormsModule],
|
||||||
templateUrl: './side-register.component.html',
|
templateUrl: './side-register.component.html',
|
||||||
})
|
})
|
||||||
export class AppSideRegisterComponent {
|
export class AppSideRegisterComponent {
|
||||||
options = this.settings.getOptions();
|
options = this.settings.getOptions();
|
||||||
|
|
||||||
constructor(private settings: CoreService, private router: Router) {}
|
constructor(private settings: CoreService, private router: Router) {}
|
||||||
|
|
||||||
form = new FormGroup({
|
form = new FormGroup({
|
||||||
uname: new FormControl('', [Validators.required, Validators.minLength(6)]),
|
uname: new FormControl('', [Validators.required, Validators.minLength(6)]),
|
||||||
email: new FormControl('', [Validators.required]),
|
email: new FormControl('', [Validators.required]),
|
||||||
password: new FormControl('', [Validators.required]),
|
password: new FormControl('', [Validators.required]),
|
||||||
});
|
});
|
||||||
|
|
||||||
get f() {
|
get f() {
|
||||||
return this.form.controls;
|
return this.form.controls;
|
||||||
}
|
}
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
// console.log(this.form.value);
|
// console.log(this.form.value);
|
||||||
this.router.navigate(['/']);
|
this.router.navigate(['/']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
import { Routes } from '@angular/router';
|
import { Routes } from '@angular/router';
|
||||||
|
|
||||||
|
|
||||||
// pages
|
// pages
|
||||||
import { AppIconsComponent } from './icons/icons.component';
|
import { AppIconsComponent } from './icons/icons.component';
|
||||||
import { AppSamplePageComponent } from './sample-page/sample-page.component';
|
import { AppSamplePageComponent } from './sample-page/sample-page.component';
|
||||||
|
|
||||||
export const ExtraRoutes: Routes = [
|
export const ExtraRoutes: Routes = [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'icons',
|
path: 'icons',
|
||||||
component: AppIconsComponent,
|
component: AppIconsComponent,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'sample-page',
|
path: 'sample-page',
|
||||||
component: AppSamplePageComponent,
|
component: AppSamplePageComponent,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<!-- ============================================================== -->
|
<!-- ============================================================== -->
|
||||||
<!-- Simple four boxes Row -->
|
<!-- Simple four boxes Row -->
|
||||||
<!-- ============================================================== -->
|
<!-- ============================================================== -->
|
||||||
<mat-card class="cardWithShadow">
|
<mat-card class="cardWithShadow">
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<mat-card-title>Icons</mat-card-title>
|
<mat-card-title>Icons</mat-card-title>
|
||||||
<mat-card-subtitle class="m-b-24">Tabler Icons</mat-card-subtitle>
|
<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"
|
<iframe src="https://tabler.io/icons" title="Tabler Icons" width="100%" height="630px"
|
||||||
allowfullscreen frameBorder="0">
|
allowfullscreen frameBorder="0">
|
||||||
</iframe>
|
</iframe>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { MaterialModule } from '../../../material.module';
|
import { MaterialModule } from '../../../material.module';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-icons',
|
selector: 'app-icons',
|
||||||
imports: [MaterialModule],
|
imports: [MaterialModule],
|
||||||
templateUrl: './icons.component.html',
|
templateUrl: './icons.component.html',
|
||||||
})
|
})
|
||||||
export class AppIconsComponent { }
|
export class AppIconsComponent { }
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<!-- ============================================================== -->
|
<!-- ============================================================== -->
|
||||||
<!-- Simple four boxes Row -->
|
<!-- Simple four boxes Row -->
|
||||||
<!-- ============================================================== -->
|
<!-- ============================================================== -->
|
||||||
<mat-card class="cardWithShadow">
|
<mat-card class="cardWithShadow">
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<mat-card-title>Sample Page</mat-card-title>
|
<mat-card-title>Sample Page</mat-card-title>
|
||||||
<mat-card-subtitle>This is test page</mat-card-subtitle>
|
<mat-card-subtitle>This is test page</mat-card-subtitle>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user