diff --git a/.gitignore b/.gitignore
index 2e81f37..914b6b2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,364 +1,364 @@
-## Ignore Visual Studio temporary files, build results, and
-## files generated by popular Visual Studio add-ons.
-##
-## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
-
-
-WebAPI/.local-chromium
-# User-specific files
-*.rsuser
-*.suo
-*.user
-*.userosscache
-*.sln.docstates
-
-# User-specific files (MonoDevelop/Xamarin Studio)
-*.userprefs
-
-# Mono auto generated files
-mono_crash.*
-
-# Build results
-[Dd]ebug/
-[Dd]ebugPublic/
-[Rr]elease/
-[Rr]eleases/
-x64/
-x86/
-[Ww][Ii][Nn]32/
-[Aa][Rr][Mm]/
-[Aa][Rr][Mm]64/
-bld/
-[Bb]in/
-[Oo]bj/
-[Ll]og/
-[Ll]ogs/
-
-# Visual Studio 2015/2017 cache/options directory
-.vs/
-# Uncomment if you have tasks that create the project's static files in wwwroot
-#wwwroot/
-
-# Visual Studio 2017 auto generated files
-Generated\ Files/
-
-# MSTest test Results
-[Tt]est[Rr]esult*/
-[Bb]uild[Ll]og.*
-
-# NUnit
-*.VisualState.xml
-TestResult.xml
-nunit-*.xml
-
-# Build Results of an ATL Project
-[Dd]ebugPS/
-[Rr]eleasePS/
-dlldata.c
-
-# Benchmark Results
-BenchmarkDotNet.Artifacts/
-
-# .NET Core
-project.lock.json
-project.fragment.lock.json
-artifacts/
-
-# ASP.NET Scaffolding
-ScaffoldingReadMe.txt
-
-# StyleCop
-StyleCopReport.xml
-
-# Files built by Visual Studio
-*_i.c
-*_p.c
-*_h.h
-*.ilk
-*.meta
-*.obj
-*.iobj
-*.pch
-*.pdb
-*.ipdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.tmp_proj
-*_wpftmp.csproj
-*.log
-*.vspscc
-*.vssscc
-.builds
-*.pidb
-*.svclog
-*.scc
-
-# Chutzpah Test files
-_Chutzpah*
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opendb
-*.opensdf
-*.sdf
-*.cachefile
-*.VC.db
-*.VC.VC.opendb
-
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
-*.sap
-
-# Visual Studio Trace Files
-*.e2e
-
-# TFS 2012 Local Workspace
-$tf/
-
-# Guidance Automation Toolkit
-*.gpState
-
-# ReSharper is a .NET coding add-in
-_ReSharper*/
-*.[Rr]e[Ss]harper
-*.DotSettings.user
-
-# TeamCity is a build add-in
-_TeamCity*
-
-# DotCover is a Code Coverage Tool
-*.dotCover
-
-# AxoCover is a Code Coverage Tool
-.axoCover/*
-!.axoCover/settings.json
-
-# Coverlet is a free, cross platform Code Coverage Tool
-coverage*.json
-coverage*.xml
-coverage*.info
-
-# Visual Studio code coverage results
-*.coverage
-*.coveragexml
-
-# NCrunch
-_NCrunch_*
-.*crunch*.local.xml
-nCrunchTemp_*
-
-# MightyMoose
-*.mm.*
-AutoTest.Net/
-
-# Web workbench (sass)
-.sass-cache/
-
-# Installshield output folder
-[Ee]xpress/
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish/
-
-# Publish Web Output
-*.[Pp]ublish.xml
-*.azurePubxml
-# Note: Comment the next line if you want to checkin your web deploy settings,
-# but database connection strings (with potential passwords) will be unencrypted
-*.pubxml
-*.publishproj
-
-# Microsoft Azure Web App publish settings. Comment the next line if you want to
-# checkin your Azure Web App publish settings, but sensitive information contained
-# in these scripts will be unencrypted
-PublishScripts/
-
-# NuGet Packages
-*.nupkg
-# NuGet Symbol Packages
-*.snupkg
-# The packages folder can be ignored because of Package Restore
-**/[Pp]ackages/*
-# except build/, which is used as an MSBuild target.
-!**/[Pp]ackages/build/
-# Uncomment if necessary however generally it will be regenerated when needed
-#!**/[Pp]ackages/repositories.config
-# NuGet v3's project.json files produces more ignorable files
-*.nuget.props
-*.nuget.targets
-
-# Microsoft Azure Build Output
-csx/
-*.build.csdef
-
-# Microsoft Azure Emulator
-ecf/
-rcf/
-
-# Windows Store app package directories and files
-AppPackages/
-BundleArtifacts/
-Package.StoreAssociation.xml
-_pkginfo.txt
-*.appx
-*.appxbundle
-*.appxupload
-
-# Visual Studio cache files
-# files ending in .cache can be ignored
-*.[Cc]ache
-# but keep track of directories ending in .cache
-!?*.[Cc]ache/
-
-# Others
-ClientBin/
-~$*
-*~
-*.dbmdl
-*.dbproj.schemaview
-*.jfm
-*.pfx
-*.publishsettings
-orleans.codegen.cs
-
-# Including strong name files can present a security risk
-# (https://github.com/github/gitignore/pull/2483#issue-259490424)
-#*.snk
-
-# Since there are multiple workflows, uncomment next line to ignore bower_components
-# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
-#bower_components/
-
-# RIA/Silverlight projects
-Generated_Code/
-
-# Backup & report files from converting an old project file
-# to a newer Visual Studio version. Backup files are not needed,
-# because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-UpgradeLog*.htm
-ServiceFabricBackup/
-*.rptproj.bak
-
-# SQL Server files
-*.mdf
-*.ldf
-*.ndf
-
-# Business Intelligence projects
-*.rdl.data
-*.bim.layout
-*.bim_*.settings
-*.rptproj.rsuser
-*- [Bb]ackup.rdl
-*- [Bb]ackup ([0-9]).rdl
-*- [Bb]ackup ([0-9][0-9]).rdl
-
-# Microsoft Fakes
-FakesAssemblies/
-
-# GhostDoc plugin setting file
-*.GhostDoc.xml
-
-# Node.js Tools for Visual Studio
-.ntvs_analysis.dat
-node_modules/
-
-# Visual Studio 6 build log
-*.plg
-
-# Visual Studio 6 workspace options file
-*.opt
-
-# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
-*.vbw
-
-# Visual Studio LightSwitch build output
-**/*.HTMLClient/GeneratedArtifacts
-**/*.DesktopClient/GeneratedArtifacts
-**/*.DesktopClient/ModelManifest.xml
-**/*.Server/GeneratedArtifacts
-**/*.Server/ModelManifest.xml
-_Pvt_Extensions
-
-# Paket dependency manager
-.paket/paket.exe
-paket-files/
-
-# FAKE - F# Make
-.fake/
-
-# CodeRush personal settings
-.cr/personal
-
-# Python Tools for Visual Studio (PTVS)
-__pycache__/
-*.pyc
-
-# Cake - Uncomment if you are using it
-# tools/**
-# !tools/packages.config
-
-# Tabs Studio
-*.tss
-
-# Telerik's JustMock configuration file
-*.jmconfig
-
-# BizTalk build output
-*.btp.cs
-*.btm.cs
-*.odx.cs
-*.xsd.cs
-
-# OpenCover UI analysis results
-OpenCover/
-
-# Azure Stream Analytics local run output
-ASALocalRun/
-
-# MSBuild Binary and Structured Log
-*.binlog
-
-# NVidia Nsight GPU debugger configuration file
-*.nvuser
-
-# MFractors (Xamarin productivity tool) working folder
-.mfractor/
-
-# Local History for Visual Studio
-.localhistory/
-
-# BeatPulse healthcheck temp database
-healthchecksdb
-
-# Backup folder for Package Reference Convert tool in Visual Studio 2017
-MigrationBackup/
-
-# Ionide (cross platform F# VS Code tools) working folder
-.ionide/
-
-# Fody - auto-generated XML schema
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+
+WebAPI/.local-chromium
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
FodyWeavers.xsd
\ No newline at end of file
diff --git a/DiunaBI.code-workspace b/DiunaBI.code-workspace
index 8aba6a2..76fb9fb 100644
--- a/DiunaBI.code-workspace
+++ b/DiunaBI.code-workspace
@@ -1,7 +1,7 @@
-{
- "folders": [
- {
- "path": "."
- }
- ]
+{
+ "folders": [
+ {
+ "path": "."
+ }
+ ]
}
\ No newline at end of file
diff --git a/DiunaBI.sln b/DiunaBI.sln
index a43d2d9..1a7ee88 100644
--- a/DiunaBI.sln
+++ b/DiunaBI.sln
@@ -1,25 +1,25 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.4.33110.190
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiunaBI-WebAPI", "WebAPI\DiunaBI-WebAPI.csproj", "{799D68C2-A4C1-43F8-8C35-1126C0AC32D6}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {799D68C2-A4C1-43F8-8C35-1126C0AC32D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {799D68C2-A4C1-43F8-8C35-1126C0AC32D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {799D68C2-A4C1-43F8-8C35-1126C0AC32D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {799D68C2-A4C1-43F8-8C35-1126C0AC32D6}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {2CFA03A7-56D9-4ADE-9B6A-1A3383A1C104}
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.4.33110.190
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiunaBI-WebAPI", "WebAPI\DiunaBI-WebAPI.csproj", "{799D68C2-A4C1-43F8-8C35-1126C0AC32D6}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {799D68C2-A4C1-43F8-8C35-1126C0AC32D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {799D68C2-A4C1-43F8-8C35-1126C0AC32D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {799D68C2-A4C1-43F8-8C35-1126C0AC32D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {799D68C2-A4C1-43F8-8C35-1126C0AC32D6}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {2CFA03A7-56D9-4ADE-9B6A-1A3383A1C104}
+ EndGlobalSection
+EndGlobal
diff --git a/Frontend/DiunaBI.code-workspace b/Frontend/DiunaBI.code-workspace
index 9e68e72..97d6683 100644
--- a/Frontend/DiunaBI.code-workspace
+++ b/Frontend/DiunaBI.code-workspace
@@ -1,7 +1,7 @@
-{
- "folders": [
- {
- "path": ".."
- }
- ]
+{
+ "folders": [
+ {
+ "path": ".."
+ }
+ ]
}
\ No newline at end of file
diff --git a/Frontend/src/app/components/login-page/login-page.component.html b/Frontend/src/app/components/login-page/login-page.component.html
index e5243c7..f582ed9 100644
--- a/Frontend/src/app/components/login-page/login-page.component.html
+++ b/Frontend/src/app/components/login-page/login-page.component.html
@@ -1,13 +1,13 @@
-
-

-
-
-
-
+
+

+
+
+
\ No newline at end of file
diff --git a/Frontend/src/app/components/login-page/login-page.component.scss b/Frontend/src/app/components/login-page/login-page.component.scss
index 52efa04..863294d 100644
--- a/Frontend/src/app/components/login-page/login-page.component.scss
+++ b/Frontend/src/app/components/login-page/login-page.component.scss
@@ -1,63 +1,63 @@
-.bg {
- background-image: url("../../../assets/bg.jpg");
- height: 70vh;
- background-size: cover;
- padding-top: 30vh;
-}
-.container {
- width: fit-content;
- display: block;
- margin: auto;
-}
-.form {
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
-}
-.logo {
- background-image: url('../../../assets/logo.png');
- background-size: cover;
- position: absolute;
- top: 10px;
- right: 10px;
- width: 250px;
- height: 250px;
- opacity: 0.6;
- }
-mat-form-field {
- width: 100%;
-}
-.user {
- text-align: right;
-}
-.load {
- text-align: center;
-}
-.loading-container {
- position: absolute;
- left: 0;
- right: 0;
- top: 0;
- bottom: 0;
- background-color: rgba(100, 100, 100, 0.3);
- z-index: 1400;
- }
- .loading-img {
- position: absolute;
- margin: auto;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- }
-/* for mobile */
-@media screen and (max-width: 700px) {
- .container {
- width: 90%;
- }
- .logo {
- width: 150px;
- height: 150px;
- }
-}
+.bg {
+ background-image: url("../../../assets/bg.jpg");
+ height: 70vh;
+ background-size: cover;
+ padding-top: 30vh;
+}
+.container {
+ width: fit-content;
+ display: block;
+ margin: auto;
+}
+.form {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+}
+.logo {
+ background-image: url('../../../assets/logo.png');
+ background-size: cover;
+ position: absolute;
+ top: 10px;
+ right: 10px;
+ width: 250px;
+ height: 250px;
+ opacity: 0.6;
+ }
+mat-form-field {
+ width: 100%;
+}
+.user {
+ text-align: right;
+}
+.load {
+ text-align: center;
+}
+.loading-container {
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ background-color: rgba(100, 100, 100, 0.3);
+ z-index: 1400;
+ }
+ .loading-img {
+ position: absolute;
+ margin: auto;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ }
+/* for mobile */
+@media screen and (max-width: 700px) {
+ .container {
+ width: 90%;
+ }
+ .logo {
+ width: 150px;
+ height: 150px;
+ }
+}
diff --git a/Frontend/src/app/components/login-page/login-page.component.ts b/Frontend/src/app/components/login-page/login-page.component.ts
index 71a623a..1d5152d 100644
--- a/Frontend/src/app/components/login-page/login-page.component.ts
+++ b/Frontend/src/app/components/login-page/login-page.component.ts
@@ -1,98 +1,98 @@
-import { Component, NgZone, OnInit } from '@angular/core';
-import { Router } from '@angular/router';
-import jwt_decode from "jwt-decode";
-import { AuthService } from 'src/app/auth/auth.service';
-import { User } from 'src/app/models/user.model';
-import { NotificationsService } from 'src/app/services/notifications.service';
-import { environment } from 'src/environments/environment';
-
-@Component({
- selector: 'app-login-page',
- templateUrl: './login-page.component.html',
- styleUrls: ['./login-page.component.scss']
-})
-
-export class LoginPageComponent implements OnInit {
- constructor(
- private router$: Router,
- private auth$: AuthService,
- private ngZone$: NgZone,
- private notifications$: NotificationsService
- ) { }
-
- loading = false;
-
- ngOnInit(): void {
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- window.onGoogleLibraryLoad = () => {
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- google.accounts.id.initialize({
- client_id: environment.google.clientId,
- callback: this.handleCredentialResponse.bind(this),
- auto_select: true,
- cancel_on_tap_outside: true
- });
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- google.accounts.id.renderButton(
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- document.getElementById("google-button"),
- { theme: "outline", size: "large", width: "100%" }
- );
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- google.accounts.id.prompt();
- };
- }
-
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- async handleCredentialResponse(response: any) {
- try {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const responsePayload: any = jwt_decode(response.credential);
- this.auth$.user = new User({
- googleCredentials: response.credential,
- userName: `${responsePayload.given_name} ${responsePayload.family_name}`,
- email: responsePayload.email,
- avatar: responsePayload.picture
- });
- this.ngZone$.run(() => {
- this.loading = true;
- });
- this.auth$.googleCredential = response.credential;
- await this.auth$.getAPIToken();
- this.ngZone$.run(() => {
- this.router$.navigate(['/app']);
- });
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- } catch (e: any) {
- console.error('handleCredentialResponse', e);
- this.ngZone$.run(() => {
- this.loading = false;
- });
- if (e.status === 401) {
- this.ngZone$.run(() => {
- this.notifications$.add({
- text: "User not exists in DiunaBI database.",
- btn: "OK",
- duration: 15000
- });
- });
- } else {
- this.ngZone$.run(() => {
- this.notifications$.add({
- text: "DiunaBI server not responded.",
- btn: "OK",
- duration: 15000
- });
- });
- }
- } finally {
- this.loading = false;
- }
- }
-}
-
+import { Component, NgZone, OnInit } from '@angular/core';
+import { Router } from '@angular/router';
+import jwt_decode from "jwt-decode";
+import { AuthService } from 'src/app/auth/auth.service';
+import { User } from 'src/app/models/user.model';
+import { NotificationsService } from 'src/app/services/notifications.service';
+import { environment } from 'src/environments/environment';
+
+@Component({
+ selector: 'app-login-page',
+ templateUrl: './login-page.component.html',
+ styleUrls: ['./login-page.component.scss']
+})
+
+export class LoginPageComponent implements OnInit {
+ constructor(
+ private router$: Router,
+ private auth$: AuthService,
+ private ngZone$: NgZone,
+ private notifications$: NotificationsService
+ ) { }
+
+ loading = false;
+
+ ngOnInit(): void {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ window.onGoogleLibraryLoad = () => {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ google.accounts.id.initialize({
+ client_id: environment.google.clientId,
+ callback: this.handleCredentialResponse.bind(this),
+ auto_select: true,
+ cancel_on_tap_outside: true
+ });
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ google.accounts.id.renderButton(
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ document.getElementById("google-button"),
+ { theme: "outline", size: "large", width: "100%" }
+ );
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ google.accounts.id.prompt();
+ };
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ async handleCredentialResponse(response: any) {
+ try {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const responsePayload: any = jwt_decode(response.credential);
+ this.auth$.user = new User({
+ googleCredentials: response.credential,
+ userName: `${responsePayload.given_name} ${responsePayload.family_name}`,
+ email: responsePayload.email,
+ avatar: responsePayload.picture
+ });
+ this.ngZone$.run(() => {
+ this.loading = true;
+ });
+ this.auth$.googleCredential = response.credential;
+ await this.auth$.getAPIToken();
+ this.ngZone$.run(() => {
+ this.router$.navigate(['/app']);
+ });
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (e: any) {
+ console.error('handleCredentialResponse', e);
+ this.ngZone$.run(() => {
+ this.loading = false;
+ });
+ if (e.status === 401) {
+ this.ngZone$.run(() => {
+ this.notifications$.add({
+ text: "User not exists in DiunaBI database.",
+ btn: "OK",
+ duration: 15000
+ });
+ });
+ } else {
+ this.ngZone$.run(() => {
+ this.notifications$.add({
+ text: "DiunaBI server not responded.",
+ btn: "OK",
+ duration: 15000
+ });
+ });
+ }
+ } finally {
+ this.loading = false;
+ }
+ }
+}
+
diff --git a/Frontend/src/app/components/notifications/notifications.component.scss b/Frontend/src/app/components/notifications/notifications.component.scss
index 3b2e934..f0be707 100644
--- a/Frontend/src/app/components/notifications/notifications.component.scss
+++ b/Frontend/src/app/components/notifications/notifications.component.scss
@@ -1,15 +1,15 @@
-mat-card {
- margin-bottom: 3px;
- background-color: rgba(255, 145, 0, 0.4);
-}
-.action-button {
- cursor: pointer;
-}
-.text {
- float: left;
-}
-.btn {
- float: right;
- color: red;
- margin-left: 5px;
+mat-card {
+ margin-bottom: 3px;
+ background-color: rgba(255, 145, 0, 0.4);
+}
+.action-button {
+ cursor: pointer;
+}
+.text {
+ float: left;
+}
+.btn {
+ float: right;
+ color: red;
+ margin-left: 5px;
}
\ No newline at end of file
diff --git a/Frontend/src/app/interceptors/auth.interceptor.ts b/Frontend/src/app/interceptors/auth.interceptor.ts
index b5cdb70..bfefc4a 100644
--- a/Frontend/src/app/interceptors/auth.interceptor.ts
+++ b/Frontend/src/app/interceptors/auth.interceptor.ts
@@ -1,56 +1,56 @@
-import { Injectable } from '@angular/core';
-import {
- HttpRequest,
- HttpHandler,
- HttpEvent,
- HttpInterceptor
-} from '@angular/common/http';
-import { AuthService } from '../auth/auth.service';
-import { EMPTY, Observable } from 'rxjs';
-import moment from 'moment';
-import { catchError, mergeMap } from 'rxjs/operators';
-import { NotificationsService } from '../services/notifications.service';
-
-@Injectable()
-export class AuthInterceptor implements HttpInterceptor {
- constructor(
- private auth$: AuthService,
- private notifications$: NotificationsService
- ) { }
-
- intercept(request: HttpRequest
, next: HttpHandler): Observable> {
- console.log('Welcome to interceptor:', request.url);
- console.log('IsAuth?', request.url.includes('/auth/apiToken'));
- if (!request.url.includes('/auth/apiToken')) {
- console.log(this.auth$.expirationTime.format(), moment.utc().format());
- if (this.auth$.expirationTime.isBefore(moment.utc())) {
- console.log('Need to refresh token');
- return this.auth$.getAPITokenObservable().pipe(
- mergeMap(() => {
- console.log('New token is ready');
- return next.handle(request.clone({
- headers: request.headers.set('Authorization', `Bearer ${this.auth$.apiToken}`),
- }));
- }),
- catchError(() => {
- this.notifications$.add({
- text: "User session is expired and unable to restore. Please restart the app.",
- btn: "Restart",
- action: () => { window.location.reload(); },
- duration: 5000,
- });
- return EMPTY;
- })
- );
- } else {
- console.log('TOken is fine');
- return next.handle(request.clone({
- headers: request.headers.set('Authorization', `Bearer ${this.auth$.apiToken}`),
- }));
- }
- } else {
- return next.handle(request);
- }
- }
-}
-
+import { Injectable } from '@angular/core';
+import {
+ HttpRequest,
+ HttpHandler,
+ HttpEvent,
+ HttpInterceptor
+} from '@angular/common/http';
+import { AuthService } from '../auth/auth.service';
+import { EMPTY, Observable } from 'rxjs';
+import moment from 'moment';
+import { catchError, mergeMap } from 'rxjs/operators';
+import { NotificationsService } from '../services/notifications.service';
+
+@Injectable()
+export class AuthInterceptor implements HttpInterceptor {
+ constructor(
+ private auth$: AuthService,
+ private notifications$: NotificationsService
+ ) { }
+
+ intercept(request: HttpRequest, next: HttpHandler): Observable> {
+ console.log('Welcome to interceptor:', request.url);
+ console.log('IsAuth?', request.url.includes('/auth/apiToken'));
+ if (!request.url.includes('/auth/apiToken')) {
+ console.log(this.auth$.expirationTime.format(), moment.utc().format());
+ if (this.auth$.expirationTime.isBefore(moment.utc())) {
+ console.log('Need to refresh token');
+ return this.auth$.getAPITokenObservable().pipe(
+ mergeMap(() => {
+ console.log('New token is ready');
+ return next.handle(request.clone({
+ headers: request.headers.set('Authorization', `Bearer ${this.auth$.apiToken}`),
+ }));
+ }),
+ catchError(() => {
+ this.notifications$.add({
+ text: "User session is expired and unable to restore. Please restart the app.",
+ btn: "Restart",
+ action: () => { window.location.reload(); },
+ duration: 5000,
+ });
+ return EMPTY;
+ })
+ );
+ } else {
+ console.log('TOken is fine');
+ return next.handle(request.clone({
+ headers: request.headers.set('Authorization', `Bearer ${this.auth$.apiToken}`),
+ }));
+ }
+ } else {
+ return next.handle(request);
+ }
+ }
+}
+
diff --git a/Frontend/src/app/interceptors/loader.interceptor.ts b/Frontend/src/app/interceptors/loader.interceptor.ts
index bcc82d1..4800a5c 100644
--- a/Frontend/src/app/interceptors/loader.interceptor.ts
+++ b/Frontend/src/app/interceptors/loader.interceptor.ts
@@ -1,42 +1,42 @@
-import { Injectable } from '@angular/core';
-import {
- HttpRequest,
- HttpHandler,
- HttpEvent,
- HttpInterceptor
-} from '@angular/common/http';
-import { finalize, Observable } from 'rxjs';
-import { DataService } from '../services/data.service';
-
-@Injectable()
-export class LoaderInterceptor implements HttpInterceptor {
-
- private tasks = 0;
-
- constructor(
- private data$: DataService
- ) { }
-
- intercept(request: HttpRequest, next: HttpHandler): Observable> {
- this.addTask();
- return next.handle(request).pipe(
- finalize(() => {
- this.removeTask();
- })
- );
- }
-
- addTask() {
- this.tasks++;
- if (this.tasks === 1) {
- this.data$.showLoader.next(true);
- }
- }
-
- removeTask() {
- this.tasks--;
- if (this.tasks === 0) {
- this.data$.showLoader.next(false);
- }
- }
-}
+import { Injectable } from '@angular/core';
+import {
+ HttpRequest,
+ HttpHandler,
+ HttpEvent,
+ HttpInterceptor
+} from '@angular/common/http';
+import { finalize, Observable } from 'rxjs';
+import { DataService } from '../services/data.service';
+
+@Injectable()
+export class LoaderInterceptor implements HttpInterceptor {
+
+ private tasks = 0;
+
+ constructor(
+ private data$: DataService
+ ) { }
+
+ intercept(request: HttpRequest, next: HttpHandler): Observable> {
+ this.addTask();
+ return next.handle(request).pipe(
+ finalize(() => {
+ this.removeTask();
+ })
+ );
+ }
+
+ addTask() {
+ this.tasks++;
+ if (this.tasks === 1) {
+ this.data$.showLoader.next(true);
+ }
+ }
+
+ removeTask() {
+ this.tasks--;
+ if (this.tasks === 0) {
+ this.data$.showLoader.next(false);
+ }
+ }
+}
diff --git a/Frontend/src/app/main-view/main-view.component.scss b/Frontend/src/app/main-view/main-view.component.scss
index f21e659..f184863 100644
--- a/Frontend/src/app/main-view/main-view.component.scss
+++ b/Frontend/src/app/main-view/main-view.component.scss
@@ -1,128 +1,128 @@
-.main-container {
- display: flex;
- flex-direction: column;
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
-}
-.sidenav-container {
- flex: 1;
-}
-mat-icon.menu-icon {
- margin-right: 3px;
- color: gray;
-}
-mat-nav-list.menu-sublist {
- padding-left: 10px;
-}
-mat-nav-list.menu-sublist > a {
- font-size: small;
-}
-div.footer {
- text-align: right;
- font-size: smaller;
- color: gray;
- padding-right: 5px;
-}
-.fill-to-right {
- flex: 1 1 auto;
-}
-span.topbar-user-name {
- font-size: small;
-}
-h1.topbar-app-name {
- margin-bottom: 0px;
-}
-mat-sidenav {
- width: 200px;
-}
-.list-container {
- display: flex;
- flex-direction: column;
- min-width: 300px;
- height: 98%;
-}
-.top-list-container {
- display: flex;
- flex-direction: column;
- min-width: 30vh;
- height: 54vh;
-}
-.bottom-list-container {
- display: flex;
- flex-direction: column;
- height: 35vh;
-}
-.table {
- overflow: auto;
- height: 100%;
-}
-.list-header {
- min-height: 50px;
- padding: 4px 12px 0;
-}
-.mat-mdc-form-field {
- font-size: 14px;
- width: 100%;
-}
-mat-form-field.detail-input {
- width: 90%;
- text-align: left;
- color: black;
-}
-mat-form-field.detail-input-full-width {
- width: 96%;
- text-align: left;
- color: black;
-}
-input[disabled] {
- color: black;
- -webkit-text-fill-color: black;
- opacity: 1; /* required on iOS */
-}
-textarea[disabled] {
- color: black;
- -webkit-text-fill-color: black;
- opacity: 1; /* required on iOS */
-}
-.loading-container {
- position: absolute;
- left: 0;
- right: 0;
- top: 0;
- bottom: 0;
- background-color: rgba(100, 100, 100, 0.3);
- z-index: 1400;
-}
-.loading-img {
- position: absolute;
- margin: auto;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
-}
-.flip-container {
- position: absolute;
- left: 0;
- right: 0;
- top: 0;
- bottom: 0;
- background-color: rgba(100, 100, 100, 0.95);
- z-index: 1500;
-}
-.flip-msg {
- margin: auto;
- text-align: center;
- padding-top: 45vh;
- color: rgb(205, 206, 177);
- font-size: larger;
-}
-
-/* links */
-a:link,
-a:visited {
- color: black;
+.main-container {
+ display: flex;
+ flex-direction: column;
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+}
+.sidenav-container {
+ flex: 1;
+}
+mat-icon.menu-icon {
+ margin-right: 3px;
+ color: gray;
+}
+mat-nav-list.menu-sublist {
+ padding-left: 10px;
+}
+mat-nav-list.menu-sublist > a {
+ font-size: small;
+}
+div.footer {
+ text-align: right;
+ font-size: smaller;
+ color: gray;
+ padding-right: 5px;
+}
+.fill-to-right {
+ flex: 1 1 auto;
+}
+span.topbar-user-name {
+ font-size: small;
+}
+h1.topbar-app-name {
+ margin-bottom: 0px;
+}
+mat-sidenav {
+ width: 200px;
+}
+.list-container {
+ display: flex;
+ flex-direction: column;
+ min-width: 300px;
+ height: 98%;
+}
+.top-list-container {
+ display: flex;
+ flex-direction: column;
+ min-width: 30vh;
+ height: 54vh;
+}
+.bottom-list-container {
+ display: flex;
+ flex-direction: column;
+ height: 35vh;
+}
+.table {
+ overflow: auto;
+ height: 100%;
+}
+.list-header {
+ min-height: 50px;
+ padding: 4px 12px 0;
+}
+.mat-mdc-form-field {
+ font-size: 14px;
+ width: 100%;
+}
+mat-form-field.detail-input {
+ width: 90%;
+ text-align: left;
+ color: black;
+}
+mat-form-field.detail-input-full-width {
+ width: 96%;
+ text-align: left;
+ color: black;
+}
+input[disabled] {
+ color: black;
+ -webkit-text-fill-color: black;
+ opacity: 1; /* required on iOS */
+}
+textarea[disabled] {
+ color: black;
+ -webkit-text-fill-color: black;
+ opacity: 1; /* required on iOS */
+}
+.loading-container {
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ background-color: rgba(100, 100, 100, 0.3);
+ z-index: 1400;
+}
+.loading-img {
+ position: absolute;
+ margin: auto;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+.flip-container {
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ background-color: rgba(100, 100, 100, 0.95);
+ z-index: 1500;
+}
+.flip-msg {
+ margin: auto;
+ text-align: center;
+ padding-top: 45vh;
+ color: rgb(205, 206, 177);
+ font-size: larger;
+}
+
+/* links */
+a:link,
+a:visited {
+ color: black;
}
\ No newline at end of file
diff --git a/Frontend/src/app/material.module.ts b/Frontend/src/app/material.module.ts
index 1b3c04a..ab90923 100644
--- a/Frontend/src/app/material.module.ts
+++ b/Frontend/src/app/material.module.ts
@@ -1,73 +1,73 @@
-import {NgModule} from '@angular/core';
-//import { MatAutocompleteModule } from '@angular/material/autocomplete';
-import { MatButtonModule } from '@angular/material/button';
-//import { MatButtonToggleModule } from '@angular/material/button-toggle';
-import { MatCardModule } from '@angular/material/card';
-//import { MatCheckboxModule } from '@angular/material/checkbox';
-//import { MatChipsModule } from '@angular/material/chips';
-//import { MatStepperModule } from '@angular/material/stepper';
-//import { MatDatepickerModule } from '@angular/material/datepicker';
-//import { MatDialogModule } from '@angular/material/dialog';
-//import { MatExpansionModule } from '@angular/material/expansion';
-import { MatGridListModule } from '@angular/material/grid-list';
-import { MatIconModule } from '@angular/material/icon';
-import { MatInputModule } from '@angular/material/input';
-import { MatListModule } from '@angular/material/list';
-import { MatMenuModule } from '@angular/material/menu';
-import { MatPaginatorModule } from '@angular/material/paginator';
-//import { MatProgressBarModule } from '@angular/material/progress-bar';
-//import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
-//import { MatRadioModule } from '@angular/material/radio';
-//import { MatRippleModule } from '@angular/material/core';
-import { MatSelectModule } from '@angular/material/select';
-import { MatSidenavModule } from '@angular/material/sidenav';
-//import { MatSliderModule } from '@angular/material/slider';
-//import { MatSlideToggleModule } from '@angular/material/slide-toggle';
-import { MatSortModule } from '@angular/material/sort';
-import { MatTableModule } from '@angular/material/table';
-//import { MatTabsModule } from '@angular/material/tabs';
-import { MatToolbarModule } from '@angular/material/toolbar';
-//import { MatTooltipModule } from '@angular/material/tooltip';
-//import {CdkTableModule} from '@angular/cdk/table';
-//import {MatBadgeModule} from '@angular/material/badge';
-import {MatBottomSheetModule} from '@angular/material/bottom-sheet';
-
-@NgModule({
- exports: [
- // CdkTableModule,
- // MatAutocompleteModule,
- MatButtonModule,
- // MatButtonToggleModule,
- MatCardModule,
- // MatCheckboxModule,
- // MatChipsModule,
- // MatStepperModule,
- // MatDatepickerModule,
- // MatDialogModule,
- // MatExpansionModule,
- MatGridListModule,
- MatIconModule,
- MatInputModule,
- MatListModule,
- MatMenuModule,
- MatPaginatorModule,
- // MatProgressBarModule,
- // MatProgressSpinnerModule,
- // MatRadioModule,
- // MatRippleModule,
- MatSelectModule,
- // MatSidenavModule,
- // MatSliderModule,
- // MatSlideToggleModule,
- MatSortModule,
- MatTableModule,
- // MatTabsModule,
- MatToolbarModule,
- // MatTooltipModule,
- MatSidenavModule,
- // MatBadgeModule,
- MatBottomSheetModule
- ],
- providers: []
-})
+import {NgModule} from '@angular/core';
+//import { MatAutocompleteModule } from '@angular/material/autocomplete';
+import { MatButtonModule } from '@angular/material/button';
+//import { MatButtonToggleModule } from '@angular/material/button-toggle';
+import { MatCardModule } from '@angular/material/card';
+//import { MatCheckboxModule } from '@angular/material/checkbox';
+//import { MatChipsModule } from '@angular/material/chips';
+//import { MatStepperModule } from '@angular/material/stepper';
+//import { MatDatepickerModule } from '@angular/material/datepicker';
+//import { MatDialogModule } from '@angular/material/dialog';
+//import { MatExpansionModule } from '@angular/material/expansion';
+import { MatGridListModule } from '@angular/material/grid-list';
+import { MatIconModule } from '@angular/material/icon';
+import { MatInputModule } from '@angular/material/input';
+import { MatListModule } from '@angular/material/list';
+import { MatMenuModule } from '@angular/material/menu';
+import { MatPaginatorModule } from '@angular/material/paginator';
+//import { MatProgressBarModule } from '@angular/material/progress-bar';
+//import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
+//import { MatRadioModule } from '@angular/material/radio';
+//import { MatRippleModule } from '@angular/material/core';
+import { MatSelectModule } from '@angular/material/select';
+import { MatSidenavModule } from '@angular/material/sidenav';
+//import { MatSliderModule } from '@angular/material/slider';
+//import { MatSlideToggleModule } from '@angular/material/slide-toggle';
+import { MatSortModule } from '@angular/material/sort';
+import { MatTableModule } from '@angular/material/table';
+//import { MatTabsModule } from '@angular/material/tabs';
+import { MatToolbarModule } from '@angular/material/toolbar';
+//import { MatTooltipModule } from '@angular/material/tooltip';
+//import {CdkTableModule} from '@angular/cdk/table';
+//import {MatBadgeModule} from '@angular/material/badge';
+import {MatBottomSheetModule} from '@angular/material/bottom-sheet';
+
+@NgModule({
+ exports: [
+ // CdkTableModule,
+ // MatAutocompleteModule,
+ MatButtonModule,
+ // MatButtonToggleModule,
+ MatCardModule,
+ // MatCheckboxModule,
+ // MatChipsModule,
+ // MatStepperModule,
+ // MatDatepickerModule,
+ // MatDialogModule,
+ // MatExpansionModule,
+ MatGridListModule,
+ MatIconModule,
+ MatInputModule,
+ MatListModule,
+ MatMenuModule,
+ MatPaginatorModule,
+ // MatProgressBarModule,
+ // MatProgressSpinnerModule,
+ // MatRadioModule,
+ // MatRippleModule,
+ MatSelectModule,
+ // MatSidenavModule,
+ // MatSliderModule,
+ // MatSlideToggleModule,
+ MatSortModule,
+ MatTableModule,
+ // MatTabsModule,
+ MatToolbarModule,
+ // MatTooltipModule,
+ MatSidenavModule,
+ // MatBadgeModule,
+ MatBottomSheetModule
+ ],
+ providers: []
+})
export class MaterialModule {}
\ No newline at end of file
diff --git a/Frontend/src/app/models/base.model.ts b/Frontend/src/app/models/base.model.ts
index 932db5f..17dde7a 100644
--- a/Frontend/src/app/models/base.model.ts
+++ b/Frontend/src/app/models/base.model.ts
@@ -1,35 +1,35 @@
-import { Moment } from 'moment';
-
-import { Deserializable } from './deserializable.model';
-import { Serializable } from './serializable.model';
-import * as moment from 'moment';
-import { User } from './user.model';
-
-export class Base implements Deserializable, Serializable {
- id?: string;
- createdAt?: Moment;
- modifiedAt?: Moment;
- createdById?: string;
- modifiedById?: string;
- createdBy?: User;
- modifiedBy?: User;
-
- constructor(data: Partial = {}) {
- Object.assign(this, data);
- }
-
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- deserialize(input: any): this {
- if (input.createdAt) { input.createdAt = moment(input.createdAt).utc(true); }
- if (input.modifiedAt) { input.modifiedAt = moment(input.modifiedAt).utc(true); }
- if (input.createdBy) { input.createdBy = new User(input.createdBy); }
- if (input.modifiedBy) { input.modifiedBy = new User(input.modifiedBy); }
- Object.assign(this, input);
- return this;
- }
-
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- serialize() : any {
- return Object.assign({}, this);
- }
+import { Moment } from 'moment';
+
+import { Deserializable } from './deserializable.model';
+import { Serializable } from './serializable.model';
+import * as moment from 'moment';
+import { User } from './user.model';
+
+export class Base implements Deserializable, Serializable {
+ id?: string;
+ createdAt?: Moment;
+ modifiedAt?: Moment;
+ createdById?: string;
+ modifiedById?: string;
+ createdBy?: User;
+ modifiedBy?: User;
+
+ constructor(data: Partial = {}) {
+ Object.assign(this, data);
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ deserialize(input: any): this {
+ if (input.createdAt) { input.createdAt = moment(input.createdAt).utc(true); }
+ if (input.modifiedAt) { input.modifiedAt = moment(input.modifiedAt).utc(true); }
+ if (input.createdBy) { input.createdBy = new User(input.createdBy); }
+ if (input.modifiedBy) { input.modifiedBy = new User(input.modifiedBy); }
+ Object.assign(this, input);
+ return this;
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ serialize() : any {
+ return Object.assign({}, this);
+ }
}
\ No newline at end of file
diff --git a/Frontend/src/app/models/deserializable.model.ts b/Frontend/src/app/models/deserializable.model.ts
index f2457f4..7cc09b2 100644
--- a/Frontend/src/app/models/deserializable.model.ts
+++ b/Frontend/src/app/models/deserializable.model.ts
@@ -1,4 +1,4 @@
-export interface Deserializable {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- deserialize(input: any): this;
+export interface Deserializable {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ deserialize(input: any): this;
}
\ No newline at end of file
diff --git a/Frontend/src/app/models/layer.model.ts b/Frontend/src/app/models/layer.model.ts
index 0747ffb..b20f8b3 100644
--- a/Frontend/src/app/models/layer.model.ts
+++ b/Frontend/src/app/models/layer.model.ts
@@ -1,124 +1,124 @@
-import { Base } from './base.model';
-import { UntypedFormBuilder, Validators, UntypedFormGroup } from '@angular/forms';
-import { HttpClient } from '@angular/common/http';
-import { environment } from 'src/environments/environment';
-import { map } from 'rxjs';
-import { Record } from 'src/app/models/record.model';
-
-export class Layer extends Base {
- // eslint-disable-next-line @typescript-eslint/ban-types
- number?: Number;
- source?: string;
- name?: string;
- records: Record[] = [];
- created?: string;
-
- constructor(data: Partial = {}) {
- super();
- Object.assign(this, data);
- }
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- override deserialize(input: any): this {
- Object.assign(this, Object.assign(this, super.deserialize(input)));
- if (this.records) { this.records = this.records.map(x => new Record().deserialize(x)); }
- return this;
- }
- override serialize() {
- this.number = 0; // will be overrided in backend
- return Object.assign({}, this);
- }
- static getForm(fb: UntypedFormBuilder) {
- return fb.group({
- id: [null],
- name: ['', Validators.required],
- source: ['', Validators.required],
- sheetId: '1G_Hu8DTP-PSPNXTaVYhc_ppnTQi6HWoA4oXSSdUmM9E',
- createdAt: '',
- modifiedAt: '',
- createdBy: '',
- modifiedBy: '',
- modified: '',
- created: ''
- });
- }
- fillForm(form: UntypedFormGroup) {
- form.patchValue(this);
- form.patchValue({
- createdBy: this.createdBy?.userName,
- modifiedBy: this.modifiedBy?.userName
- });
- }
- loadForm(form: UntypedFormGroup) {
- for (const field of Object.keys(form.controls)) {
- this[field as keyof Layer] = form.controls[field].value;
- }
- this.createdBy = undefined;
- this.modifiedBy = undefined;
- }
- //API Actions
- static add(input: Layer, _http: HttpClient): Promise {
- return new Promise((resolve, reject) => {
- _http.post(`${environment.api.url}/layers`, { ...input.serialize(), }).subscribe({
- next: (data) => resolve(data),
- error: (e) => reject(e)
- }
- );
- });
- }
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- static getList(_http: HttpClient): any {
- return new Promise((resolve, reject) => {
- _http.get(`${environment.api.url}/layers`)
- .pipe(map(data => data.map(x => new Layer().deserialize(x))))
- .subscribe({
- next: (data) => resolve(data),
- error: (e) => reject(e)
- })
- });
- }
- static getById(id: string, _http: HttpClient): Promise {
- return new Promise((resolve, reject) => {
- _http.get(`${environment.api.url}/layers/${id}`).pipe(map(x => new Layer().deserialize(x))).subscribe({
- next: (data) => resolve(data),
- error: (e) => reject(e)
- })
- });
- }
- static parseFile(file: File, _http: HttpClient): Promise {
- const formData = new FormData();
- formData.append(file.name, file);
- return new Promise((resolve, reject) => {
- _http.post(`${environment.api.url}/layers/parseFile`, formData,
- ).pipe(map(data => data.map(x => new Layer().deserialize(x))))
- .subscribe({
- next: (data) => {
- resolve(data);
- },
- error: (e) => reject(e)
- })
- })
- }
- static parseGoogleSheet(sheetId: string, _http: HttpClient): Promise {
- return new Promise((resolve, reject) => {
- _http.get(`${environment.api.url}/layers/parseGoogleSheet/${sheetId}`,
- ).pipe(map(data => new Layer().deserialize(data)))
- .subscribe({
- next: (data) => {
- resolve(data);
- },
- error: (e) => reject(e)
- })
- })
- }
- static exportToGoogleSheet(id: string, _http: HttpClient): Promise {
- return new Promise((resolve, reject) => {
- _http.get(`${environment.api.url}/layers/exportToGoogleSheet/${id}`,
- ).subscribe({
- next: (data) => {
- resolve(data);
- },
- error: (e) => reject(e)
- })
- })
- }
+import { Base } from './base.model';
+import { UntypedFormBuilder, Validators, UntypedFormGroup } from '@angular/forms';
+import { HttpClient } from '@angular/common/http';
+import { environment } from 'src/environments/environment';
+import { map } from 'rxjs';
+import { Record } from 'src/app/models/record.model';
+
+export class Layer extends Base {
+ // eslint-disable-next-line @typescript-eslint/ban-types
+ number?: Number;
+ source?: string;
+ name?: string;
+ records: Record[] = [];
+ created?: string;
+
+ constructor(data: Partial = {}) {
+ super();
+ Object.assign(this, data);
+ }
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ override deserialize(input: any): this {
+ Object.assign(this, Object.assign(this, super.deserialize(input)));
+ if (this.records) { this.records = this.records.map(x => new Record().deserialize(x)); }
+ return this;
+ }
+ override serialize() {
+ this.number = 0; // will be overrided in backend
+ return Object.assign({}, this);
+ }
+ static getForm(fb: UntypedFormBuilder) {
+ return fb.group({
+ id: [null],
+ name: ['', Validators.required],
+ source: ['', Validators.required],
+ sheetId: '1G_Hu8DTP-PSPNXTaVYhc_ppnTQi6HWoA4oXSSdUmM9E',
+ createdAt: '',
+ modifiedAt: '',
+ createdBy: '',
+ modifiedBy: '',
+ modified: '',
+ created: ''
+ });
+ }
+ fillForm(form: UntypedFormGroup) {
+ form.patchValue(this);
+ form.patchValue({
+ createdBy: this.createdBy?.userName,
+ modifiedBy: this.modifiedBy?.userName
+ });
+ }
+ loadForm(form: UntypedFormGroup) {
+ for (const field of Object.keys(form.controls)) {
+ this[field as keyof Layer] = form.controls[field].value;
+ }
+ this.createdBy = undefined;
+ this.modifiedBy = undefined;
+ }
+ //API Actions
+ static add(input: Layer, _http: HttpClient): Promise {
+ return new Promise((resolve, reject) => {
+ _http.post(`${environment.api.url}/layers`, { ...input.serialize(), }).subscribe({
+ next: (data) => resolve(data),
+ error: (e) => reject(e)
+ }
+ );
+ });
+ }
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ static getList(_http: HttpClient): any {
+ return new Promise((resolve, reject) => {
+ _http.get(`${environment.api.url}/layers`)
+ .pipe(map(data => data.map(x => new Layer().deserialize(x))))
+ .subscribe({
+ next: (data) => resolve(data),
+ error: (e) => reject(e)
+ })
+ });
+ }
+ static getById(id: string, _http: HttpClient): Promise {
+ return new Promise((resolve, reject) => {
+ _http.get(`${environment.api.url}/layers/${id}`).pipe(map(x => new Layer().deserialize(x))).subscribe({
+ next: (data) => resolve(data),
+ error: (e) => reject(e)
+ })
+ });
+ }
+ static parseFile(file: File, _http: HttpClient): Promise {
+ const formData = new FormData();
+ formData.append(file.name, file);
+ return new Promise((resolve, reject) => {
+ _http.post(`${environment.api.url}/layers/parseFile`, formData,
+ ).pipe(map(data => data.map(x => new Layer().deserialize(x))))
+ .subscribe({
+ next: (data) => {
+ resolve(data);
+ },
+ error: (e) => reject(e)
+ })
+ })
+ }
+ static parseGoogleSheet(sheetId: string, _http: HttpClient): Promise {
+ return new Promise((resolve, reject) => {
+ _http.get(`${environment.api.url}/layers/parseGoogleSheet/${sheetId}`,
+ ).pipe(map(data => new Layer().deserialize(data)))
+ .subscribe({
+ next: (data) => {
+ resolve(data);
+ },
+ error: (e) => reject(e)
+ })
+ })
+ }
+ static exportToGoogleSheet(id: string, _http: HttpClient): Promise {
+ return new Promise((resolve, reject) => {
+ _http.get(`${environment.api.url}/layers/exportToGoogleSheet/${id}`,
+ ).subscribe({
+ next: (data) => {
+ resolve(data);
+ },
+ error: (e) => reject(e)
+ })
+ })
+ }
}
\ No newline at end of file
diff --git a/Frontend/src/app/models/record.model.ts b/Frontend/src/app/models/record.model.ts
index c5db352..b48a762 100644
--- a/Frontend/src/app/models/record.model.ts
+++ b/Frontend/src/app/models/record.model.ts
@@ -1,22 +1,22 @@
-import { Base } from './base.model';
-
-export class Record extends Base {
- code?: string;
- value?: number;
- desc1?: string;
- desc2?: string;
- desc3?: string;
- desc4?: string;
- desc5?: string;
-
- constructor(data: Partial = {}) {
- super();
- Object.assign(this, data);
- }
-
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- override deserialize(input: any): this {
- Object.assign(this, Object.assign(this, super.deserialize(input)));
- return this;
- }
+import { Base } from './base.model';
+
+export class Record extends Base {
+ code?: string;
+ value?: number;
+ desc1?: string;
+ desc2?: string;
+ desc3?: string;
+ desc4?: string;
+ desc5?: string;
+
+ constructor(data: Partial = {}) {
+ super();
+ Object.assign(this, data);
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ override deserialize(input: any): this {
+ Object.assign(this, Object.assign(this, super.deserialize(input)));
+ return this;
+ }
}
\ No newline at end of file
diff --git a/Frontend/src/app/models/serializable.model.ts b/Frontend/src/app/models/serializable.model.ts
index 2e016fe..f65da47 100644
--- a/Frontend/src/app/models/serializable.model.ts
+++ b/Frontend/src/app/models/serializable.model.ts
@@ -1,4 +1,4 @@
-export interface Serializable {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- serialize(input: this): any;
+export interface Serializable {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ serialize(input: this): any;
}
\ No newline at end of file
diff --git a/Frontend/src/app/models/user.model.ts b/Frontend/src/app/models/user.model.ts
index 460aa13..58a0b34 100644
--- a/Frontend/src/app/models/user.model.ts
+++ b/Frontend/src/app/models/user.model.ts
@@ -1,11 +1,11 @@
-export class User {
- id!: string;
- email!: string;
- userName!: string;
- googleCredentials!: string;
- avatar?: string;
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- constructor(input: any) {
- Object.assign(this, input)
- }
+export class User {
+ id!: string;
+ email!: string;
+ userName!: string;
+ googleCredentials!: string;
+ avatar?: string;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ constructor(input: any) {
+ Object.assign(this, input)
+ }
}
\ No newline at end of file
diff --git a/Frontend/src/app/modules/dashboard/board/board.component.ts b/Frontend/src/app/modules/dashboard/board/board.component.ts
index d2b9fe4..41c3d00 100644
--- a/Frontend/src/app/modules/dashboard/board/board.component.ts
+++ b/Frontend/src/app/modules/dashboard/board/board.component.ts
@@ -1,14 +1,14 @@
-import { Component } from '@angular/core';
-import { DeviceService } from 'src/app/services/device.service';
-
-
-@Component({
- selector: 'app-board',
- templateUrl: './board.component.html',
- styleUrls: ['./board.component.scss']
-})
-export class BoardComponent {
- constructor(
- public _device: DeviceService
- ) { }
-}
+import { Component } from '@angular/core';
+import { DeviceService } from 'src/app/services/device.service';
+
+
+@Component({
+ selector: 'app-board',
+ templateUrl: './board.component.html',
+ styleUrls: ['./board.component.scss']
+})
+export class BoardComponent {
+ constructor(
+ public _device: DeviceService
+ ) { }
+}
diff --git a/Frontend/src/app/modules/dashboard/dashboard-routing.module.ts b/Frontend/src/app/modules/dashboard/dashboard-routing.module.ts
index 7f8484d..f14c8b9 100644
--- a/Frontend/src/app/modules/dashboard/dashboard-routing.module.ts
+++ b/Frontend/src/app/modules/dashboard/dashboard-routing.module.ts
@@ -1,16 +1,16 @@
-import { NgModule } from '@angular/core';
-import { RouterModule, Routes } from '@angular/router';
-import { BoardComponent } from './board/board.component';
-
-const routes: Routes = [
- {
- path: '',
- component: BoardComponent
- }
-];
-
-@NgModule({
- imports: [RouterModule.forChild(routes)],
- exports: [RouterModule]
-})
-export class DashboardRoutingModule { }
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { BoardComponent } from './board/board.component';
+
+const routes: Routes = [
+ {
+ path: '',
+ component: BoardComponent
+ }
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule]
+})
+export class DashboardRoutingModule { }
diff --git a/Frontend/src/app/modules/dashboard/dashboard.module.ts b/Frontend/src/app/modules/dashboard/dashboard.module.ts
index 3a64cff..b119f9c 100644
--- a/Frontend/src/app/modules/dashboard/dashboard.module.ts
+++ b/Frontend/src/app/modules/dashboard/dashboard.module.ts
@@ -1,17 +1,17 @@
-import { NgModule } from '@angular/core';
-import { CommonModule } from '@angular/common';
-
-import { DashboardRoutingModule } from './dashboard-routing.module';
-import { BoardComponent } from './board/board.component';
-
-
-@NgModule({
- declarations: [
- BoardComponent
- ],
- imports: [
- CommonModule,
- DashboardRoutingModule
- ]
-})
-export class DashboardModule { }
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { DashboardRoutingModule } from './dashboard-routing.module';
+import { BoardComponent } from './board/board.component';
+
+
+@NgModule({
+ declarations: [
+ BoardComponent
+ ],
+ imports: [
+ CommonModule,
+ DashboardRoutingModule
+ ]
+})
+export class DashboardModule { }
diff --git a/Frontend/src/app/modules/layers/layer-edit/layer-edit.component.scss b/Frontend/src/app/modules/layers/layer-edit/layer-edit.component.scss
index 38ef489..561ea11 100644
--- a/Frontend/src/app/modules/layers/layer-edit/layer-edit.component.scss
+++ b/Frontend/src/app/modules/layers/layer-edit/layer-edit.component.scss
@@ -1,5 +1,5 @@
-@import "../../../main-view/main-view.component.scss";
-
-.file-input {
- display: none;
+@import "../../../main-view/main-view.component.scss";
+
+.file-input {
+ display: none;
}
\ No newline at end of file
diff --git a/Frontend/src/app/modules/layers/layers-routing.module.ts b/Frontend/src/app/modules/layers/layers-routing.module.ts
index 67cdc72..2a69c7f 100644
--- a/Frontend/src/app/modules/layers/layers-routing.module.ts
+++ b/Frontend/src/app/modules/layers/layers-routing.module.ts
@@ -1,17 +1,17 @@
-import { NgModule } from '@angular/core';
-import { RouterModule, Routes } from '@angular/router';
-import { LayerDetailComponent } from './layer-detail/layer-detail.component';
-import { LayerEditComponent } from './layer-edit/layer-edit.component';
-import { LayersListComponent } from './layers-list/layers-list.component';
-
-const routes: Routes = [
- { path: '', component: LayersListComponent },
- { path: 'Edit/:id', component: LayerEditComponent },
- { path: 'Detail/:id', component: LayerDetailComponent }
-];
-
-@NgModule({
- imports: [RouterModule.forChild(routes)],
- exports: [RouterModule]
-})
-export class LayersRoutingModule { }
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { LayerDetailComponent } from './layer-detail/layer-detail.component';
+import { LayerEditComponent } from './layer-edit/layer-edit.component';
+import { LayersListComponent } from './layers-list/layers-list.component';
+
+const routes: Routes = [
+ { path: '', component: LayersListComponent },
+ { path: 'Edit/:id', component: LayerEditComponent },
+ { path: 'Detail/:id', component: LayerDetailComponent }
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule]
+})
+export class LayersRoutingModule { }
diff --git a/Utils/loadStagingDB.ps1 b/Utils/loadStagingDB.ps1
index 7b313d1..484dc9e 100644
--- a/Utils/loadStagingDB.ps1
+++ b/Utils/loadStagingDB.ps1
@@ -1,88 +1,88 @@
-Function IsDatabaseExists{
- param([string]$containerId, [string]$database, [string]$sqlPass)
- $query = "IF EXISTS
- (SELECT name FROM master.sys.databases WHERE name = N'$database')
- PRINT 'yes'
- ELSE
- PRINT 'no'"
- return (docker exec $containerId /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P $sqlPass -Q $query)
- # USE master; ALTER DATABASE b-crm-master; SET SINGLE_USER WITH ROLLBACK IMMEDIATE; DROP DATABASE b-crm-master;
-}
-Function DropDatabase{
- param([string]$containerId, [string]$database, [string]$sqlPass)
- $query = "USE master;
- ALTER DATABASE [$database]
- SET SINGLE_USER
- WITH ROLLBACK IMMEDIATE;
- GO
- DROP DATABASE [$database];"
- docker exec $containerId /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P $sqlPass -Q $query > $null
- return;
- # /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P 'v](8Lc|RfG' -Q "USE master; ALTER DATABASE b-crm-master; SET SINGLE_USER WITH ROLLBACK IMMEDIATE; DROP DATABASE b-crm-master;"
-}
-Function AttachDatabase{
- param([string]$containerId, [string]$database, [string]$sqlPass, [string]$mdfName, [string]$ldfName)
- $query = "CREATE DATABASE [$database]
- ON (FILENAME = N'/var/opt/mssql/data/$mdfName'),
- (FILENAME = N'/var/opt/mssql/data/$ldfName') FOR ATTACH;
- ALTER DATABASE [$database] SET READ_WRITE;"
- docker exec $containerId /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P $sqlPass -Q $query
- return;
-}
-Function CopyFile{
- param([string]$containerId, [string]$fileName)
- docker cp ./Temp/$fileName $containerId"://var/opt/mssql/data/$fileName"
- docker exec --user root $containerId chown mssql:root /var/opt/mssql/data/$fileName
- return;
-}
-
-if ((Split-Path (Get-Location) -Leaf) -ne "DiunaBI") {
- Write-Host "Error: Run script from main source directory.";
- Exit;
-}
-try {
- $containerId = (docker ps | Select-String "mssql").Line.split(" ")[0]
-} catch {
- Write-Host "Error: MSSQL container not exists (or Docker is not running)";
- Exit;
-}
-Write-Host "MSSQL container id: "$containerId;
-
-$sqlPass = "v](8Lc|RfG";
-# Let's do the job!
-@("diuna").ForEach({
- $database = $_;
- $ldfName = $database+"_log.ldf";
- $mdfName = $database+".mdf";
-
- Write-Host "Restoring database: "$database
- # Download mdf/ldf nd check if files are new (donwload with success)
- scp "crm.bim-it.pl:/var/opt/mssql/data/$mdfName" ./Temp/
- if (((Get-Date) - ((Get-Item ./Temp/$mdfName).LastWriteTime)).TotalMinutes -gt 5) {
- Write-Host "Error: $mdfName was not downloaded correctly."
- continue;
- }
- scp "crm.bim-it.pl:/var/opt/mssql/data/$ldfName" ./Temp/
- if (((Get-Date) - ((Get-Item ./Temp/$ldfName).LastWriteTime)).TotalMinutes -gt 5) {
- Write-Host "Error: $ldfName was not downloaded correctly."
- continue;
- }
-
- #drop existing database
- DropDatabase $containerId $database $sqlPass;
- if ((IsDatabaseExists $containerId $database $sqlPass) -eq 'yes') {
- Write-Host "Error: $database still exists (drop error)"
- continue;
- }
- #copy new files
- CopyFile $containerId $mdfName
- CopyFile $containerId $ldfName
- #attach databases in container
- AttachDatabase $containerId $database $sqlPass $mdfName $ldfName;
- if ((IsDatabaseExists $containerId $database $sqlPass) -eq 'no') {
- Write-Host "Error: $database still not exists (attach error)"
- continue;
- }
- Write-Host "OK";
-});
+Function IsDatabaseExists{
+ param([string]$containerId, [string]$database, [string]$sqlPass)
+ $query = "IF EXISTS
+ (SELECT name FROM master.sys.databases WHERE name = N'$database')
+ PRINT 'yes'
+ ELSE
+ PRINT 'no'"
+ return (docker exec $containerId /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P $sqlPass -Q $query)
+ # USE master; ALTER DATABASE b-crm-master; SET SINGLE_USER WITH ROLLBACK IMMEDIATE; DROP DATABASE b-crm-master;
+}
+Function DropDatabase{
+ param([string]$containerId, [string]$database, [string]$sqlPass)
+ $query = "USE master;
+ ALTER DATABASE [$database]
+ SET SINGLE_USER
+ WITH ROLLBACK IMMEDIATE;
+ GO
+ DROP DATABASE [$database];"
+ docker exec $containerId /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P $sqlPass -Q $query > $null
+ return;
+ # /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P 'v](8Lc|RfG' -Q "USE master; ALTER DATABASE b-crm-master; SET SINGLE_USER WITH ROLLBACK IMMEDIATE; DROP DATABASE b-crm-master;"
+}
+Function AttachDatabase{
+ param([string]$containerId, [string]$database, [string]$sqlPass, [string]$mdfName, [string]$ldfName)
+ $query = "CREATE DATABASE [$database]
+ ON (FILENAME = N'/var/opt/mssql/data/$mdfName'),
+ (FILENAME = N'/var/opt/mssql/data/$ldfName') FOR ATTACH;
+ ALTER DATABASE [$database] SET READ_WRITE;"
+ docker exec $containerId /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P $sqlPass -Q $query
+ return;
+}
+Function CopyFile{
+ param([string]$containerId, [string]$fileName)
+ docker cp ./Temp/$fileName $containerId"://var/opt/mssql/data/$fileName"
+ docker exec --user root $containerId chown mssql:root /var/opt/mssql/data/$fileName
+ return;
+}
+
+if ((Split-Path (Get-Location) -Leaf) -ne "DiunaBI") {
+ Write-Host "Error: Run script from main source directory.";
+ Exit;
+}
+try {
+ $containerId = (docker ps | Select-String "mssql").Line.split(" ")[0]
+} catch {
+ Write-Host "Error: MSSQL container not exists (or Docker is not running)";
+ Exit;
+}
+Write-Host "MSSQL container id: "$containerId;
+
+$sqlPass = "v](8Lc|RfG";
+# Let's do the job!
+@("diuna").ForEach({
+ $database = $_;
+ $ldfName = $database+"_log.ldf";
+ $mdfName = $database+".mdf";
+
+ Write-Host "Restoring database: "$database
+ # Download mdf/ldf nd check if files are new (donwload with success)
+ scp "crm.bim-it.pl:/var/opt/mssql/data/$mdfName" ./Temp/
+ if (((Get-Date) - ((Get-Item ./Temp/$mdfName).LastWriteTime)).TotalMinutes -gt 5) {
+ Write-Host "Error: $mdfName was not downloaded correctly."
+ continue;
+ }
+ scp "crm.bim-it.pl:/var/opt/mssql/data/$ldfName" ./Temp/
+ if (((Get-Date) - ((Get-Item ./Temp/$ldfName).LastWriteTime)).TotalMinutes -gt 5) {
+ Write-Host "Error: $ldfName was not downloaded correctly."
+ continue;
+ }
+
+ #drop existing database
+ DropDatabase $containerId $database $sqlPass;
+ if ((IsDatabaseExists $containerId $database $sqlPass) -eq 'yes') {
+ Write-Host "Error: $database still exists (drop error)"
+ continue;
+ }
+ #copy new files
+ CopyFile $containerId $mdfName
+ CopyFile $containerId $ldfName
+ #attach databases in container
+ AttachDatabase $containerId $database $sqlPass $mdfName $ldfName;
+ if ((IsDatabaseExists $containerId $database $sqlPass) -eq 'no') {
+ Write-Host "Error: $database still not exists (attach error)"
+ continue;
+ }
+ Write-Host "OK";
+});
Write-Host "All databases restored!";
\ No newline at end of file
diff --git a/WebAPI/AppDbContext.cs b/WebAPI/AppDbContext.cs
index 6e563d1..72d32df 100644
--- a/WebAPI/AppDbContext.cs
+++ b/WebAPI/AppDbContext.cs
@@ -1,31 +1,31 @@
-using Microsoft.EntityFrameworkCore;
-using System.Collections.Generic;
-using WebAPI.Models;
-
-namespace WebAPI
-{
- public class AppDbContext : DbContext
- {
- public DbSet Users { get; set; }
- public DbSet Layers { get; set; }
- public DbSet Records { get; set; }
-
- public AppDbContext(DbContextOptions options) : base(options)
- {
- }
-
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- }
-
- public static readonly Microsoft.Extensions.Logging.LoggerFactory _myLoggerFactory =
- new LoggerFactory(new[] {
- new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider()
- });
-
- protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
- {
- optionsBuilder.UseLoggerFactory(_myLoggerFactory);
- }
- }
-}
+using Microsoft.EntityFrameworkCore;
+using System.Collections.Generic;
+using WebAPI.Models;
+
+namespace WebAPI
+{
+ public class AppDbContext : DbContext
+ {
+ public DbSet Users { get; set; }
+ public DbSet Layers { get; set; }
+ public DbSet Records { get; set; }
+
+ public AppDbContext(DbContextOptions options) : base(options)
+ {
+ }
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ }
+
+ public static readonly Microsoft.Extensions.Logging.LoggerFactory _myLoggerFactory =
+ new LoggerFactory(new[] {
+ new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider()
+ });
+
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+ {
+ optionsBuilder.UseLoggerFactory(_myLoggerFactory);
+ }
+ }
+}
diff --git a/WebAPI/Controllers/AuthController.cs b/WebAPI/Controllers/AuthController.cs
index 4e2a4e4..287592d 100644
--- a/WebAPI/Controllers/AuthController.cs
+++ b/WebAPI/Controllers/AuthController.cs
@@ -1,72 +1,72 @@
-using Google.Apis.Auth;
-using Google.Apis.Http;
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Identity.Client.Platforms.Features.DesktopOs.Kerberos;
-using Microsoft.IdentityModel.Tokens;
-using System.Configuration;
-using System.IdentityModel.Tokens.Jwt;
-using System.Security.Claims;
-using System.Text;
-using WebAPI.Models;
-
-namespace WebAPI.Controllers
-{
- [ApiController]
- [Route("api/[controller]")]
- // [Authorize]
- public class AuthController : Controller
- {
- private readonly AppDbContext db;
- private readonly IConfiguration configuration;
- public AuthController(
- AppDbContext _db, IConfiguration _configuration)
- { db = _db; configuration = _configuration; }
-
- [HttpPost]
- [Route("apiToken")]
- public async Task apiToken([FromBody] string credential)
- {
- var settings = new GoogleJsonWebSignature.ValidationSettings()
- {
- Audience = new List { configuration.GetValue("GoogleClientId") }
- };
- var payload = await GoogleJsonWebSignature.ValidateAsync(credential, settings);
- var user = db.Users.Where(x => x.Email == payload.Email).FirstOrDefault();
- if (user != null)
- {
- return Ok(JWTGenerator(user));
- }
- else
- {
- return Unauthorized();
- }
- }
-
- private dynamic JWTGenerator(User user)
- {
- var key = Encoding.ASCII.GetBytes(configuration.GetValue("Secret"));
- var expirationTime = DateTime.UtcNow.AddMinutes(5);
- var tokenDescriptor = new SecurityTokenDescriptor
- {
- Subject = new ClaimsIdentity(new[]
- {
- new Claim("Id", Guid.NewGuid().ToString()),
- new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()),
- new Claim(JwtRegisteredClaimNames.Jti,
- Guid.NewGuid().ToString())
- }),
- Expires = expirationTime,
- SigningCredentials = new SigningCredentials
- (new SymmetricSecurityKey(key),
- SecurityAlgorithms.HmacSha512Signature)
- };
- var tokenHandler = new JwtSecurityTokenHandler();
- var token = tokenHandler.CreateToken(tokenDescriptor);
- var jwtToken = tokenHandler.WriteToken(token);
- var stringToken = tokenHandler.WriteToken(token);
- return new { token = stringToken, id = user.Id, expirationTime };
- }
- }
+using Google.Apis.Auth;
+using Google.Apis.Http;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Identity.Client.Platforms.Features.DesktopOs.Kerberos;
+using Microsoft.IdentityModel.Tokens;
+using System.Configuration;
+using System.IdentityModel.Tokens.Jwt;
+using System.Security.Claims;
+using System.Text;
+using WebAPI.Models;
+
+namespace WebAPI.Controllers
+{
+ [ApiController]
+ [Route("api/[controller]")]
+ // [Authorize]
+ public class AuthController : Controller
+ {
+ private readonly AppDbContext db;
+ private readonly IConfiguration configuration;
+ public AuthController(
+ AppDbContext _db, IConfiguration _configuration)
+ { db = _db; configuration = _configuration; }
+
+ [HttpPost]
+ [Route("apiToken")]
+ public async Task apiToken([FromBody] string credential)
+ {
+ var settings = new GoogleJsonWebSignature.ValidationSettings()
+ {
+ Audience = new List { configuration.GetValue("GoogleClientId") }
+ };
+ var payload = await GoogleJsonWebSignature.ValidateAsync(credential, settings);
+ var user = db.Users.Where(x => x.Email == payload.Email).FirstOrDefault();
+ if (user != null)
+ {
+ return Ok(JWTGenerator(user));
+ }
+ else
+ {
+ return Unauthorized();
+ }
+ }
+
+ private dynamic JWTGenerator(User user)
+ {
+ var key = Encoding.ASCII.GetBytes(configuration.GetValue("Secret"));
+ var expirationTime = DateTime.UtcNow.AddMinutes(5);
+ var tokenDescriptor = new SecurityTokenDescriptor
+ {
+ Subject = new ClaimsIdentity(new[]
+ {
+ new Claim("Id", Guid.NewGuid().ToString()),
+ new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()),
+ new Claim(JwtRegisteredClaimNames.Jti,
+ Guid.NewGuid().ToString())
+ }),
+ Expires = expirationTime,
+ SigningCredentials = new SigningCredentials
+ (new SymmetricSecurityKey(key),
+ SecurityAlgorithms.HmacSha512Signature)
+ };
+ var tokenHandler = new JwtSecurityTokenHandler();
+ var token = tokenHandler.CreateToken(tokenDescriptor);
+ var jwtToken = tokenHandler.WriteToken(token);
+ var stringToken = tokenHandler.WriteToken(token);
+ return new { token = stringToken, id = user.Id, expirationTime };
+ }
+ }
}
\ No newline at end of file
diff --git a/WebAPI/Controllers/LayersController.cs b/WebAPI/Controllers/LayersController.cs
index e058a98..b8dbd92 100644
--- a/WebAPI/Controllers/LayersController.cs
+++ b/WebAPI/Controllers/LayersController.cs
@@ -1,182 +1,182 @@
-using Google.Apis.Auth;
-using Google.Apis.Http;
-using Google.Apis.Sheets.v4;
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Identity.Client.Platforms.Features.DesktopOs.Kerberos;
-using Microsoft.IdentityModel.Tokens;
-using System;
-using System.Configuration;
-using System.IdentityModel.Tokens.Jwt;
-using System.Security.Claims;
-using System.Text;
-using WebAPI.dataParsers;
-using WebAPI.Exports;
-using WebAPI.Models;
-
-namespace WebAPI.Controllers
-{
- [ApiController]
- [Route("api/[controller]")]
- [Authorize]
- public class LayersController : Controller
- {
- private readonly AppDbContext db;
- private SpreadsheetsResource.ValuesResource googleSheetValues;
- private GoogleDriveHelper googleDriveHelper;
- private readonly IConfiguration configuration;
- public LayersController(
- AppDbContext _db,
- GoogleSheetsHelper _googleSheetsHelper,
- GoogleDriveHelper _googleDriveHelper,
- IConfiguration _configuration)
- {
- db = _db;
- googleSheetValues = _googleSheetsHelper.Service.Spreadsheets.Values;
- googleDriveHelper = _googleDriveHelper;
- configuration = _configuration;
- }
-
- [HttpGet]
- public IActionResult GetAll()
- {
- try
- {
- return Ok(db.Layers.Where(x => !x.IsDeleted).ToList());
- }
- catch (Exception e)
- {
- return BadRequest(e.ToString());
- }
- }
- [HttpPost]
- public IActionResult Save(Layer input)
- {
- try
- {
- Request.Headers.TryGetValue("userId", out var value);
- Guid currentUserId = new Guid(value!);
- return Ok(AddLayer(input, currentUserId).Id);
- } catch (Exception e)
- {
- return BadRequest(e.ToString());
- }
- }
- [HttpGet]
- [Route("{id}")]
- public IActionResult Get(Guid id)
- {
- try
- {
- return Ok(db.Layers
- .Include(x => x.CreatedBy)
- .Include(x => x.Records)
- .Where(x => x.Id == id && !x.IsDeleted).First());
- }
- catch (Exception e)
- {
- return BadRequest(e.ToString());
- }
- }
- [HttpGet]
- [Route("parseGoogleSheet/{sheetId}")]
- public IActionResult ParseGoogleSheet(string sheetId)
- {
-
- string sheetName = "KOSZTY";
-
- Layer layer = new Layer();
- layer.Source = "GoogleSheet";
- layer.Number = db.Layers.Count() + 1;
- var parser = new googleSheetParser(googleSheetValues);
- dynamic parsedSheet = parser.parse(sheetId);
- layer.Records = parsedSheet.records;
- layer.Name = $"W{layer.Number}-I-{sheetName}-{parsedSheet.date}-{DateTime.Now.ToString("yyyyMMddHHmm")}";
-
- return Ok(layer);
- }
- [HttpPost]
- [DisableRequestSizeLimit]
- [Route("parseFile")]
- public IActionResult ParseFile()
- {
- var parser = new csvParser();
- return Ok(parser.parse(Request.Form.Files[0]));
- }
- [HttpGet]
- [Route("exportToGoogleSheet/{id}")]
- public IActionResult ExportToGoogleSheet(Guid id)
- {
- Layer layer = db.Layers
- .Include(x => x.Records)
- .Where(x => x.Id == id && !x.IsDeleted).First();
-
- var export = new googleSheetExport(googleDriveHelper, googleSheetValues);
- export.export(layer);
- return Ok(true);
- }
-
- [HttpGet]
- [Route("autoImport/{apiKey}")]
- [AllowAnonymous]
- public IActionResult autoImport(string apiKey)
- {
- if (Request.Host.Value != "localhost:5400" || apiKey != configuration["apiKey"])
- {
- return Unauthorized();
- }
- string sheetId = "1G_Hu8DTP-PSPNXTaVYhc_ppnTQi6HWoA4oXSSdUmM9E";
- string sheetName = "KOSZTY";
-
- Layer layer = new Layer();
- layer.Source = "GoogleSheet";
- layer.Number = db.Layers.Count() + 1;
- var parser = new googleSheetParser(googleSheetValues);
- dynamic parsedSheet = parser.parse(sheetId);
- layer.Records = parsedSheet.records;
- layer.Name = $"W{layer.Number}-I-{sheetName}-{parsedSheet.date}-{DateTime.Now.ToString("yyyyMMddHHmm")}";
- AddLayer(layer, Guid.Parse("F392209E-123E-4651-A5A4-0B1D6CF9FF9D"));
-
- return Ok("OK");
- }
-
- //
- private Layer AddLayer(Layer input, Guid currentUserId)
- {
- input.Number = db.Layers.Count() + 1;
- input.CreatedById = currentUserId;
- input.ModifiedById = currentUserId;
- input.CreatedAt = DateTime.UtcNow;
- input.ModifiedAt = DateTime.UtcNow;
-
- db.Layers.Add(input);
- SaveRecords(input.Id, input.Records!, currentUserId);
- db.SaveChanges();
- return input;
- }
-
- private void SaveRecords(Guid id, ICollection records, Guid currentUserId)
- {
- try
- {
- List ids = new List();
- foreach (Record record in records)
- {
- record.CreatedById = currentUserId;
- record.CreatedAt = DateTime.UtcNow;
- record.ModifiedById = currentUserId;
- record.ModifiedAt = DateTime.UtcNow;
- record.LayerId= id;
-
- db.Records.Add(record);
- }
- }
- catch (Exception)
- {
- throw;
- }
- }
- }
+using Google.Apis.Auth;
+using Google.Apis.Http;
+using Google.Apis.Sheets.v4;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Identity.Client.Platforms.Features.DesktopOs.Kerberos;
+using Microsoft.IdentityModel.Tokens;
+using System;
+using System.Configuration;
+using System.IdentityModel.Tokens.Jwt;
+using System.Security.Claims;
+using System.Text;
+using WebAPI.dataParsers;
+using WebAPI.Exports;
+using WebAPI.Models;
+
+namespace WebAPI.Controllers
+{
+ [ApiController]
+ [Route("api/[controller]")]
+ [Authorize]
+ public class LayersController : Controller
+ {
+ private readonly AppDbContext db;
+ private SpreadsheetsResource.ValuesResource googleSheetValues;
+ private GoogleDriveHelper googleDriveHelper;
+ private readonly IConfiguration configuration;
+ public LayersController(
+ AppDbContext _db,
+ GoogleSheetsHelper _googleSheetsHelper,
+ GoogleDriveHelper _googleDriveHelper,
+ IConfiguration _configuration)
+ {
+ db = _db;
+ googleSheetValues = _googleSheetsHelper.Service.Spreadsheets.Values;
+ googleDriveHelper = _googleDriveHelper;
+ configuration = _configuration;
+ }
+
+ [HttpGet]
+ public IActionResult GetAll()
+ {
+ try
+ {
+ return Ok(db.Layers.Where(x => !x.IsDeleted).ToList());
+ }
+ catch (Exception e)
+ {
+ return BadRequest(e.ToString());
+ }
+ }
+ [HttpPost]
+ public IActionResult Save(Layer input)
+ {
+ try
+ {
+ Request.Headers.TryGetValue("userId", out var value);
+ Guid currentUserId = new Guid(value!);
+ return Ok(AddLayer(input, currentUserId).Id);
+ } catch (Exception e)
+ {
+ return BadRequest(e.ToString());
+ }
+ }
+ [HttpGet]
+ [Route("{id}")]
+ public IActionResult Get(Guid id)
+ {
+ try
+ {
+ return Ok(db.Layers
+ .Include(x => x.CreatedBy)
+ .Include(x => x.Records)
+ .Where(x => x.Id == id && !x.IsDeleted).First());
+ }
+ catch (Exception e)
+ {
+ return BadRequest(e.ToString());
+ }
+ }
+ [HttpGet]
+ [Route("parseGoogleSheet/{sheetId}")]
+ public IActionResult ParseGoogleSheet(string sheetId)
+ {
+
+ string sheetName = "KOSZTY";
+
+ Layer layer = new Layer();
+ layer.Source = "GoogleSheet";
+ layer.Number = db.Layers.Count() + 1;
+ var parser = new googleSheetParser(googleSheetValues);
+ dynamic parsedSheet = parser.parse(sheetId);
+ layer.Records = parsedSheet.records;
+ layer.Name = $"W{layer.Number}-I-{sheetName}-{parsedSheet.date}-{DateTime.Now.ToString("yyyyMMddHHmm")}";
+
+ return Ok(layer);
+ }
+ [HttpPost]
+ [DisableRequestSizeLimit]
+ [Route("parseFile")]
+ public IActionResult ParseFile()
+ {
+ var parser = new csvParser();
+ return Ok(parser.parse(Request.Form.Files[0]));
+ }
+ [HttpGet]
+ [Route("exportToGoogleSheet/{id}")]
+ public IActionResult ExportToGoogleSheet(Guid id)
+ {
+ Layer layer = db.Layers
+ .Include(x => x.Records)
+ .Where(x => x.Id == id && !x.IsDeleted).First();
+
+ var export = new googleSheetExport(googleDriveHelper, googleSheetValues);
+ export.export(layer);
+ return Ok(true);
+ }
+
+ [HttpGet]
+ [Route("autoImport/{apiKey}")]
+ [AllowAnonymous]
+ public IActionResult autoImport(string apiKey)
+ {
+ if (Request.Host.Value != "localhost:5400" || apiKey != configuration["apiKey"])
+ {
+ return Unauthorized();
+ }
+ string sheetId = "1G_Hu8DTP-PSPNXTaVYhc_ppnTQi6HWoA4oXSSdUmM9E";
+ string sheetName = "KOSZTY";
+
+ Layer layer = new Layer();
+ layer.Source = "GoogleSheet";
+ layer.Number = db.Layers.Count() + 1;
+ var parser = new googleSheetParser(googleSheetValues);
+ dynamic parsedSheet = parser.parse(sheetId);
+ layer.Records = parsedSheet.records;
+ layer.Name = $"W{layer.Number}-I-{sheetName}-{parsedSheet.date}-{DateTime.Now.ToString("yyyyMMddHHmm")}";
+ AddLayer(layer, Guid.Parse("F392209E-123E-4651-A5A4-0B1D6CF9FF9D"));
+
+ return Ok("OK");
+ }
+
+ //
+ private Layer AddLayer(Layer input, Guid currentUserId)
+ {
+ input.Number = db.Layers.Count() + 1;
+ input.CreatedById = currentUserId;
+ input.ModifiedById = currentUserId;
+ input.CreatedAt = DateTime.UtcNow;
+ input.ModifiedAt = DateTime.UtcNow;
+
+ db.Layers.Add(input);
+ SaveRecords(input.Id, input.Records!, currentUserId);
+ db.SaveChanges();
+ return input;
+ }
+
+ private void SaveRecords(Guid id, ICollection records, Guid currentUserId)
+ {
+ try
+ {
+ List ids = new List();
+ foreach (Record record in records)
+ {
+ record.CreatedById = currentUserId;
+ record.CreatedAt = DateTime.UtcNow;
+ record.ModifiedById = currentUserId;
+ record.ModifiedAt = DateTime.UtcNow;
+ record.LayerId= id;
+
+ db.Records.Add(record);
+ }
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/WebAPI/Controllers/PingController.cs b/WebAPI/Controllers/PingController.cs
index 9c06d5c..a63204b 100644
--- a/WebAPI/Controllers/PingController.cs
+++ b/WebAPI/Controllers/PingController.cs
@@ -1,36 +1,36 @@
-using Google.Apis.Auth;
-using Google.Apis.Http;
-using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Identity.Client.Platforms.Features.DesktopOs.Kerberos;
-using Microsoft.IdentityModel.Tokens;
-using System.Configuration;
-using System.IdentityModel.Tokens.Jwt;
-using System.Security.Claims;
-using System.Text;
-using WebAPI.Models;
-
-namespace WebAPI.Controllers
-{
- [ApiController]
- [Route("api/[controller]")]
- [Authorize]
- public class PingController : Controller
- {
- private readonly IConfiguration configuration;
- public PingController(
- IConfiguration _configuration)
- {
- configuration = _configuration;
- }
-
- [HttpGet]
- [Route("Ping")]
- [AllowAnonymous]
- public IActionResult Ping()
- {
- return Ok(configuration["PONG"]);
- }
- }
+using Google.Apis.Auth;
+using Google.Apis.Http;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Identity.Client.Platforms.Features.DesktopOs.Kerberos;
+using Microsoft.IdentityModel.Tokens;
+using System.Configuration;
+using System.IdentityModel.Tokens.Jwt;
+using System.Security.Claims;
+using System.Text;
+using WebAPI.Models;
+
+namespace WebAPI.Controllers
+{
+ [ApiController]
+ [Route("api/[controller]")]
+ [Authorize]
+ public class PingController : Controller
+ {
+ private readonly IConfiguration configuration;
+ public PingController(
+ IConfiguration _configuration)
+ {
+ configuration = _configuration;
+ }
+
+ [HttpGet]
+ [Route("Ping")]
+ [AllowAnonymous]
+ public IActionResult Ping()
+ {
+ return Ok(configuration["PONG"]);
+ }
+ }
}
\ No newline at end of file
diff --git a/WebAPI/DiunaBI-WebAPI.csproj b/WebAPI/DiunaBI-WebAPI.csproj
index baefb4e..f49ab1f 100644
--- a/WebAPI/DiunaBI-WebAPI.csproj
+++ b/WebAPI/DiunaBI-WebAPI.csproj
@@ -1,33 +1,33 @@
-
-
-
- net7.0
- enable
- enable
-
-
-
-
-
-
-
-
-
-
-
- runtime; build; native; contentfiles; analyzers; buildtransitive
- all
-
-
-
-
-
-
-
- PreserveNewest
- true
- PreserveNewest
-
-
-
-
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+ PreserveNewest
+ true
+ PreserveNewest
+
+
+
+
diff --git a/WebAPI/Exports/googleSheet.export.cs b/WebAPI/Exports/googleSheet.export.cs
index ba40244..d1ef584 100644
--- a/WebAPI/Exports/googleSheet.export.cs
+++ b/WebAPI/Exports/googleSheet.export.cs
@@ -1,50 +1,50 @@
-using Google.Apis.Drive.v3.Data;
-using Google.Apis.Sheets.v4;
-using Google.Apis.Sheets.v4.Data;
-using WebAPI.Models;
-using static Google.Apis.Drive.v3.FilesResource;
-
-namespace WebAPI.Exports
-{
- public class googleSheetExport
- {
- private GoogleDriveHelper googleDriveHelper;
- private SpreadsheetsResource.ValuesResource googleSheetValues;
- public googleSheetExport(GoogleDriveHelper _googleDriveHelper, SpreadsheetsResource.ValuesResource _googleSheetValues)
- {
- googleDriveHelper = _googleDriveHelper;
- googleSheetValues = _googleSheetValues;
- }
- public void export(Layer layer)
- {
- try
- {
- List> data = new List>() { new List