Merge commit 'refs/tags/0.2.0.1111^{}'

This commit is contained in:
Chris.Watts90@outlook.com 2018-06-06 12:13:00 +01:00
commit dad901ef31
48 changed files with 1645 additions and 307 deletions

2
.gitignore vendored
View File

@ -6,3 +6,5 @@
**/node_modules/*
**csproj.DotSettings
**.csproj.user
*spa.min.*
**spa.min.*

View File

@ -32,6 +32,26 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugInstallers|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\DebugInstallers\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseInstallers|AnyCPU'">
<OutputPath>bin\ReleaseInstallers\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>

View File

@ -1,5 +1,4 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using CardReaderService.DefaultComponents;

View File

@ -32,6 +32,26 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugInstallers|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\DebugInstallers\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseInstallers|AnyCPU'">
<OutputPath>bin\ReleaseInstallers\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\CardReaderService\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>

View File

@ -25,6 +25,7 @@
<ComponentGroup Id="CardReaderServiceComponents" Directory="INSTALLFOLDER">
<ComponentRef Id="CardReaderServiceStarter" />
<ComponentRef Id="CardReaderEventLog" />
<ComponentRef Id="ServiceConfiguration"/>
<!-- Start the Smart Card Service which is a dependency of the PCSC library. -->
<Component Id="SmartCardServiceConfig" Guid="{73D2E31D-F256-457C-AFD5-EC456CDAD7E8}" KeyPath="yes">
<ServiceControl Id="SmartCardServiceStarter"
@ -99,5 +100,15 @@
Source="$(var.CardReaderService.TargetDir)pcsc-sharp.dll" />
</Component>
</ComponentGroup>
<Component Id="ServiceConfiguration" Directory="INSTALLFOLDER" Guid="{E49ABD61-0CCA-45A2-A525-DF85A0493FF7}" KeyPath="yes">
<util:XmlFile Id="SetDataCenterEndpoint"
Action="setValue"
ElementPath="//appSettings/add[\[]@key='DataCenterServiceEndpoint'[\]]/@value"
Value="http://[SERVICEIP]:[SERVICEPORT]"
File="[#CardReaderService.exe.config]"
SelectionLanguage="XPath"
Sequence="1" />
</Component>
</Fragment>
</Wix>

View File

@ -2,5 +2,7 @@
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<Property Id="STARTSERVICEONINSTALL" Value="false" />
<Property Id="SERVICEIP" Value="127.0.0.1" />
<Property Id="SERVICEPORT" Value="8800"/>
</Fragment>
</Wix>

View File

@ -29,6 +29,24 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugInstallers|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\DebugInstallers\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseInstallers|AnyCPU'">
<OutputPath>bin\ReleaseInstallers\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Configuration" />

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
<Bundle Name="FlexiTimeSystemInstaller"
Version="1.0.0.0"
Manufacturer="Chris Watts"
UpgradeCode="d38e92db-48f9-40c3-9a6f-d76fbd07326e">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
<bal:WixStandardBootstrapperApplication
LicenseFile="License.rtf"
ThemeFile="Theme.xml" />
</BootstrapperApplicationRef>
<Variable Name="InstallCardService" Value="1" Type="numeric"/>
<Variable Name="InstallDataCenter" Value="1" Type="numeric"/>
<Variable Name="DataServiceIpAddress" Value="127.0.0.1" Type="string"/>
<Variable Name="DataServicePort" Value="8800" Type="string"/>
<Variable Name="INSTALLFOLDER"
bal:Overridable="yes"
Type="string"
Value="[ProgramFilesFolder]Flexitime Data Center"/>
<Variable Name="InstallSQLiteDatabase" Value="1" Type="numeric"/>
<Chain>
<MsiPackage SourceFile="$(var.CardReaderServiceInstaller.TargetDir)CardReaderServiceInstaller.msi"
Compressed="yes"
Visible="no"
DisplayName="Card Reader Service"
InstallCondition="InstallCardService = 1">
<MsiProperty Name="SERVICEPORT" Value="[DataServicePort]"/>
<MsiProperty Name="SERVICEIP" Value="[DataServiceIpAddress]"/>
</MsiPackage>
<MsiPackage SourceFile="$(var.DataCenterHostInstaller.TargetDir)WebApiServerHostInstaller.msi"
Compressed="yes"
Visible="no"
DisplayName="Flexitime Data Center"
InstallCondition="InstallDataCenter = 1">
<MsiProperty Name="ServicePort" Value="[DataServicePort]"/>
<MsiProperty Name="INSTALLFOLDER"
Value="[INSTALLFOLDER]" />
</MsiPackage>
<MsiPackage SourceFile="$(var.SQLiteRepositoryInstaller.TargetDir)SQLiteRepository.msi"
Compressed="yes"
Visible="no"
DisplayName="Flexitime SQLite Database Provider"
InstallCondition="InstallSQLiteDatabase = 1">
<MsiProperty Name="INSTALLFOLDER"
Value="[INSTALLFOLDER]" />
</MsiPackage>
</Chain>
</Bundle>
</Wix>

View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>3.10</ProductVersion>
<ProjectGuid>d38e92db-48f9-40c3-9a6f-d76fbd07326e</ProjectGuid>
<SchemaVersion>2.0</SchemaVersion>
<OutputName>FlexiTimeSystemInstaller</OutputName>
<OutputType>Bundle</OutputType>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>Debug</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="Bundle.wxs" />
</ItemGroup>
<ItemGroup>
<WixExtension Include="WixBalExtension">
<HintPath>$(WixExtDir)\WixBalExtension.dll</HintPath>
<Name>WixBalExtension</Name>
</WixExtension>
</ItemGroup>
<ItemGroup>
<Content Include="License.rtf" />
<Content Include="Theme.xml" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="ThemeLocalisation.wxl" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CardReaderServiceInstaller\CardReaderServiceInstaller.wixproj">
<Name>CardReaderServiceInstaller</Name>
<Project>{119216de-fc7f-408a-9c2c-105874449e42}</Project>
<Private>True</Private>
<DoNotHarvest>True</DoNotHarvest>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
</ProjectReference>
<ProjectReference Include="..\SQLiteProvider\SQLiteRepositoryInstaller.wixproj">
<Name>SQLiteRepositoryInstaller</Name>
<Project>{41caf3c0-ddf9-4a65-a715-da07c4178cbf}</Project>
<Private>True</Private>
<DoNotHarvest>True</DoNotHarvest>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
</ProjectReference>
<ProjectReference Include="..\WebApiServerHostInstaller\DataCenterHostInstaller.wixproj">
<Name>DataCenterHostInstaller</Name>
<Project>{c5a4cdc3-849c-4166-bdc3-56bdb307126d}</Project>
<Private>True</Private>
<DoNotHarvest>True</DoNotHarvest>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
</ProjectReference>
</ItemGroup>
<Import Project="$(WixTargetsPath)" />
<!--
To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Wix.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,85 @@
<Theme xmlns="http://wixtoolset.org/schemas/thmutil/2010">
<Window Width="485" Height="300" HexStyle="100a0000" FontId="0">#(loc.Caption)</Window>
<Font Id="0" Height="-12" Weight="500" Foreground="000000" Background="FFFFFF">Segoe UI</Font>
<Font Id="1" Height="-24" Weight="500" Foreground="000000">Segoe UI</Font>
<Font Id="2" Height="-22" Weight="500" Foreground="666666">Segoe UI</Font>
<Font Id="3" Height="-12" Weight="500" Foreground="000000" Background="FFFFFF">Segoe UI</Font>
<Font Id="4" Height="-12" Weight="500" Foreground="ff0000" Background="FFFFFF" Underline="yes">Segoe UI</Font>
<Image X="11" Y="11" Width="64" Height="64" ImageFile="logo.png" Visible="yes"/>
<Text X="80" Y="11" Width="-11" Height="64" FontId="1" Visible="yes" DisablePrefix="yes">#(loc.Title)</Text>
<Page Name="Help">
<Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.HelpHeader)</Text>
<Text X="11" Y="112" Width="-11" Height="-35" FontId="3" DisablePrefix="yes">#(loc.HelpText)</Text>
<Button Name="HelpCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.HelpCloseButton)</Button>
</Page>
<Page Name="Install">
<Text Name="InstCardSvcLbl" X="20" Y="80" Width="200" Height="17" TabStop="no" FontId="3">Install Card Service</Text>
<Checkbox Name="InstallCardService" X="230" Y="80" Width="200" Height="17" TabStop="yes" FontId="3"></Checkbox>
<Text Name="InstDataCntrSvcLbl" X="20" Y="110" Width="200" Height="17" TabStop="no" FontId="3">Install Data Centre</Text>
<Checkbox Name="InstallDataCenter" X="230" Y="110" Width="200" Height="17" TabStop="yes" FontId="3"></Checkbox>
<Text Name="DataCenterIPLbl" X="20" Y="140" Width="200" Height="17" TabStop="no" FontId="3">Data Centre IP Address</Text>
<Editbox Name="DataServiceIpAddress" X="230" Y="140" Width="100" Height="17" TabStop="yes" FontId="3"></Editbox>
<Text Name="PortLabel" X="20" Y="170" Width="200" Height="17" TabStop="no" FontId="3">Data Centre Website Port</Text>
<Editbox Name="DataServicePort" X="230" Y="170" Width="100" Height="17" TabStop="yes" FontId="3"></Editbox>
<Text Name="DatabaseLabel" X="20" Y="200" Width="100" Height="17" TabStop="no" FontId="3">Database Type</Text>
<Button Name="InstallSQLiteDatabase" X="230" Y="200" Width="100" Height="23" TabStop="yes" FontId="0" HexStyle="000009">SQLite</Button>
<Button Name="OptionsButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.InstallOptionsButton)</Button>
<Button Name="InstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallInstallButton)</Button>
<Button Name="WelcomeCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.InstallCloseButton)</Button>
</Page>
<Page Name="Options">
<Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.OptionsHeader)</Text>
<Text X="11" Y="121" Width="-11" Height="17" FontId="3" DisablePrefix="yes">#(loc.OptionsLocationLabel)</Text>
<Editbox Name="FolderEditbox" X="11" Y="143" Width="-91" Height="21" TabStop="yes" FontId="3" FileSystemAutoComplete="yes" />
<Button Name="BrowseButton" X="-11" Y="142" Width="75" Height="23" TabStop="yes" FontId="3">#(loc.OptionsBrowseButton)</Button>
<Button Name="OptionsOkButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.OptionsOkButton)</Button>
<Button Name="OptionsCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.OptionsCancelButton)</Button>
</Page>
<Page Name="FilesInUse">
<Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.FilesInUseHeader)</Text>
<Text X="11" Y="121" Width="-11" Height="34" FontId="3" DisablePrefix="yes">#(loc.FilesInUseLabel)</Text>
<Text Name="FilesInUseText" X="11" Y="150" Width="-11" Height="-86" FontId="3" DisablePrefix="yes" HexStyle="0x0000C000"></Text>
<Button Name="FilesInUseCloseRadioButton" X="11" Y="-60" Width="-11" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes" HexStyle="0x000009">#(loc.FilesInUseCloseRadioButton)</Button>
<Button Name="FilesInUseDontCloseRadioButton" X="11" Y="-40" Width="-11" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes" HexStyle="0x000009">#(loc.FilesInUseDontCloseRadioButton)</Button>
<Button Name="FilesInUseOkButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.FilesInUseOkButton)</Button>
<Button Name="FilesInUseCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.FilesInUseCancelButton)</Button>
</Page>
<Page Name="Progress">
<Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ProgressHeader)</Text>
<Text X="11" Y="121" Width="70" Height="17" FontId="3" DisablePrefix="yes">#(loc.ProgressLabel)</Text>
<Text Name="OverallProgressPackageText" X="85" Y="121" Width="-11" Height="17" FontId="3" DisablePrefix="yes">#(loc.OverallProgressPackageText)</Text>
<Progressbar Name="OverallCalculatedProgressbar" X="11" Y="143" Width="-11" Height="15" />
<Button Name="ProgressCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ProgressCancelButton)</Button>
</Page>
<Page Name="Modify">
<Text X="11" Y="80" Width="-11" Height="30" FontId="2" DisablePrefix="yes">#(loc.ModifyHeader)</Text>
<Button Name="RepairButton" X="-171" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.ModifyRepairButton)</Button>
<Button Name="UninstallButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ModifyUninstallButton)</Button>
<Button Name="ModifyCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.ModifyCloseButton)</Button>
</Page>
<Page Name="Success">
<Text Name="SuccessHeader" X="11" Y="80" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessHeader)</Text>
<Text Name="SuccessInstallHeader" X="11" Y="80" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessInstallHeader)</Text>
<Text Name="SuccessRepairHeader" X="11" Y="80" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessRepairHeader)</Text>
<Text Name="SuccessUninstallHeader" X="11" Y="80" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessUninstallHeader)</Text>
<Button Name="LaunchButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessLaunchButton)</Button>
<Text Name="SuccessRestartText" X="-11" Y="-51" Width="400" Height="34" FontId="3" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.SuccessRestartText)</Text>
<Button Name="SuccessRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.SuccessRestartButton)</Button>
<Button Name="SuccessCancelButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.SuccessCloseButton)</Button>
</Page>
<Page Name="Failure">
<Text Name="FailureHeader" X="11" Y="80" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureHeader)</Text>
<Text Name="FailureInstallHeader" X="11" Y="80" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureInstallHeader)</Text>
<Text Name="FailureUninstallHeader" X="11" Y="80" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureUninstallHeader)</Text>
<Text Name="FailureRepairHeader" X="11" Y="80" Width="-11" Height="30" FontId="2" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureRepairHeader)</Text>
<Hypertext Name="FailureLogFileLink" X="11" Y="121" Width="-11" Height="42" FontId="3" TabStop="yes" HideWhenDisabled="yes">#(loc.FailureHyperlinkLogText)</Hypertext>
<Hypertext Name="FailureMessageText" X="22" Y="163" Width="-11" Height="51" FontId="3" TabStop="yes" HideWhenDisabled="yes" />
<Text Name="FailureRestartText" X="-11" Y="-51" Width="400" Height="34" FontId="3" HideWhenDisabled="yes" DisablePrefix="yes">#(loc.FailureRestartText)</Text>
<Button Name="FailureRestartButton" X="-91" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0" HideWhenDisabled="yes">#(loc.FailureRestartButton)</Button>
<Button Name="FailureCloseButton" X="-11" Y="-11" Width="75" Height="23" TabStop="yes" FontId="0">#(loc.FailureCloseButton)</Button>
</Page>
</Theme>

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
<WixLocalization Culture="en-us" Language="1033" xmlns="http://schemas.microsoft.com/wix/2006/localization">
<String Id="Caption">[WixBundleName] Setup</String>
<String Id="Title">[WixBundleName]</String>
<String Id="InstallVersion">Version [WixBundleVersion]</String>
<String Id="ConfirmCancelMessage">Are you sure you want to cancel?</String>
<String Id="ExecuteUpgradeRelatedBundleMessage">Previous version</String>
<String Id="HelpHeader">Setup Help</String>
<String Id="HelpText">
/install | /repair | /uninstall | /layout [directory] - installs, repairs, uninstalls or
creates a complete local copy of the bundle in directory. Install is the default.
/passive | /quiet - displays minimal UI with no prompts or displays no UI and
no prompts. By default UI and all prompts are displayed.
/norestart - suppress any attempts to restart. By default UI will prompt before restart.
/log log.txt - logs to a specific file. By default a log file is created in %TEMP%.
</String>
<String Id="HelpCloseButton">&amp;Close</String>
<String Id="InstallAcceptCheckbox">I &amp;agree to the license terms and conditions</String>
<String Id="InstallOptionsButton">&amp;Options</String>
<String Id="InstallInstallButton">&amp;Install</String>
<String Id="InstallCloseButton">&amp;Close</String>
<String Id="OptionsHeader">Setup Options</String>
<String Id="OptionsLocationLabel">Install location:</String>
<String Id="OptionsBrowseButton">&amp;Browse</String>
<String Id="OptionsOkButton">&amp;OK</String>
<String Id="OptionsCancelButton">&amp;Cancel</String>
<String Id="ProgressHeader">Setup Progress</String>
<String Id="ProgressLabel">Processing:</String>
<String Id="OverallProgressPackageText">Initializing...</String>
<String Id="ProgressCancelButton">&amp;Cancel</String>
<String Id="ModifyHeader">Modify Setup</String>
<String Id="ModifyRepairButton">&amp;Repair</String>
<String Id="ModifyUninstallButton">&amp;Uninstall</String>
<String Id="ModifyCloseButton">&amp;Close</String>
<String Id="SuccessRepairHeader">Repair Successfully Completed</String>
<String Id="SuccessUninstallHeader">Uninstall Successfully Completed</String>
<String Id="SuccessInstallHeader">Installation Successfully Completed</String>
<String Id="SuccessHeader">Setup Successful</String>
<String Id="SuccessLaunchButton">&amp;Launch</String>
<String Id="SuccessRestartText">You must restart your computer before you can use the software.</String>
<String Id="SuccessRestartButton">&amp;Restart</String>
<String Id="SuccessCloseButton">&amp;Close</String>
<String Id="FailureHeader">Setup Failed</String>
<String Id="FailureInstallHeader">Setup Failed</String>
<String Id="FailureUninstallHeader">Uninstall Failed</String>
<String Id="FailureRepairHeader">Repair Failed</String>
<String Id="FailureHyperlinkLogText">One or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the &lt;a href="#"&gt;log file&lt;/a&gt;.</String>
<String Id="FailureRestartText">You must restart your computer to complete the rollback of the software.</String>
<String Id="FailureRestartButton">&amp;Restart</String>
<String Id="FailureCloseButton">&amp;Close</String>
<String Id="FilesInUseHeader">Files In Use</String>
<String Id="FilesInUseLabel">The following applications are using files that need to be updated:</String>
<String Id="FilesInUseCloseRadioButton">Close the &amp;applications and attempt to restart them.</String>
<String Id="FilesInUseDontCloseRadioButton">&amp;Do not close applications. A reboot will be required.</String>
<String Id="FilesInUseOkButton">&amp;OK</String>
<String Id="FilesInUseCancelButton">&amp;Cancel</String>
<String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
</WixLocalization>

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Interfaces
{
public class LogEventResponse
{
public LogDirection Direction { get; set; }
public OperationResponse ProcessResponse { get; set; }
}
}

View File

@ -95,12 +95,16 @@ namespace Interfaces
/// <returns>
/// <see cref="OperationResponse"/> to indicate procedure status.
/// </returns>
OperationResponse LogEventTime(Identifier identifier, out int logId);
LogEventResponse LogEventTime(Identifier identifier, out int logId);
OperationResponse CreateGroup(Group group, out int groupId);
List<Group> GetGroups(int userId = -1);
Group GetGroup(int groupId);
OperationResponse UpdateGroup(Group group);
OperationResponse DeleteGroup(int groupId);
OperationResponse DeleteLog(TimeLog log);
OperationResponse CreateLog(TimeLog log);
OperationResponse UpdateLog(TimeLog log);
}
}

View File

@ -29,6 +29,24 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugInstallers|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\DebugInstallers\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseInstallers|AnyCPU'">
<OutputPath>bin\ReleaseInstallers\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
@ -42,6 +60,7 @@
<ItemGroup>
<Compile Include="AppDetails.cs" />
<Compile Include="DailyLogs.cs" />
<Compile Include="EventLogResponse.cs" />
<Compile Include="Group.cs" />
<Compile Include="GroupList.cs" />
<Compile Include="ILogger.cs" />

View File

@ -11,6 +11,7 @@ namespace Interfaces
public DateTimeOffset EventTime { get; set; }
public int CalendarWeek { get; set; }
public int Year { get; set; }
public LogSource Source { get; set; }
}
public enum LogDirection
@ -19,4 +20,12 @@ namespace Interfaces
IN = 1,
OUT = 2
}
public enum LogSource
{
UNKNOWN=0,
IDENTIFIER=1,
UI=2,
TRAYAPP=3
}
}

View File

@ -29,6 +29,24 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugInstallers|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\DebugInstallers\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseInstallers|AnyCPU'">
<OutputPath>bin\ReleaseInstallers\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.4.2\lib\net45\NLog.dll</HintPath>

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Product Id="{34DA87B7-752D-4A37-928B-650160269E70}"
Name="SQLiteRepositoryInstaller"
Language="1033"
Version="1.0.0.0"
Manufacturer="Chris Watts" UpgradeCode="ec13c45c-6b63-49a6-b058-39e3069a0d6b">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes"/>
<Feature Id="ProductFeature" Title="SQLiteProvider" Level="1">
<ComponentGroupRef Id="SQLiteRepositoryComponents" />
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="SQLiteRepository" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<DirectoryRef Id="INSTALLFOLDER">
<Directory Id="SQLITEX86" Name="x86" />
<Directory Id="SQLITEX64" Name="x64" />
</DirectoryRef>
<ComponentGroup Id="SQLiteRepositoryComponents" >
<ComponentGroupRef Id="SQLiteRepository" />
<ComponentGroupRef Id="SQLiteInterop" />
<ComponentRef Id="RepositoryConfiguration"/>
</ComponentGroup>
<Component Id="RepositoryConfiguration" Directory="INSTALLFOLDER" Guid="{E49ABD61-0CCA-45A2-A525-DF85A0493FF7}" KeyPath="yes">
<util:XmlFile Id="SetServicePort"
Action="setValue"
ElementPath="/module[\[]@name='NinjectAssemblies'[\]]/bind[\[]@service='Interfaces.IRepository, Interfaces'[\]]//@to"
Value="SQLiteRepository.SQLiteRepository, SQLiteRepository"
File="[INSTALLFOLDER]NinjectConfig.xml"
SelectionLanguage="XPath"
Sequence="1" />
</Component>
<ComponentGroup Id="SQLiteRepository" Directory="INSTALLFOLDER">
<Component Id="SQLiteNet" Guid="{4295A808-7CB1-4EFC-BC94-136F22AF7A78}">
<File Id="SQLiteNet.dll"
Source="$(var.SQLiteRepository.TargetDir)\SQLite.Net.dll"
KeyPath="yes"
Checksum="yes" />
</Component>
<Component Id="SQLiteNetPlatformGeneric" Guid="{BBDE8C94-FBBE-413E-83B8-B4248F3B718C}">
<File Id="SQLiteNetPlatformGenericDll"
Source="$(var.SQLiteRepository.TargetDir)\SQLite.Net.Platform.Generic.dll"
KeyPath="yes"
Checksum="yes"/>
</Component>
<Component Id="SQLiteNetPlatformWin32" Guid="{4FE0506E-1A8A-45DF-A2C8-C461332406C8}">
<File Id="SQLiteNetPlatformWin32.dll"
Source="$(var.SQLiteRepository.TargetDir)\SQLite.Net.Platform.Win32.dll"
KeyPath="yes"
Checksum="yes"/>
</Component>
<Component Id="SQLiteRepository" Guid="{4E68CF6F-7F31-4F59-AC93-F48EFE9E1445}">
<File Id="SQLiteRepository.dll"
Source="$(var.SQLiteRepository.TargetDir)\SQLiteRepository.dll"
KeyPath="yes"
Checksum="yes"/>
</Component>
</ComponentGroup>
<ComponentGroup Id="SQLiteInterop">
<Component Id="SQLiteInteropx86" Guid="{14F1C2DD-5D3D-49DF-B466-21AF881FCEAF}" Directory="SQLITEX86">
<File Id="SQLite.Interop.dllx86"
Source="$(var.SQLiteRepository.TargetDir)x86\SQLite.Interop.dll"
KeyPath="yes"
Checksum="yes"/>
</Component>
<Component Id="SQLiteInteropx64" Guid="{45C77D89-8037-48CE-8B78-34C937ECBE83}" Directory="SQLITEX64">
<File Id="SQLite.Interop.dllx64"
Source="$(var.SQLiteRepository.TargetDir)x64\SQLite.Interop.dll"
KeyPath="yes"
Checksum="yes"/>
</Component>
</ComponentGroup>
</Fragment>
</Wix>

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>3.10</ProductVersion>
<ProjectGuid>41caf3c0-ddf9-4a65-a715-da07c4178cbf</ProjectGuid>
<SchemaVersion>2.0</SchemaVersion>
<OutputName>SQLiteRepository</OutputName>
<OutputType>Package</OutputType>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
<Name>SQLiteRepositoryInstaller</Name>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
<DefineConstants>Debug</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\$(Configuration)\</OutputPath>
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="Product.wxs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SQLiteRepository\SQLiteRepository.csproj">
<Name>SQLiteRepository</Name>
<Project>{b3510c81-f069-48a2-b826-ebe0ce7ab0b2}</Project>
<Private>True</Private>
<DoNotHarvest>True</DoNotHarvest>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<WixExtension Include="WixUtilExtension">
<HintPath>$(WixExtDir)\WixUtilExtension.dll</HintPath>
<Name>WixUtilExtension</Name>
</WixExtension>
</ItemGroup>
<Import Project="$(WixTargetsPath)" />
<!--
To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Wix.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,10 @@
namespace SQLiteRepository
{
public enum LogSourceDb
{
UNKNOWN=0,
IDENTIFIER = 1,
UI = 2,
TRAYAPP = 3
}
}

View File

@ -18,6 +18,14 @@ namespace SQLiteRepository
"select * from " + nameof(UserIdentity) + " order by " + nameof(UserIdentity.LastName) + " collate nocase, " +
nameof(UserIdentity.FirstName) + " collate nocase limit ? offset ?";
public const string GET_ALL_USERS_BY_GROUP =
"select u." + nameof(UserIdentity.Id) + ", u." + nameof(UserIdentity.FirstName) + ", u." +
nameof(UserIdentity.LastName) + ", u." + nameof(UserIdentity.HoursPerWeek) + ", u." +
nameof(UserIdentity.IsContractor) + " from " + nameof(UserIdentity) + " u left join " +
nameof(UserGroupJoinDb) + " ugj on ugj." + nameof(UserGroupJoinDb.UserId_FK) + " = u." +
nameof(UserIdentity.Id) + " where ugj." + nameof(UserGroupJoinDb.GroupId_FK) + "=? order by u." +
nameof(UserIdentity.LastName) + " collate nocase, u." + nameof(UserIdentity.LastName) + " collate nocase";
public const string GET_USER_BY_ID =
"select * from " + nameof(UserIdentity) + " where " + nameof(UserIdentity.Id) + "=?";
@ -38,6 +46,11 @@ namespace SQLiteRepository
"update " + nameof(CardUniqueId) + " set " + nameof(CardUniqueId.LastUsed) + " = ? where " +
nameof(CardUniqueId.Id) + " = ?";
public const string UPDATE_USER_DETAILS =
"update " + nameof(UserIdentity) + " set " + nameof(UserIdentity.FirstName) + "=?, " +
nameof(UserIdentity.LastName) + "=?, " + nameof(UserIdentity.HoursPerWeek) + "=?," +
nameof(UserIdentity.IsContractor) + "=? where " + nameof(UserIdentity.Id) + "=?";
public const string SEARCH_USER_LIST =
"SELECT * FROM " + nameof(UserIdentity) + " where(" + nameof(UserIdentity.FirstName) + " Like ? OR " +
nameof(UserIdentity.LastName) + " Like ?)";

View File

@ -50,7 +50,7 @@ namespace SQLiteRepository
{
users =
_connection.Query<UserIdentity>(
"select u.Id, u.FirstName, u.LastName, u.HoursPerWeek, u.IsContractor from UserIdentity u left join UserGroupJoinDb ugj on ugj.UserId_FK = u.Id where ugj.GroupId_FK=?",
SQLiteProcedures.GET_ALL_USERS_BY_GROUP,
groupId);
userCount = users.Count;
}
@ -99,26 +99,6 @@ namespace SQLiteRepository
return ret;
}
private DateTime GetLastLogDateTime(TimeLogDb timeLog)
{
if (timeLog != null)
{
return timeLog.SwipeEventDateTime.DateTime;
}
return DateTime.MinValue;
}
private bool GetUserState(LogDirectionDb logDirection)
{
switch (logDirection)
{
case LogDirectionDb.OUT:
return true;
default:
return false;
}
}
public UserList Search(string searchParam)
{
_logger.Trace("Searching SQLite database for the term: {0}", searchParam);
@ -311,7 +291,7 @@ namespace SQLiteRepository
{
//edit..
_connection.Query<UserIdentity>(
"update UserIdentity set FirstName=?, LastName=?, HoursPerWeek=?,IsContractor=? where Id=?",
SQLiteProcedures.UPDATE_USER_DETAILS,
user.FirstName,
user.LastName,
user.HoursPerWeek,
@ -353,7 +333,7 @@ namespace SQLiteRepository
#region Update Group Associations
SetUserGroups(userId, user.Groups.Where(x=>x.IsAssociatedToUser).ToList());
SetUserGroups(userId, user.Groups.Where(x => x.IsAssociatedToUser).ToList());
#endregion
@ -361,8 +341,9 @@ namespace SQLiteRepository
return ret;
}
public OperationResponse LogEventTime(Identifier identifier, out int logId)
public LogEventResponse LogEventTime(Identifier identifier, out int logId)
{
var ret = new LogEventResponse();
var cardIdQuery = _connection.Query<CardUniqueId>(
SQLiteProcedures.GET_CARDS_BY_UNIQUE_ID,
identifier.UniqueId);
@ -378,7 +359,9 @@ namespace SQLiteRepository
UpdateIdentifierLastUsed(DateTimeOffset.UtcNow, ident.Id);
logId = -1;
//dont try to log any timelogs against this card, as it is unassigned to a user.
return OperationResponse.SUCCESS;
ret.ProcessResponse=OperationResponse.SUCCESS;
ret.Direction = LogDirection.UNKNOWN;
return ret;
}
else
{
@ -392,7 +375,7 @@ namespace SQLiteRepository
#region Check the user hasnt registered an event in the last few minutes..
if (ident.UserId_FK!=-1)
if (ident.UserId_FK != -1)
{ //only check log gap if the card is associated to a user
var hysteresisThresholdMinutes = Convert.ToInt32(ConfigurationHandler.ConfigurationHandler.GetConfiguration("SwipeTimeGap") ?? "3");
var threshold = DateTime.UtcNow.AddMinutes(0 - hysteresisThresholdMinutes);
@ -404,7 +387,9 @@ namespace SQLiteRepository
{
_logger.Error("Not logging event for user id: {0}, logged event within TimeGap Threshold of {1}", ident.UserId_FK, threshold);
logId = -1;
return OperationResponse.FAILED;
ret.ProcessResponse = OperationResponse.FAILED;
ret.Direction = LogDirection.UNKNOWN;
return ret;
}
}
@ -423,28 +408,30 @@ namespace SQLiteRepository
IdentifierId = ident.Id,
Direction = logDirection,
Year = year,
CalendarWeek = calendarWeek
CalendarWeek = calendarWeek,
Source = LogSourceDb.IDENTIFIER
};
_connection.Insert(timeLog);
UpdateIdentifierLastUsed(timeLog.SwipeEventDateTime, timeLog.IdentifierId);
logId = timeLog.Id;
return OperationResponse.SUCCESS;
ret.Direction = (LogDirection)(int)logDirection;
ret.ProcessResponse = OperationResponse.SUCCESS;
return ret;
}
/*Groups*/
//TODO: check group name can only be entered once.
public OperationResponse CreateGroup(Group group, out int groupId)
{
var groupDb = new GroupDb { GroupName=group.Name};
var groupDb = new GroupDb { GroupName = group.Name };
var resp = _connection.Insert(groupDb);
groupId = groupDb.GroupId;
return OperationResponse.CREATED;
}
public List<Group> GetGroups(int userId=-1)
public List<Group> GetGroups(int userId = -1)
{
var ret = new List<Group>();
List<GroupDb> query;
@ -459,13 +446,12 @@ namespace SQLiteRepository
}
else
{
var t = new UserGroupJoinDb();
query =
_connection.Query<GroupDb>(
"select gdb.GroupId, gdb.GroupName, gdb.AssignedUserCount"+
" from GroupDb gdb"+
" left join UserGroupJoinDb ujdb"+
" on gdb.GroupId = ujdb.GroupId_FK"+
"select gdb.GroupId, gdb.GroupName, gdb.AssignedUserCount" +
" from GroupDb gdb" +
" left join UserGroupJoinDb ujdb" +
" on gdb.GroupId = ujdb.GroupId_FK" +
" where ujdb.UserId_FK = ?",
userId);
}
@ -473,9 +459,9 @@ namespace SQLiteRepository
{
ret.Add(new Group
{
Id=group.GroupId,
Id = group.GroupId,
Name = group.GroupName,
UserCount = int.Parse(group.AssignedUserCount??"0")
UserCount = int.Parse(group.AssignedUserCount ?? "0")
});
}
return ret;
@ -500,11 +486,6 @@ namespace SQLiteRepository
public OperationResponse UpdateGroup(Group group)
{
//TODO: I would probably prefer to do this manually....
var groupDb = new GroupDb
{
GroupId = group.Id,
GroupName = group.Name
};
var resp = _connection.Query<GroupDb>("update GroupDb set GroupName=? where GroupId=?", group.Name, group.Id);
//var resp = _connection.Update(groupDb);
return OperationResponse.UPDATED;
@ -516,9 +497,96 @@ namespace SQLiteRepository
return OperationResponse.DELETED;
}
public OperationResponse DeleteLog(TimeLog log)
{
var query = _connection.Query<TimeLogDb>(
"select * from TimeLogDb where Id=?", log.Id);
if (!query.Any())
return OperationResponse.FAILED;
_connection.ExecuteScalar<TimeLogDb>("delete from TimeLogDb where Id=?", log.Id);
return OperationResponse.DELETED;
}
public OperationResponse CreateLog(TimeLog log)
{
var calendarWeek = GetIso8601CalendarWeek(log.EventTime.UtcDateTime);
var year = log.EventTime.Year;
var dbLog = new TimeLogDb
{
SwipeEventDateTime = log.EventTime,
Direction = (LogDirectionDb)(int)log.Direction,
Year = year,
CalendarWeek = calendarWeek,
Source = (LogSourceDb)(int)log.Source,
UserId_FK = log.UserId,
IdentifierId = ConvertSourceToIdentifierId(log.Source),
};
_connection.Insert(dbLog);
return OperationResponse.CREATED;
}
public OperationResponse UpdateLog(TimeLog log)
{
var query = _connection.Query<TimeLogDb>(
"select * from TimeLogDb where Id=?", log.Id);
if(!query.Any())
return OperationResponse.FAILED;
if (log.CalendarWeek > 52 || log.CalendarWeek < 1)
{
log.CalendarWeek = GetIso8601CalendarWeek(log.EventTime.UtcDateTime);
}
if (log.Year < 2017)
{
log.Year = log.EventTime.Year;
}
_connection.ExecuteScalar<TimeLogDb>(
"update TimeLogDb set UserId_FK=?, Direction=?,SwipeEventDateTime=?,CalendarWeek=?,Year=?,Source=? where Id=?",
log.UserId, (LogDirectionDb) (int) log.Direction, log.EventTime, log.CalendarWeek, log.Year,
(LogSourceDb) (int) log.Source, log.Id);
return OperationResponse.UPDATED;
}
private DateTime GetLastLogDateTime(TimeLogDb timeLog)
{
if (timeLog != null)
{
return timeLog.SwipeEventDateTime.DateTime;
}
return DateTime.MinValue;
}
private bool GetUserState(LogDirectionDb logDirection)
{
switch (logDirection)
{
case LogDirectionDb.OUT:
return true;
default:
return false;
}
}
private int ConvertSourceToIdentifierId(LogSource logSource)
{
switch (logSource)
{
case LogSource.UI:
return -100;
case LogSource.TRAYAPP:
return -200;
default:
return -10;
}
}
private bool SetUserGroups(int userId, List<Group> groups)
{
var groupIds = GetGroupIds(groups.Select(x=>x.Name).ToList());
var groupIds = GetGroupIds(groups.Select(x => x.Name).ToList());
return SetUserGroups(userId, groupIds);
}
@ -527,7 +595,7 @@ namespace SQLiteRepository
//remove the existing user>group associations
_connection.Query<UserGroupJoinDb>("delete from UserGroupJoinDb where UserId_FK = ?", userId);
//add the new group associations.
_connection.InsertAll(groupIds.Select(x => new UserGroupJoinDb {GroupId_FK = x, UserId_FK = userId}));
_connection.InsertAll(groupIds.Select(x => new UserGroupJoinDb { GroupId_FK = x, UserId_FK = userId }));
return true;
}
@ -560,7 +628,7 @@ namespace SQLiteRepository
EventTime = x.SwipeEventDateTime,
UserId = x.UserId_FK,
Year = x.Year
}).ToList();
}).OrderBy(x=>x.EventTime.UtcDateTime).ToList();
var dict = new Dictionary<DayOfWeek, DailyLogs>();
var logList = new List<DailyLogs>();
@ -572,7 +640,7 @@ namespace SQLiteRepository
}
//add the logs to the respective day of the week.
foreach (var log in timeLogs)
foreach (var log in timeLogs.OrderBy(x=>x.EventTime))
{
dict[log.EventTime.DayOfWeek].Logs.Add(log);
}
@ -592,7 +660,7 @@ namespace SQLiteRepository
foreach (DayOfWeek day in Enum.GetValues(typeof(DayOfWeek)))
{
if (logList.Any(x => x.Day == day)) continue;
var dailyLog = new DailyLogs {Day = day, DayOfWeek = day.ToString()};
var dailyLog = new DailyLogs { Day = day, DayOfWeek = day.ToString() };
logList.Add(dailyLog);
}
@ -601,13 +669,13 @@ namespace SQLiteRepository
dailyCollection.Value.DailyTotal = CalculateDailyTotal(dailyCollection.Value);
}
return logList.OrderBy(x => ((int) x.Day + 6)%7).ToList();
return logList.OrderBy(x => ((int)x.Day + 6) % 7).ToList();
}
private double CalculateDailyTotal(DailyLogs dailyLogs)
{
var totalInTime = TimeSpan.FromSeconds(0);
var logs = dailyLogs.Logs.OrderBy(x => x.Id).ToArray();
var logs = dailyLogs.Logs.OrderBy(x => x.EventTime.UtcDateTime).ToArray();
var totalCalcMax = IsOdd(logs.Length) ? logs.Length - 1 : logs.Length;
for (int i = 0; i < totalCalcMax; i += 2)
{

View File

@ -31,6 +31,24 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugInstallers|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\DebugInstallers\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseInstallers|AnyCPU'">
<OutputPath>bin\ReleaseInstallers\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="SQLite.Net, Version=3.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\SQLite.Net.Core-PCL.3.1.1\lib\portable-win8+net45+wp8+wpa81+MonoAndroid1+MonoTouch1\SQLite.Net.dll</HintPath>
@ -61,6 +79,7 @@
<ItemGroup>
<Compile Include="CardUniqueId.cs" />
<Compile Include="GroupDb.cs" />
<Compile Include="LogSourceDb.cs" />
<Compile Include="SQLiteRepository.cs" />
<Compile Include="Constants.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

View File

@ -13,5 +13,6 @@ namespace SQLiteRepository
public DateTimeOffset SwipeEventDateTime { get; set; }
public int CalendarWeek { get; set; }
public int Year { get; set; }
public LogSourceDb Source { get; set; }
}
}

View File

@ -31,10 +31,17 @@
<Compile Include="NLog.wxs" />
<Compile Include="Product.wxs" />
<Compile Include="Properties.wxs" />
<Compile Include="SQLiteRepository.wxs" />
<Compile Include="WebPages.wxs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ConfigurationHandler\ConfigurationHandler.csproj">
<Name>ConfigurationHandler</Name>
<Project>{115250f6-f8c4-4f9b-a15f-251ea258d963}</Project>
<Private>True</Private>
<DoNotHarvest>True</DoNotHarvest>
<RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
<RefTargetDir>INSTALLFOLDER</RefTargetDir>
</ProjectReference>
<ProjectReference Include="..\Interfaces\Interfaces.csproj">
<Name>Interfaces</Name>
<Project>{b7347b72-e208-423a-9d99-723b558ea3d7}</Project>

View File

@ -8,6 +8,7 @@
<ComponentRef Id="URLReservation"/>
<ComponentRef Id="DataCenterFirewallConfig"/>
<ComponentGroupRef Id="DataCenterFileGroup"/>
<ComponentRef Id="ServiceConfiguration"/>
</ComponentGroup>
<ComponentGroup Id="DataCenterFileGroup" Directory="INSTALLFOLDER">
@ -202,5 +203,15 @@
Checksum="yes"/>
</Component>
</ComponentGroup>
<Component Id="ServiceConfiguration" Directory="INSTALLFOLDER" Guid="{E49ABD61-0CCA-45A2-A525-DF85A0493FF7}" KeyPath="yes">
<util:XmlFile Id="SetServicePort"
Action="setValue"
ElementPath="//appSettings/add[\[]@key='WebsiteHttpPort'[\]]/@value"
Value="[SERVICEPORT]"
File="[#WindowsDataCenter.exe.config]"
SelectionLanguage="XPath"
Sequence="1" />
</Component>
</Fragment>
</Wix>

View File

@ -3,7 +3,7 @@
xmlns:http="http://schemas.microsoft.com/wix/HttpExtension">
<Fragment>
<Component Id="URLReservation" Guid="{35F39190-88CA-4D1D-B066-9F9CAB328F4D}" Directory="INSTALLFOLDER" KeyPath="yes">
<http:UrlReservation Id="EndpointUrlAcl" Url="http://*:8800/" HandleExisting="ignore">
<http:UrlReservation Id="EndpointUrlAcl" Url="http://*:[SERVICEPORT]/" HandleExisting="ignore">
<http:UrlAce SecurityPrincipal="Everyone" Rights="all"/>
</http:UrlReservation>
</Component>

View File

@ -3,7 +3,7 @@
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="WebApiServerHostInstaller" >
<Directory Id="INSTALLFOLDER" Name="Flexitime Data Center" >
<Directory Id="CONFIGFILES" Name="Configs" />
</Directory>
</Directory>

View File

@ -29,7 +29,6 @@
<ComponentGroupRef Id="DalSoftWebApiHelpComponents" />
<ComponentGroupRef Id="DataCenterComponents"/>
<ComponentGroupRef Id="NLogComponents" />
<ComponentGroupRef Id="SQLiteRepositoryComponents" />
<ComponentGroupRef Id="WebSiteComponents" />
</ComponentGroup>
</Fragment>

View File

@ -2,5 +2,6 @@
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<Property Id="STARTSERVICEONINSTALL" Value="false" />
<Property Id="SERVICEPORT" Value="8800" />
</Fragment>
</Wix>

View File

@ -1,56 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef Id="INSTALLFOLDER">
<Directory Id="SQLITEX86" Name="x86" />
<Directory Id="SQLITEX64" Name="x64" />
</DirectoryRef>
<ComponentGroup Id="SQLiteRepositoryComponents" >
<ComponentGroupRef Id="SQLiteRepository" />
<ComponentGroupRef Id="SQLiteInterop" />
</ComponentGroup>
<ComponentGroup Id="SQLiteRepository" Directory="INSTALLFOLDER">
<Component Id="SQLiteNet" Guid="{65D7D3DB-AB4A-41DE-956E-ACBC1EC1E5B7}">
<File Id="SQLiteNet.dll"
Source="$(var.SQLiteRepository.TargetDir)\SQLite.Net.dll"
KeyPath="yes"
Checksum="yes" />
</Component>
<Component Id="SQLiteNetPlatformGeneric" Guid="{6E540212-B40B-41EB-BD81-1D8625F330D3}">
<File Id="SQLiteNetPlatformGenericDll"
Source="$(var.SQLiteRepository.TargetDir)\SQLite.Net.Platform.Generic.dll"
KeyPath="yes"
Checksum="yes"/>
</Component>
<Component Id="SQLiteNetPlatformWin32" Guid="{41E99987-0901-44D8-A2E8-2BCE18660298}">
<File Id="SQLiteNetPlatformWin32.dll"
Source="$(var.SQLiteRepository.TargetDir)\SQLite.Net.Platform.Win32.dll"
KeyPath="yes"
Checksum="yes"/>
</Component>
<Component Id="SQLiteRepository" Guid="{B109C5DD-FD21-4078-9534-6065753F2900}">
<File Id="SQLiteRepository.dll"
Source="$(var.SQLiteRepository.TargetDir)\SQLiteRepository.dll"
KeyPath="yes"
Checksum="yes"/>
</Component>
</ComponentGroup>
<ComponentGroup Id="SQLiteInterop">
<Component Id="SQLiteInteropx86" Guid="{7D4C1BF5-A6B5-4379-B040-4AD6BABBB526}" Directory="SQLITEX86">
<File Id="SQLite.Interop.dllx86"
Source="$(var.WindowsDataCenter.TargetDir)x86\SQLite.Interop.dll"
KeyPath="yes"
Checksum="yes"/>
</Component>
<Component Id="SQLiteInteropx64" Guid="{3591D185-ECBA-4382-BE75-FF6A271CEE3B}" Directory="SQLITEX64">
<File Id="SQLite.Interop.dllx64"
Source="$(var.WindowsDataCenter.TargetDir)x64\SQLite.Interop.dll"
KeyPath="yes"
Checksum="yes"/>
</Component>
</ComponentGroup>
</Fragment>
</Wix>

View File

@ -30,90 +30,206 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Installers", "Installers",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConfigurationHandler", "ConfigurationHandler\ConfigurationHandler.csproj", "{115250F6-F8C4-4F9B-A15F-251EA258D963}"
EndProject
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "FlexiTimeSystemInstaller", "FlexiTimeSystemInstaller\FlexiTimeSystemInstaller.wixproj", "{D38E92DB-48F9-40C3-9A6F-D76FBD07326E}"
EndProject
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "SQLiteRepositoryInstaller", "SQLiteProvider\SQLiteRepositoryInstaller.wixproj", "{41CAF3C0-DDF9-4A65-A715-DA07C4178CBF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x86 = Debug|x86
DebugInstallers|Any CPU = DebugInstallers|Any CPU
DebugInstallers|x86 = DebugInstallers|x86
Release|Any CPU = Release|Any CPU
Release|x86 = Release|x86
ReleaseInstallers|Any CPU = ReleaseInstallers|Any CPU
ReleaseInstallers|x86 = ReleaseInstallers|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A5FEE048-17A6-4966-9B6B-BF073592A470}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A5FEE048-17A6-4966-9B6B-BF073592A470}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A5FEE048-17A6-4966-9B6B-BF073592A470}.Debug|x86.ActiveCfg = Debug|Any CPU
{A5FEE048-17A6-4966-9B6B-BF073592A470}.Debug|x86.Build.0 = Debug|Any CPU
{A5FEE048-17A6-4966-9B6B-BF073592A470}.DebugInstallers|Any CPU.ActiveCfg = DebugInstallers|Any CPU
{A5FEE048-17A6-4966-9B6B-BF073592A470}.DebugInstallers|Any CPU.Build.0 = DebugInstallers|Any CPU
{A5FEE048-17A6-4966-9B6B-BF073592A470}.DebugInstallers|x86.ActiveCfg = DebugInstallers|Any CPU
{A5FEE048-17A6-4966-9B6B-BF073592A470}.DebugInstallers|x86.Build.0 = DebugInstallers|Any CPU
{A5FEE048-17A6-4966-9B6B-BF073592A470}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A5FEE048-17A6-4966-9B6B-BF073592A470}.Release|Any CPU.Build.0 = Release|Any CPU
{A5FEE048-17A6-4966-9B6B-BF073592A470}.Release|x86.ActiveCfg = Release|Any CPU
{A5FEE048-17A6-4966-9B6B-BF073592A470}.Release|x86.Build.0 = Release|Any CPU
{A5FEE048-17A6-4966-9B6B-BF073592A470}.ReleaseInstallers|Any CPU.ActiveCfg = ReleaseInstallers|Any CPU
{A5FEE048-17A6-4966-9B6B-BF073592A470}.ReleaseInstallers|Any CPU.Build.0 = ReleaseInstallers|Any CPU
{A5FEE048-17A6-4966-9B6B-BF073592A470}.ReleaseInstallers|x86.ActiveCfg = ReleaseInstallers|Any CPU
{A5FEE048-17A6-4966-9B6B-BF073592A470}.ReleaseInstallers|x86.Build.0 = ReleaseInstallers|Any CPU
{5A4E2CF2-FA51-413E-82C7-14A19A50766D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5A4E2CF2-FA51-413E-82C7-14A19A50766D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5A4E2CF2-FA51-413E-82C7-14A19A50766D}.Debug|x86.ActiveCfg = Debug|Any CPU
{5A4E2CF2-FA51-413E-82C7-14A19A50766D}.Debug|x86.Build.0 = Debug|Any CPU
{5A4E2CF2-FA51-413E-82C7-14A19A50766D}.DebugInstallers|Any CPU.ActiveCfg = DebugInstallers|Any CPU
{5A4E2CF2-FA51-413E-82C7-14A19A50766D}.DebugInstallers|Any CPU.Build.0 = DebugInstallers|Any CPU
{5A4E2CF2-FA51-413E-82C7-14A19A50766D}.DebugInstallers|x86.ActiveCfg = DebugInstallers|Any CPU
{5A4E2CF2-FA51-413E-82C7-14A19A50766D}.DebugInstallers|x86.Build.0 = DebugInstallers|Any CPU
{5A4E2CF2-FA51-413E-82C7-14A19A50766D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5A4E2CF2-FA51-413E-82C7-14A19A50766D}.Release|Any CPU.Build.0 = Release|Any CPU
{5A4E2CF2-FA51-413E-82C7-14A19A50766D}.Release|x86.ActiveCfg = Release|Any CPU
{5A4E2CF2-FA51-413E-82C7-14A19A50766D}.Release|x86.Build.0 = Release|Any CPU
{5A4E2CF2-FA51-413E-82C7-14A19A50766D}.ReleaseInstallers|Any CPU.ActiveCfg = ReleaseInstallers|Any CPU
{5A4E2CF2-FA51-413E-82C7-14A19A50766D}.ReleaseInstallers|Any CPU.Build.0 = ReleaseInstallers|Any CPU
{5A4E2CF2-FA51-413E-82C7-14A19A50766D}.ReleaseInstallers|x86.ActiveCfg = ReleaseInstallers|Any CPU
{5A4E2CF2-FA51-413E-82C7-14A19A50766D}.ReleaseInstallers|x86.Build.0 = ReleaseInstallers|Any CPU
{B7347B72-E208-423A-9D99-723B558EA3D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B7347B72-E208-423A-9D99-723B558EA3D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B7347B72-E208-423A-9D99-723B558EA3D7}.Debug|x86.ActiveCfg = Debug|Any CPU
{B7347B72-E208-423A-9D99-723B558EA3D7}.Debug|x86.Build.0 = Debug|Any CPU
{B7347B72-E208-423A-9D99-723B558EA3D7}.DebugInstallers|Any CPU.ActiveCfg = DebugInstallers|Any CPU
{B7347B72-E208-423A-9D99-723B558EA3D7}.DebugInstallers|Any CPU.Build.0 = DebugInstallers|Any CPU
{B7347B72-E208-423A-9D99-723B558EA3D7}.DebugInstallers|x86.ActiveCfg = DebugInstallers|Any CPU
{B7347B72-E208-423A-9D99-723B558EA3D7}.DebugInstallers|x86.Build.0 = DebugInstallers|Any CPU
{B7347B72-E208-423A-9D99-723B558EA3D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B7347B72-E208-423A-9D99-723B558EA3D7}.Release|Any CPU.Build.0 = Release|Any CPU
{B7347B72-E208-423A-9D99-723B558EA3D7}.Release|x86.ActiveCfg = Release|Any CPU
{B7347B72-E208-423A-9D99-723B558EA3D7}.Release|x86.Build.0 = Release|Any CPU
{B7347B72-E208-423A-9D99-723B558EA3D7}.ReleaseInstallers|Any CPU.ActiveCfg = ReleaseInstallers|Any CPU
{B7347B72-E208-423A-9D99-723B558EA3D7}.ReleaseInstallers|Any CPU.Build.0 = ReleaseInstallers|Any CPU
{B7347B72-E208-423A-9D99-723B558EA3D7}.ReleaseInstallers|x86.ActiveCfg = ReleaseInstallers|Any CPU
{B7347B72-E208-423A-9D99-723B558EA3D7}.ReleaseInstallers|x86.Build.0 = ReleaseInstallers|Any CPU
{B3510C81-F069-48A2-B826-EBE0CE7AB0B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B3510C81-F069-48A2-B826-EBE0CE7AB0B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B3510C81-F069-48A2-B826-EBE0CE7AB0B2}.Debug|x86.ActiveCfg = Debug|Any CPU
{B3510C81-F069-48A2-B826-EBE0CE7AB0B2}.Debug|x86.Build.0 = Debug|Any CPU
{B3510C81-F069-48A2-B826-EBE0CE7AB0B2}.DebugInstallers|Any CPU.ActiveCfg = DebugInstallers|Any CPU
{B3510C81-F069-48A2-B826-EBE0CE7AB0B2}.DebugInstallers|Any CPU.Build.0 = DebugInstallers|Any CPU
{B3510C81-F069-48A2-B826-EBE0CE7AB0B2}.DebugInstallers|x86.ActiveCfg = DebugInstallers|Any CPU
{B3510C81-F069-48A2-B826-EBE0CE7AB0B2}.DebugInstallers|x86.Build.0 = DebugInstallers|Any CPU
{B3510C81-F069-48A2-B826-EBE0CE7AB0B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B3510C81-F069-48A2-B826-EBE0CE7AB0B2}.Release|Any CPU.Build.0 = Release|Any CPU
{B3510C81-F069-48A2-B826-EBE0CE7AB0B2}.Release|x86.ActiveCfg = Release|Any CPU
{B3510C81-F069-48A2-B826-EBE0CE7AB0B2}.Release|x86.Build.0 = Release|Any CPU
{B3510C81-F069-48A2-B826-EBE0CE7AB0B2}.ReleaseInstallers|Any CPU.ActiveCfg = ReleaseInstallers|Any CPU
{B3510C81-F069-48A2-B826-EBE0CE7AB0B2}.ReleaseInstallers|Any CPU.Build.0 = ReleaseInstallers|Any CPU
{B3510C81-F069-48A2-B826-EBE0CE7AB0B2}.ReleaseInstallers|x86.ActiveCfg = ReleaseInstallers|Any CPU
{B3510C81-F069-48A2-B826-EBE0CE7AB0B2}.ReleaseInstallers|x86.Build.0 = ReleaseInstallers|Any CPU
{1C5220D6-9166-4F47-B57D-BEB4D09D2A3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1C5220D6-9166-4F47-B57D-BEB4D09D2A3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1C5220D6-9166-4F47-B57D-BEB4D09D2A3F}.Debug|x86.ActiveCfg = Debug|Any CPU
{1C5220D6-9166-4F47-B57D-BEB4D09D2A3F}.Debug|x86.Build.0 = Debug|Any CPU
{1C5220D6-9166-4F47-B57D-BEB4D09D2A3F}.DebugInstallers|Any CPU.ActiveCfg = DebugInstallers|Any CPU
{1C5220D6-9166-4F47-B57D-BEB4D09D2A3F}.DebugInstallers|Any CPU.Build.0 = DebugInstallers|Any CPU
{1C5220D6-9166-4F47-B57D-BEB4D09D2A3F}.DebugInstallers|x86.ActiveCfg = DebugInstallers|Any CPU
{1C5220D6-9166-4F47-B57D-BEB4D09D2A3F}.DebugInstallers|x86.Build.0 = DebugInstallers|Any CPU
{1C5220D6-9166-4F47-B57D-BEB4D09D2A3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1C5220D6-9166-4F47-B57D-BEB4D09D2A3F}.Release|Any CPU.Build.0 = Release|Any CPU
{1C5220D6-9166-4F47-B57D-BEB4D09D2A3F}.Release|x86.ActiveCfg = Release|Any CPU
{1C5220D6-9166-4F47-B57D-BEB4D09D2A3F}.Release|x86.Build.0 = Release|Any CPU
{1C5220D6-9166-4F47-B57D-BEB4D09D2A3F}.ReleaseInstallers|Any CPU.ActiveCfg = ReleaseInstallers|Any CPU
{1C5220D6-9166-4F47-B57D-BEB4D09D2A3F}.ReleaseInstallers|Any CPU.Build.0 = ReleaseInstallers|Any CPU
{1C5220D6-9166-4F47-B57D-BEB4D09D2A3F}.ReleaseInstallers|x86.ActiveCfg = ReleaseInstallers|Any CPU
{1C5220D6-9166-4F47-B57D-BEB4D09D2A3F}.ReleaseInstallers|x86.Build.0 = ReleaseInstallers|Any CPU
{C5A4CDC3-849C-4166-BDC3-56BDB307126D}.Debug|Any CPU.ActiveCfg = Debug|x86
{C5A4CDC3-849C-4166-BDC3-56BDB307126D}.Debug|x86.ActiveCfg = Debug|x86
{C5A4CDC3-849C-4166-BDC3-56BDB307126D}.Debug|x86.Build.0 = Debug|x86
{C5A4CDC3-849C-4166-BDC3-56BDB307126D}.DebugInstallers|Any CPU.ActiveCfg = Debug|x86
{C5A4CDC3-849C-4166-BDC3-56BDB307126D}.DebugInstallers|Any CPU.Build.0 = Debug|x86
{C5A4CDC3-849C-4166-BDC3-56BDB307126D}.DebugInstallers|x86.ActiveCfg = Debug|x86
{C5A4CDC3-849C-4166-BDC3-56BDB307126D}.DebugInstallers|x86.Build.0 = Debug|x86
{C5A4CDC3-849C-4166-BDC3-56BDB307126D}.Release|Any CPU.ActiveCfg = Release|x86
{C5A4CDC3-849C-4166-BDC3-56BDB307126D}.Release|x86.ActiveCfg = Release|x86
{C5A4CDC3-849C-4166-BDC3-56BDB307126D}.Release|x86.Build.0 = Release|x86
{C5A4CDC3-849C-4166-BDC3-56BDB307126D}.ReleaseInstallers|Any CPU.ActiveCfg = Release|x86
{C5A4CDC3-849C-4166-BDC3-56BDB307126D}.ReleaseInstallers|Any CPU.Build.0 = Release|x86
{C5A4CDC3-849C-4166-BDC3-56BDB307126D}.ReleaseInstallers|x86.ActiveCfg = Release|x86
{C5A4CDC3-849C-4166-BDC3-56BDB307126D}.ReleaseInstallers|x86.Build.0 = Release|x86
{5F30E8E4-5107-4C99-ADFF-38D735DC113D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5F30E8E4-5107-4C99-ADFF-38D735DC113D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5F30E8E4-5107-4C99-ADFF-38D735DC113D}.Debug|x86.ActiveCfg = Debug|Any CPU
{5F30E8E4-5107-4C99-ADFF-38D735DC113D}.Debug|x86.Build.0 = Debug|Any CPU
{5F30E8E4-5107-4C99-ADFF-38D735DC113D}.DebugInstallers|Any CPU.ActiveCfg = DebugInstallers|Any CPU
{5F30E8E4-5107-4C99-ADFF-38D735DC113D}.DebugInstallers|Any CPU.Build.0 = DebugInstallers|Any CPU
{5F30E8E4-5107-4C99-ADFF-38D735DC113D}.DebugInstallers|x86.ActiveCfg = DebugInstallers|Any CPU
{5F30E8E4-5107-4C99-ADFF-38D735DC113D}.DebugInstallers|x86.Build.0 = DebugInstallers|Any CPU
{5F30E8E4-5107-4C99-ADFF-38D735DC113D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5F30E8E4-5107-4C99-ADFF-38D735DC113D}.Release|Any CPU.Build.0 = Release|Any CPU
{5F30E8E4-5107-4C99-ADFF-38D735DC113D}.Release|x86.ActiveCfg = Release|Any CPU
{5F30E8E4-5107-4C99-ADFF-38D735DC113D}.Release|x86.Build.0 = Release|Any CPU
{5F30E8E4-5107-4C99-ADFF-38D735DC113D}.ReleaseInstallers|Any CPU.ActiveCfg = ReleaseInstallers|Any CPU
{5F30E8E4-5107-4C99-ADFF-38D735DC113D}.ReleaseInstallers|Any CPU.Build.0 = ReleaseInstallers|Any CPU
{5F30E8E4-5107-4C99-ADFF-38D735DC113D}.ReleaseInstallers|x86.ActiveCfg = ReleaseInstallers|Any CPU
{5F30E8E4-5107-4C99-ADFF-38D735DC113D}.ReleaseInstallers|x86.Build.0 = ReleaseInstallers|Any CPU
{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}.Debug|x86.ActiveCfg = Debug|Any CPU
{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}.Debug|x86.Build.0 = Debug|Any CPU
{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}.DebugInstallers|Any CPU.ActiveCfg = DebugInstallers|Any CPU
{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}.DebugInstallers|Any CPU.Build.0 = DebugInstallers|Any CPU
{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}.DebugInstallers|x86.ActiveCfg = DebugInstallers|Any CPU
{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}.DebugInstallers|x86.Build.0 = DebugInstallers|Any CPU
{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}.Release|Any CPU.Build.0 = Release|Any CPU
{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}.Release|x86.ActiveCfg = Release|Any CPU
{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}.Release|x86.Build.0 = Release|Any CPU
{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}.ReleaseInstallers|Any CPU.ActiveCfg = ReleaseInstallers|Any CPU
{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}.ReleaseInstallers|Any CPU.Build.0 = ReleaseInstallers|Any CPU
{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}.ReleaseInstallers|x86.ActiveCfg = ReleaseInstallers|Any CPU
{6E48913F-9D8C-4132-93A7-C7B1C6DD5264}.ReleaseInstallers|x86.Build.0 = ReleaseInstallers|Any CPU
{119216DE-FC7F-408A-9C2C-105874449E42}.Debug|Any CPU.ActiveCfg = Debug|x86
{119216DE-FC7F-408A-9C2C-105874449E42}.Debug|x86.ActiveCfg = Debug|x86
{119216DE-FC7F-408A-9C2C-105874449E42}.Debug|x86.Build.0 = Debug|x86
{119216DE-FC7F-408A-9C2C-105874449E42}.DebugInstallers|Any CPU.ActiveCfg = Debug|x86
{119216DE-FC7F-408A-9C2C-105874449E42}.DebugInstallers|Any CPU.Build.0 = Debug|x86
{119216DE-FC7F-408A-9C2C-105874449E42}.DebugInstallers|x86.ActiveCfg = Debug|x86
{119216DE-FC7F-408A-9C2C-105874449E42}.DebugInstallers|x86.Build.0 = Debug|x86
{119216DE-FC7F-408A-9C2C-105874449E42}.Release|Any CPU.ActiveCfg = Release|x86
{119216DE-FC7F-408A-9C2C-105874449E42}.Release|x86.ActiveCfg = Release|x86
{119216DE-FC7F-408A-9C2C-105874449E42}.Release|x86.Build.0 = Release|x86
{119216DE-FC7F-408A-9C2C-105874449E42}.ReleaseInstallers|Any CPU.ActiveCfg = Release|x86
{119216DE-FC7F-408A-9C2C-105874449E42}.ReleaseInstallers|Any CPU.Build.0 = Release|x86
{119216DE-FC7F-408A-9C2C-105874449E42}.ReleaseInstallers|x86.ActiveCfg = Release|x86
{119216DE-FC7F-408A-9C2C-105874449E42}.ReleaseInstallers|x86.Build.0 = Release|x86
{115250F6-F8C4-4F9B-A15F-251EA258D963}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{115250F6-F8C4-4F9B-A15F-251EA258D963}.Debug|Any CPU.Build.0 = Debug|Any CPU
{115250F6-F8C4-4F9B-A15F-251EA258D963}.Debug|x86.ActiveCfg = Debug|Any CPU
{115250F6-F8C4-4F9B-A15F-251EA258D963}.Debug|x86.Build.0 = Debug|Any CPU
{115250F6-F8C4-4F9B-A15F-251EA258D963}.DebugInstallers|Any CPU.ActiveCfg = DebugInstallers|Any CPU
{115250F6-F8C4-4F9B-A15F-251EA258D963}.DebugInstallers|Any CPU.Build.0 = DebugInstallers|Any CPU
{115250F6-F8C4-4F9B-A15F-251EA258D963}.DebugInstallers|x86.ActiveCfg = DebugInstallers|Any CPU
{115250F6-F8C4-4F9B-A15F-251EA258D963}.DebugInstallers|x86.Build.0 = DebugInstallers|Any CPU
{115250F6-F8C4-4F9B-A15F-251EA258D963}.Release|Any CPU.ActiveCfg = Release|Any CPU
{115250F6-F8C4-4F9B-A15F-251EA258D963}.Release|Any CPU.Build.0 = Release|Any CPU
{115250F6-F8C4-4F9B-A15F-251EA258D963}.Release|x86.ActiveCfg = Release|Any CPU
{115250F6-F8C4-4F9B-A15F-251EA258D963}.Release|x86.Build.0 = Release|Any CPU
{115250F6-F8C4-4F9B-A15F-251EA258D963}.ReleaseInstallers|Any CPU.ActiveCfg = ReleaseInstallers|Any CPU
{115250F6-F8C4-4F9B-A15F-251EA258D963}.ReleaseInstallers|Any CPU.Build.0 = ReleaseInstallers|Any CPU
{115250F6-F8C4-4F9B-A15F-251EA258D963}.ReleaseInstallers|x86.ActiveCfg = ReleaseInstallers|Any CPU
{115250F6-F8C4-4F9B-A15F-251EA258D963}.ReleaseInstallers|x86.Build.0 = ReleaseInstallers|Any CPU
{D38E92DB-48F9-40C3-9A6F-D76FBD07326E}.Debug|Any CPU.ActiveCfg = Debug|x86
{D38E92DB-48F9-40C3-9A6F-D76FBD07326E}.Debug|x86.ActiveCfg = Debug|x86
{D38E92DB-48F9-40C3-9A6F-D76FBD07326E}.Debug|x86.Build.0 = Debug|x86
{D38E92DB-48F9-40C3-9A6F-D76FBD07326E}.DebugInstallers|Any CPU.ActiveCfg = Debug|x86
{D38E92DB-48F9-40C3-9A6F-D76FBD07326E}.DebugInstallers|Any CPU.Build.0 = Debug|x86
{D38E92DB-48F9-40C3-9A6F-D76FBD07326E}.DebugInstallers|x86.ActiveCfg = Debug|x86
{D38E92DB-48F9-40C3-9A6F-D76FBD07326E}.DebugInstallers|x86.Build.0 = Debug|x86
{D38E92DB-48F9-40C3-9A6F-D76FBD07326E}.Release|Any CPU.ActiveCfg = Release|x86
{D38E92DB-48F9-40C3-9A6F-D76FBD07326E}.Release|x86.ActiveCfg = Release|x86
{D38E92DB-48F9-40C3-9A6F-D76FBD07326E}.Release|x86.Build.0 = Release|x86
{D38E92DB-48F9-40C3-9A6F-D76FBD07326E}.ReleaseInstallers|Any CPU.ActiveCfg = Release|x86
{D38E92DB-48F9-40C3-9A6F-D76FBD07326E}.ReleaseInstallers|Any CPU.Build.0 = Release|x86
{D38E92DB-48F9-40C3-9A6F-D76FBD07326E}.ReleaseInstallers|x86.ActiveCfg = Release|x86
{D38E92DB-48F9-40C3-9A6F-D76FBD07326E}.ReleaseInstallers|x86.Build.0 = Release|x86
{41CAF3C0-DDF9-4A65-A715-DA07C4178CBF}.Debug|Any CPU.ActiveCfg = Debug|x86
{41CAF3C0-DDF9-4A65-A715-DA07C4178CBF}.Debug|x86.ActiveCfg = Debug|x86
{41CAF3C0-DDF9-4A65-A715-DA07C4178CBF}.Debug|x86.Build.0 = Debug|x86
{41CAF3C0-DDF9-4A65-A715-DA07C4178CBF}.DebugInstallers|Any CPU.ActiveCfg = Debug|x86
{41CAF3C0-DDF9-4A65-A715-DA07C4178CBF}.DebugInstallers|Any CPU.Build.0 = Debug|x86
{41CAF3C0-DDF9-4A65-A715-DA07C4178CBF}.DebugInstallers|x86.ActiveCfg = Debug|x86
{41CAF3C0-DDF9-4A65-A715-DA07C4178CBF}.DebugInstallers|x86.Build.0 = Debug|x86
{41CAF3C0-DDF9-4A65-A715-DA07C4178CBF}.Release|Any CPU.ActiveCfg = Release|x86
{41CAF3C0-DDF9-4A65-A715-DA07C4178CBF}.Release|x86.ActiveCfg = Release|x86
{41CAF3C0-DDF9-4A65-A715-DA07C4178CBF}.Release|x86.Build.0 = Release|x86
{41CAF3C0-DDF9-4A65-A715-DA07C4178CBF}.ReleaseInstallers|Any CPU.ActiveCfg = Release|x86
{41CAF3C0-DDF9-4A65-A715-DA07C4178CBF}.ReleaseInstallers|Any CPU.Build.0 = Release|x86
{41CAF3C0-DDF9-4A65-A715-DA07C4178CBF}.ReleaseInstallers|x86.ActiveCfg = Release|x86
{41CAF3C0-DDF9-4A65-A715-DA07C4178CBF}.ReleaseInstallers|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -121,5 +237,7 @@ Global
GlobalSection(NestedProjects) = preSolution
{C5A4CDC3-849C-4166-BDC3-56BDB307126D} = {10A7E78C-0D11-40DD-AEC3-27C2C507A926}
{119216DE-FC7F-408A-9C2C-105874449E42} = {10A7E78C-0D11-40DD-AEC3-27C2C507A926}
{D38E92DB-48F9-40C3-9A6F-D76FBD07326E} = {10A7E78C-0D11-40DD-AEC3-27C2C507A926}
{41CAF3C0-DDF9-4A65-A715-DA07C4178CBF} = {10A7E78C-0D11-40DD-AEC3-27C2C507A926}
EndGlobalSection
EndGlobal

View File

@ -3,6 +3,7 @@
<appSettings>
<add key="NLogConfigFilePath" value="Configs/NLogConfig.xml" />
<add key="DefaultPageSize" value="20" />
<add key="WebsiteHttpPort" value="8800"/>
<add key="SwipeTimeGap" value="3" />
<add key="BugSubmissionEmailAddress" value="incoming+WattsC/FlexiTimeTrackerTool+24qrefn8e1urhl4iqct7we2jl@gitlab.com"/>
</appSettings>

View File

@ -0,0 +1,48 @@
using System;
using System.Web.Http;
using WindowsDataCenter.Helpers;
using Interfaces;
namespace WindowsDataCenter
{
[RoutePrefix("api/logs")]
public class LogsController:ApiController
{
private IRepository _repo;
private ILogger _logger;
public LogsController(IRepository repo, ILogger logger)
{
if (repo == null)
{
throw new ArgumentNullException(nameof(repo));
}
if (logger == null)
{
throw new ArgumentNullException(nameof(logger));
}
_repo = repo;
_logger = logger;
}
[HttpPost]
[Route("create")]
[CacheControl(MaxAge = 0)]
public IHttpActionResult CreateAndEditResultLog([FromBody] TimeLog log)
{
log.Source = LogSource.UI;
var resp = log.Id > 0 ? _repo.UpdateLog(log) : _repo.CreateLog(log);
return Ok(new {Id=log.Id, OperationResponse=resp});
}
[HttpDelete]
[Route("delete")]
[CacheControl(MaxAge = 0)]
public IHttpActionResult DeleteLog([FromBody] TimeLog log)
{
_logger.Info("Removing Log {0} for user id {1}", log.Id, log.UserId);
_repo.DeleteLog(log);
return Ok();
}
}
}

View File

@ -14,10 +14,12 @@ namespace WindowsDataCenter
{
private readonly IRepository _repo;
private readonly ILogger _logger;
/// <summary>
///
/// </summary>
/// <param name="repo"></param>
/// <param name="logger"></param>
public SwipeDataController(IRepository repo, ILogger logger)
{
if(repo == null) throw new ArgumentNullException(nameof(repo));
@ -36,24 +38,10 @@ namespace WindowsDataCenter
public IHttpActionResult PostData([FromBody] CardData cData)
{
int logId;
_repo.LogEventTime(new Identifier {UniqueId = cData.CardUId}, out logId);
_logger.Trace("Received new \"Swipe Event\" for UId: {0} at {1}", cData.CardUId, DateTime.UtcNow);
return
ResponseMessage(new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(logId.ToString())
});
}
/// <summary>
///
/// </summary>
/// <param name="log"></param>
/// <returns></returns>
[HttpPost]
[Route("manual")]
public IHttpActionResult ManuallyPostData([FromBody] ManualLog log)
{
throw new NotImplementedException();
var resp = _repo.LogEventTime(new Identifier {UniqueId = cData.CardUId}, out logId);
_logger.Trace("Received new \"Swipe Event\" for UId: {0} at {1}, direction is : {2}", cData.CardUId,
DateTime.UtcNow, resp.Direction);
return Ok(new {Id = logId, resp.Direction});
}
}
}

View File

@ -1,4 +1,7 @@
using System;
using System.Configuration;
using System.IO;
using System.Reflection;
using System.ServiceProcess;
using System.Threading;
using Interfaces;
@ -31,6 +34,12 @@ namespace WindowsDataCenter
protected override void OnStart(string[] args)
{
var configPath = string.Concat(System.Reflection.Assembly.GetEntryAssembly().Location, ".config");
//var configsDir = new Uri(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "configs")).LocalPath;
//var exeName = Assembly.GetEntryAssembly().ManifestModule.ScopeName;
//var appConfigPath = Path.Combine(configsDir, string.Format("{0}.config", exeName));
//AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", appConfigPath);
//var val = ConfigurationManager.AppSettings["TEST"];
//Initialise the Ninject system.
var ninjectInstance = NinjectHelper.GetInstance();
_logger = NinjectHelper.GetInstance().Get<ILogger>();
@ -40,12 +49,14 @@ namespace WindowsDataCenter
_mainWorkerThread = new Thread(MainWorkerThread)
{
IsBackground = false,
Name = "OWIN SELF HOST MAIN THREAD"
Name = "DATACENTER SELF HOST MAIN THREAD"
};
//TODO: use app.config for endpoint config.
var endpointPort = ConfigurationManager.AppSettings["WebsiteHttpPort"] ?? "8800";
try
{
_webApp = WebApp.Start<StartOwin>("http://*:8800");
var endpoint = string.Format("http://*:{0}", endpointPort);
_webApp = WebApp.Start<StartOwin>(endpoint);
}
catch (Exception ex)
{

View File

@ -5,7 +5,7 @@ echo "1 - %Directory%"
echo "1a - %SolutionDir%"
call :normalise "%Directory%"
start /wait "" "%Directory%" -xml "%SolutionDir%WindowsDataCenter\Minifier\MinifierConfig.xml"
start /wait /min "" "%Directory%" -xml "%SolutionDir%WindowsDataCenter\Minifier\MinifierConfig.xml"
GOTO :EOF

View File

@ -35,6 +35,27 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugInstallers|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\DebugInstallers\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DocumentationFile>bin\Debug\WindowsDataCenter.XML</DocumentationFile>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseInstallers|AnyCPU'">
<OutputPath>bin\ReleaseInstallers\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="DalSoft.WebApi.HelpPage, Version=0.0.7.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\DalSoft.WebApi.HelpPage.0.0.7.0\lib\net451\DalSoft.WebApi.HelpPage.dll</HintPath>
@ -151,6 +172,7 @@
<Compile Include="Controllers\CardsController.cs" />
<Compile Include="Configuration.cs" />
<Compile Include="Controllers\GroupController.cs" />
<Compile Include="Controllers\LogsController.cs" />
<Compile Include="Controllers\TimelogController.cs" />
<Compile Include="DefaultComponents\DefaultLogger.cs" />
<Compile Include="Helpers\CacheControlAttribute.cs" />
@ -199,6 +221,9 @@
<Content Include="www\css\bootstrap.min.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="www\css\knockout.contextmenu.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="www\favicon.ico">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
@ -220,6 +245,9 @@
<Content Include="www\js\bootstrap.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="www\js\knockout.contextmenu.js">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="www\spa.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>

View File

@ -3,7 +3,7 @@
/**
* Create a request URL - references apiEndpoints object to construct url with args, and optional callback url.
* @param {string} routePath
* @param {Array<Object<string>} params - Key, Value object detailing the param name (key) and value (value).
* @param {Array<Object<string>>} params - Key, Value object detailing the param name (key) and value (value).
* @param {boolean} requiresCallback - True - add callback function for JSONP/CORS.
* @param {boolean} isAbsolutePath - True, create a relative URL (without root).
* @returns {string} the url generated

View File

@ -0,0 +1,59 @@
/* knockout.contextmenu v1.0.0
Nicolás Escalante - nlante@gmail.com
Issues: https://github.com/nescalante/knockout.contextmenu/issues
License: MIT */
.context-menu {
position: absolute;
padding: 0;
margin: 0;
z-index: 1030;
background-color: #ffffff;
}
.context-menu ul {
line-height: 1.6;
padding: 0;
margin: 0;
border: 1px solid #dddddd;
box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.3);
}
.context-menu ul > li {
padding: 4px 20px;
margin: 0;
z-index: 1031;
list-style-type: none;
cursor: pointer;
white-space: nowrap;
color: #333333;
}
.context-menu ul > li:hover {
background-color: #eeeeee;
}
.context-menu ul > li.disabled,
.context-menu ul > li.disabled a {
color: #666666;
cursor: default;
}
.context-menu ul > li.checked:before {
position: absolute;
content: "\2713";
left: 7px;
}
.context-menu ul > li.with-url {
padding: 0;
}
.context-menu ul > li.with-url a {
display: block;
padding: 4px 20px;
text-decoration: none;
color: #333333;
}
.context-menu ul > li.separator {
margin: 4px 0;
padding: 0;
border-bottom: 1px solid #cccccc;
cursor: default;
}
.context-menu ul > li.separator:hover {
background-color: #ffffff;
}

View File

@ -4,16 +4,20 @@
<title>Flexi Time Data Viewer</title>
<link rel="shortcut icon" href="favicon.ico" />
<link rel="stylesheet preload" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet preload" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.6.1/css/bootstrap-datepicker3.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"/>
<!--<link rel="stylesheet preload" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.6.1/css/bootstrap-datepicker3.min.css"/>-->
<link href="spa.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<link href="css/knockout.contextmenu.css" rel="stylesheet" type="text/css"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/css/bootstrap-datetimepicker.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min.js" type="text/javascript"></script>
<script src="js/knockout.contextmenu.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sammy.js/0.7.6/sammy.js" type="text/javascript"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/momentjs/2.10.6/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.6.1/js/bootstrap-datepicker.js"></script>
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.6.1/js/bootstrap-datepicker.js"></script>-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/js/bootstrap-datetimepicker.min.js"></script>
</head>
<body data-bind="css: {footerBody: errorData() !== null}">
<nav class="navbar navbar-default">
@ -246,9 +250,6 @@
</div>
<br/>
<br/>
<!--<div class="row">
</div>-->
<div class="row">
<div class="col-md-3 col-xs-12">
<div id="datePickerContainer">
@ -259,7 +260,7 @@
<!-- main content panel. -->
<table class="table table-striped">
<thead>
<tr>
<tr data-bind="contextMenu: $root.createContextMenu">
<th>Day Of Week</th>
<!-- ko foreach: new Array($root.getTimeLogEntryArrayLength(MaxDailyLogCount)) -->
<th>In</th>
@ -271,24 +272,30 @@
<tbody>
<!-- ko foreach: TimeLogs-->
<tr>
<td class="valign" data-bind="text: DayOfWeek"></td>
<td class="valign" data-bind="text: DayOfWeek, contextMenu: $root.createContextMenu"></td>
<!-- ko foreach: Logs -->
<td class="valign" data-bind="text: $root.convertToDisplayTime(EventTime)"></td>
<td class="valign" data-bind="text: $root.convertToDisplayTime(EventTime), contextMenu: $root.editContextMenu"></td>
<!-- /ko -->
<!-- ko foreach: new Array($root.correctLogOffset($parent.MaxDailyLogCount)-LogCount)-->
<td class="valign"></td>
<td class="valign" data-bind="contextMenu: $root.createContextMenu"></td>
<!-- /ko -->
<td class="valign"data-bind="text: $root.convertToHours(DailyTotal)"></td>
<td class="valign" data-bind="text: $root.convertToHours(DailyTotal), contextMenu: $root.createContextMenu"></td>
</tr>
<!-- /ko -->
<tr>
<td class="valign" data-bind="attr:{colspan: $root.correctLogOffset(MaxDailyLogCount)+1}">Weekly Total</td>
<td class="valign" for="dailyHrsTotal" data-bind="text: $root.convertToHours(WeeklyTotal)"></td>
<td class="valign" data-bind="attr:{colspan: $root.correctLogOffset(MaxDailyLogCount)+1}, contextMenu: $root.createContextMenu">Weekly Total</td>
<td class="valign" for="dailyHrsTotal" data-bind="text: $root.convertToHours(WeeklyTotal), contextMenu: $root.createContextMenu"></td>
</tr>
</tbody>
</table>
</div>
</div>
<!--<menu type="context" id="manualLogsMenu">
<menu label="ManuallyCreateLogs">
<menuitem label="Edit" onclick="$root.editLogClick()"/>
<menuitem label="Create" onlcick="$root.createLogClick()"/>
</menu>
</menu>-->
</div>
<div id="aboutDialog" class="modal fade" role="dialog" data-bind="with: appDetails">
@ -318,8 +325,42 @@
</div>
</div>
</div>
<footer data-bind="with: errorData, css: {footer: $root.errorData()!==null}">
<div id="manualLogDialog" class="modal fade" role="dialog" data-bind="with: manualLog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4>MANUAL EDIT</h4>
</div>
<div class="modal-body" style="height: 300px;">
<form action="#manualLog" method="post" class="form-group">
<input type="hidden" name="Id" data-bind="value: Id"/>
<div class="form-group">
<div class="input-group date" id="datetimepicker1">
<input type="text" class="form-control" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
<div>
<div class="input-group">
<select data-bind="options: $root.possibleLogDirections,
optionsText: function(item) { return item.Text },
optionsValue: function(item){ return item.value },
value: Direction,
optionsCaption: 'Choose...'"></select>
</div>
</div>
<br/>
<button type="submit" class="btn btn-primary">Submit</button>
<button type="button" class="btn btn-secondary close" data-dismiss="modal">Cancel</button>
</form>
</div>
</div>
</div>
</div>
<footer data-bind="with: errorData, css: {footer: $root.errorData()!==null}">
<div class="container">
<!-- Alert/Error banner-->
<div class="alert alert-danger alert-dismissible" role="alert">
@ -331,8 +372,8 @@
<div data-bind="text: errorDate"></div>
</div>
</div>
</footer>
<script src="spa.min.js" type="text/javascript"></script>
</footer>
<script src="Helpers.js" type="text/javascript"></script>
<script src="spa.js" type="text/javascript"></script>
</body>
</html>

View File

@ -0,0 +1,362 @@
/* knockout.contextmenu v1.0.0
Nicolás Escalante - nlante@gmail.com
Issues: https://github.com/nescalante/knockout.contextmenu/issues
License: MIT */
(function (undefined) {
"use strict";
// client
if (typeof ko !== undefined + "") {
bindContextMenu(ko);
}
// node
if (typeof module !== undefined + "" && module.exports && typeof require !== undefined + "") {
bindContextMenu(require("knockout"));
}
function bindContextMenu(ko) {
var currentMenu;
var elementMapping = [];
var utils = ko.utils;
var registerEvent = utils.registerEventHandler;
var isObservable = ko.isObservable;
registerEvent(document, "click", function (event) {
var button = event.which || event.button;
if (!event.defaultPrevented && button < 2) {
hideCurrentMenu();
}
});
utils.contextMenu = {
getMenuFor: function (element, event) {
var result = getMapping(element);
if (result) {
return result.get(event);
}
},
openMenuFor: function (element, event) {
var result = getMapping(element);
if (result) {
return result.open(event);
}
},
};
ko.bindingHandlers.contextMenu = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var eventsToHandle = valueAccessor() || {};
var allBindings = allBindingsAccessor();
var defaultClass = allBindings.contextMenuClass || "context-menu";
var activeElement;
// bind on click? bind on context click?
if (allBindings.bindMenuOnClick) {
registerEvent(element, "click", openMenu);
}
if (allBindings.bindMenuOnContextMenu === undefined || allBindings.bindMenuOnContextMenu) {
registerEvent(element, "contextmenu", openMenu);
}
elementMapping.push({
element: element,
get: function () {
return activeElement;
},
open: openMenu,
hide: function () {
if (activeElement) {
activeElement.hide();
}
}
});
function mouseX(evt) {
if (evt.pageX) {
return evt.pageX;
} else if (evt.clientX) {
return evt.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft);
} else {
return null;
}
}
function mouseY(evt) {
if (evt.pageY) {
return evt.pageY;
} else if (evt.clientY) {
return evt.clientY + (document.documentElement.scrollTop || document.body.scrollTop);
} else {
return null;
}
}
function openMenu(event) {
activeElement = getMenu(event);
var menuElement = activeElement.element;
hideCurrentMenu();
if (menuElement) {
// make visibility hidden, then add to DOM so that we can get the height/width of the menu
menuElement.style.visibility = "hidden";
(document.body || document).appendChild(menuElement);
// set location
if (event) {
var bottomOfViewport = window.innerHeight + window.pageYOffset;
var rightOfViewport = window.innerWidth + window.pageXOffset;
if (mouseY(event) + menuElement.offsetHeight > bottomOfViewport) {
menuElement.style.top = 1 * (bottomOfViewport - menuElement.offsetHeight - 10) + "px";
} else {
menuElement.style.top = mouseY(event) + "px";
}
if (mouseX(event) + menuElement.offsetWidth > rightOfViewport) {
menuElement.style.left = 1 * (rightOfViewport - menuElement.offsetWidth - 10) + "px";
} else {
menuElement.style.left = mouseX(event) + "px";
}
event.preventDefault();
event.stopPropagation();
} else {
menuElement.style.top = (element.offsetTop + element.offsetHeight) + "px";
menuElement.style.left = (element.offsetLeft + element.offsetWidth) + "px";
}
// now set to visible
menuElement.style.visibility = "";
}
// replace current menu with the recently created
currentMenu = menuElement;
return activeElement;
}
function getMenu(event) {
var menu;
var hasChecks = false;
var elements = [];
var actions = [];
var items = [];
var props = Object.keys(
ko.isObservable(eventsToHandle) ?
eventsToHandle() :
eventsToHandle
);
props.forEach(function (eventNameOutsideClosure) {
pushItem(eventNameOutsideClosure);
});
if (elements.length) {
menu = document.createElement("div");
menu.className = defaultClass;
// you may need padding to menus that has checks
menu.innerHTML = "<ul class=\"" + (hasChecks ? "has-checks" : "") + '">' +
elements.join("") +
"</ul>";
// map items to actions
elements.forEach(function (item, index) {
registerEvent(menu.children[0].children[index], "click", function (event) {
var result = actions[index](viewModel, event);
if (!result && event) {
event.preventDefault();
}
});
});
}
return {
element: menu,
items: items,
open: openMenu,
hide: function () {
if (menu && menu.parentNode) {
menu.parentNode.removeChild(menu);
}
currentMenu = null;
},
};
function pushItem(eventName) {
var item = getMenuProperties(eventName);
var classes = [];
var id = "";
var liHtml;
if (item.isVisible) {
hasChecks = hasChecks || item.isBoolean;
if (item.id) {
id = item.id;
}
// set css classes
if (item.isChecked) {
classes.push("checked");
}
if (item.isDisabled) {
classes.push("disabled");
}
if (item.isSeparator) {
classes.push("separator");
}
if (item.url) {
classes.push("with-url");
}
liHtml = "<li " + (id ? ('id="' + id + '" ') : "") +
' class="' + classes.join(" ") + '">' +
item.html +
"</li>";
elements.push(liHtml);
actions.push(item.action);
}
items.push(item);
}
}
function getMenuProperties(eventName) {
var text = "";
var html = "";
var currentEvent = ko.isObservable(eventsToHandle) ?
eventsToHandle()[eventName] :
eventsToHandle[eventName];
var item = currentEvent || {};
var id = item.id;
var url = (isObservable(item.url) ? item.url() : item.url);
var isVisible = item.visible === undefined || item.visible === null ||
(isObservable(item.visible) && item.visible()) ||
(!isObservable(item.visible) && !!item.visible);
var isChecked = false;
var isEnabled = !item.disabled ||
(isObservable(item.disabled) && !item.disabled()) ||
(isObservable(item.enabled) && item.enabled()) ||
(!isObservable(item.enabled) && !!item.enabled);
var isBoolean = false;
var isDisabled = !isEnabled;
var isSeparator = !!currentEvent.separator;
if (!isSeparator) {
text = isObservable(item.text) ? item.text() : item.text;
if (!text) {
text = eventName;
}
if (url) {
html = '<a href="' + url + '">' + text + "</a>";
} else {
html = text;
}
}
if ((isObservable(item) && typeof item() === "boolean") ||
(isObservable(item.action) && typeof item.action() === "boolean")) {
isBoolean = true;
if ((item.action && item.action()) ||
(typeof item === "function" && item())) {
isChecked = true;
}
}
return {
html: html,
text: text,
url: url,
id: id,
isVisible: isVisible,
isChecked: isChecked,
isEnabled: isEnabled,
isDisabled: isDisabled,
isBoolean: isBoolean,
isSeparator: isSeparator,
action: action
};
function action(viewModel, event) {
var error = eventName + " option must have an action or an url.";
if (isDisabled) {
return false;
}
// check if option is a boolean
if (isObservable(item) && typeof item() === "boolean") {
item(!item());
}
// is an object? well, lets check it properties
else if (typeof item === "object") {
// check if has an action or if its a separator
if (!item.action && !url && !isSeparator) {
throw error;
}
// evaluate action
else if (item.action) {
if (isObservable(item.action) && typeof item.action() === "boolean") {
item.action(!item.action());
} else {
item.action(viewModel, event);
}
}
}
// its not an observable, should be a function
else if (typeof item === "function") {
item(viewModel, event);
}
// nothing to do with this
else {
throw error;
}
return true;
}
}
}
};
function hideCurrentMenu() {
if (currentMenu && currentMenu.parentNode) {
currentMenu.parentNode.removeChild(currentMenu);
}
currentMenu = null;
}
function getMapping(element) {
var i = 0;
for (; i < elementMapping.length; i++) {
if (elementMapping[i].element === element) {
return elementMapping[i];
}
}
}
}
})();

View File

@ -12,7 +12,7 @@
}
}
.bootstrap-datetimepicker-widget tr:hover {
background-color: #808080;
background-color: #a9a9a9;
}
.datepicker tr.highlight {
background: #eeeeee;

View File

@ -1,7 +1,12 @@
function DataVM() {
"use strict";
var self = this;
self.helpers = new Helpers();
self.menuOptions = ["Home"];
self.possibleLogDirections = ko.observableArray([
{ Text: "In", value: 1 },
{ Text: "Out", value: 2 }
]),
self.chosenMenuItemId = ko.observable();
self.appDetails = ko.observable(null);
self.userList = ko.observable(null);
@ -10,8 +15,10 @@
self.userTimeLogData = ko.observable(null);
self.unassignedCardData = ko.observable(null);
self.chosenTimeLogUserId = -1;
self.selectedTimeLogDate = ko.observable(null);
self.selectedCalendarWeek = ko.observable(0);
self.errorData = ko.observable(null);
self.manualLog = ko.observable(null);
self.apiEndpoints = {
root: "http://localhost:8800",
getUserList: "/api/users",
@ -20,7 +27,9 @@
getTimeLogs: "/api/timelogs",
getUnassignedCards: "/api/cards/unassigned",
getGroups: "/api/groups",
getAppDetails: "/api/app"
getAppDetails: "/api/app",
manualLogsCreate: "/api/logs/create",
manualLogsDelete: "/api/logs/delete"
};
self.uiPages = {
users: "users",
@ -39,7 +48,7 @@
}
var url = "timelogs" + "/" + userId;
if (args) {
url = self.createRequestUrl(url, args, false, false);
url = self.helpers.createRequestUrl(url, args, false, false);
}
location.hash = url;
};
@ -52,86 +61,11 @@
};
self.errorData(errDat);
}
self.processRequestFailure = function (xmlHttpRequest, textStatus, errorThrown) {
if (xmlHttpRequest.readyState === 4) {
return {
errorCode: xmlHttpRequest.status,
errorMessage: xmlHttpRequest.statusText,
errorSource: ""
};
}
else if (xmlHttpRequest.readyState === 0) {
return {
errorCode: xmlHttpRequest.status,
errorMessage: "Network Error - Is the server available?",
errorSource: ""
};
}
else {
return {
errorCode: xmlHttpRequest.status,
errorMessage: "Unknown Error",
errorSource: ""
};
}
};
/**
* Create a request URL - references apiEndpoints object to construct url with args, and optional callback url.
* @param {string} routePath
* @param {Array<Object<string>} params - Key, Value object detailing the param name (key) and value (value).
* @param {boolean} requiresCallback - True - add callback function for JSONP/CORS.
* @param {boolean} isAbsolutePath - True, create a relative URL (without root).
* @returns {string} the url generated
* @example
* createRequestUrl("/api/endpoint", [{key:"param", value:"value"}], true, false);
* returns: "http://192.168.2.2/api/endpoint?param=value&callback=?"
*/
self.createRequestUrl = function (routePath, params, requiresCallback, isAbsoluteUrl) {
var appender = "?";
var url = "";
if (isAbsoluteUrl) {
url = self.apiEndpoints.root;
}
url = url + routePath;
if (params !== undefined
&& params !== null) {
if (params.length > 0) {
for (var i = 0; i < params.length; i++) {
url += appender + params[i].key + "=" + params[i].value;
appender = "&";
}
}
}
if (requiresCallback) {
url += appender + "callback=?";
}
return url;
};
/**
* Function to redirect to a page in the sammy.js eco system.
* Relies on "pagedestination" tag in the html. This is a button click handler.
* @param {Object<unknown>} data - dunno?
* @param {Object<buttonhandle>} event - handle to the button that was clicked.
* @returns {nothing} - redirects to the url referenced by the pageDestination tag.
*/
self.returnButtonClick = function (data, event) {
var target = null;
if (event.target) target = event.target;
else if (event.srcElement) target = event.srcElement;
var destination = "";
if (target != null) {
for (var i = 0; i < target.attributes.length; i++) {
if (target.attributes[i].nodeName === "pagedestination") {
destination = target.attributes[i].value;
break;
}
}
var destination = self.helpers.getPageDestination(data, event);
if (destination !== "") {
self.goToMenuOption(destination); //redirect to whereever the button is telling us to go..
}
} else {
console.log("target is null, going nowhere");
}
};
self.convertToHours = function (value) {
var hrs = value / 60;
@ -146,24 +80,24 @@
var date = new Date(dateValue);
return date.getHours() + ":" + self.padNumber(date.getMinutes());
};
self.correctLogOffset = function (logCount) {
self.correctLogOffset = function(logCount) {
if (logCount % 2 !== 0) {
logCount += 1;
}
return logCount;
}
self.round = function (value, decimals) {
};
self.round = function(value, decimals) {
return parseFloat(Math.round(value * 100) / 100).toFixed(decimals);
}
};
self.getTimeLogEntryArrayLength = function(maxDailyLogs) {
return Math.round(maxDailyLogs/2);
};
self.padNumber = function(number) {
return (number < 10 ? '0' : '') + number;
}
return (number < 10 ? "0" : "") + number;
};
self.convertToDisplayDateTime = function (dateValue) {
var date = new Date(dateValue); // dd MM YY HH:mm:ss e.g.: 01 Mar 17 17:34:02
return date.getDay() + " "
return date.getDate() + " "
+ date.toLocaleString("en-us", { month: "long" }) + " "
+ (date.getYear()-100) + " "
+ self.padNumber(date.getHours()) + ":"
@ -215,7 +149,7 @@
value: data
}
];
var url = self.createRequestUrl("users", args, false, false);
var url = self.helpers.createRequestUrl("users", args, false, false);
location.hash = url;
console.log(url);
};
@ -230,38 +164,53 @@
value: pageNumber
}
];
var url = self.createRequestUrl("users", args, false, false);
var url = self.helpers.createRequestUrl("users", args, false, false);
location.hash = url;
console.log(url);
};
self.initDatePicker = function (selectedDate) {
$("#weeklyDatePicker").datepicker({
weekStart: 1,
maxViewMode: 2,
endDate: "+0d",
todayBtn: "linked",
format: "yyyy-mm-dd",
todayHighlight: true,
calendarWeeks: true
});
if (!selectedDate) {
selectedDate = new Date();
} else {
selectedDate = new Date(selectedDate);
}
$("#weeklyDatePicker").datepicker("setDate", selectedDate);
moment.locale("en", { week: { dow: 1 } });
$("#weeklyDatePicker").datetimepicker({
format: "DD/MM/YYYY",
inline: true,
showTodayButton: true,
calendarWeeks: true,
maxDate: "now",
date: selectedDate
});
};
self.assignHandler = function () {
self.assignHandler = function() {
var elem = $("#weeklyDatePicker")[0];
var data = jQuery.hasData(elem) && jQuery._data(elem);
if (!data.events.changeDate) {
$("#weeklyDatePicker").on("changeDate", function (e) {
var kk = e.date;
self.selectedCalendarWeek(moment(kk).isoWeek());
self.goToTimeLogs(self.chosenTimeLogUserId, null, [{ key: "selectedDate", value: moment(kk).format("MM-DD-YYYY") }]);
if (!data.events) {
$("#weeklyDatePicker")
.on("dp.change",
function(e) {
var value = e.date;
self.selectedCalendarWeek(moment(value).isoWeek());
self.goToTimeLogs(self.chosenTimeLogUserId,
null,
[{ key: "selectedDate", value: moment(value).format("MM-DD-YYYY") }]);
});
}
};
self.assignUpdateHandler = function() {
var elem = $("#datetimepicker1")[0];
var data = jQuery.hasData(elem) && jQuery._data(elem);
if (!data.events) {
$("#datetimepicker1")
.on("dp.change",
function(e) {
var value = e.date.toISOString();
self.manualLog().EventTime = value;
});
}
};
self.getUserList = function (pageSize, pageNumber, groupId) {
var args = null;
if (pageSize && pageNumber) {
@ -282,52 +231,52 @@
value: groupId
}];
}
var url = self.createRequestUrl(self.apiEndpoints.getUserList, args, false);
var url = self.helpers.createRequestUrl(self.apiEndpoints.getUserList, args, false);
$.getJSON(url, function (res) {
self.userList(res);
$('[data-toggle="tooltip"]').tooltip();
}).fail(function (response, status, error) {
console.log("error - getusers");
var errObj = self.processRequestFailure(response, status, error);
var errObj = self.helpers.processRequestFailure(response, status, error);
self.assignErrorObject(errObj.errorCode, errObj.errorMessage, "getUserList");
});
};
self.getAppDetails = function() {
var url = self.createRequestUrl(self.apiEndpoints.getAppDetails, null, false, false);
var url = self.helpers.createRequestUrl(self.apiEndpoints.getAppDetails, null, false, false);
$.getJSON(url, function (res) {
self.appDetails(res);
}).fail(function (response, status, error) {
console.log("error - getusers");
var errObj = self.processRequestFailure(response, status, error);
var errObj = self.helpers.processRequestFailure(response, status, error);
self.assignErrorObject(errObj.errorCode, errObj.errorMessage, "getUserList");
});
};
self.searchUsers = function(query) {
var url = self.createRequestUrl(self.apiEndpoints.getUserList,
var url = self.helpers.createRequestUrl(self.apiEndpoints.getUserList,
[{ key: "query", value: query }], false, false);
$.getJSON(url,
function(res) {
self.userList(res);
}).fail(function(resp, status, error) {
self.goToMenuOption(self.uiPages.home());
var errObj = self.processRequestFailure(resp, status, error);
var errObj = self.helpers.processRequestFailure(resp, status, error);
self.assignErrorObject(errObj.errorCode, errObj.errorMessage, "searchUsers");
}
);
};
self.getUserDetails = function (userId) {
var url = self.createRequestUrl(self.apiEndpoints.getUserDetails + "/" + userId, null, false);
var url = self.helpers.createRequestUrl(self.apiEndpoints.getUserDetails + "/" + userId, null, false);
$.getJSON(url, function (res) {
self.chosenUserDetails(res);
}).fail(function (resp, status, error) {
console.log("error - getuserdetails");
var errObj = self.processRequestFailure(resp, status, error);
var errObj = self.helpers.processRequestFailure(resp, status, error);
self.assignErrorObject(errObj.errorCode, errObj.errorMessage, "getUserDetails");
self.goToMenuOption(self.uiPages.home());
});
};
self.submitChangedUser = function (user) {
var url = self.apiEndpoints.editUser;
var url = self.helpers.createRequestUrl(self.apiEndpoints.editUser, null, false, false);
$.post(url, user, function () {
}, "json")
.done(function () {
@ -335,7 +284,7 @@
self.goToMenuOption(self.uiPages.home());
})
.fail(function (resp, status, error) {
var errObj = self.processRequestFailure(resp, status, error);
var errObj = self.helpers.processRequestFailure(resp, status, error);
self.assignErrorObject(errObj.errorCode, errObj.errorMessage, "submitChangedUser");
self.chosenUserDetails(null);
self.goToMenuOption(self.uiPages.home());
@ -346,7 +295,7 @@
if (selectedDate) {
urlArgs.push({ key: "selectedDate", value: selectedDate });
}
var url = self.createRequestUrl(self.apiEndpoints.getTimeLogs,
var url = self.helpers.createRequestUrl(self.apiEndpoints.getTimeLogs,
urlArgs,
false);
$.getJSON(url, function (res) {
@ -355,33 +304,103 @@
self.assignHandler();
}).fail(function (resp, status, error) {
console.log("error - getuserdetails");
var errObj = self.processRequestFailure(resp, status, error);
var errObj = self.helpers.processRequestFailure(resp, status, error);
self.assignErrorObject(errObj.errorCode, errObj.errorMessage, "getTimeLogData");
self.goToMenuOption(self.uiPages.home()); //go home.
});
};
self.getUnassignedCardData = function () {
var url = self.createRequestUrl(self.apiEndpoints.getUnassignedCards, null, false);
var url = self.helpers.createRequestUrl(self.apiEndpoints.getUnassignedCards, null, false);
$.getJSON(url, function (res) {
self.unassignedCardData(res);
}).fail(function (resp, status, error) {
console.log("error - getuserdetails");
var errObj = self.processRequestFailure(resp, status, error);
var errObj = self.helpers.processRequestFailure(resp, status, error);
self.assignErrorObject(errObj.errorCode, errObj.errorMessage, "getUnassignedCardData");
});
};
self.getGroups = function (successFunc) {
var url = self.createRequestUrl(self.apiEndpoints.getGroups, null, false);
var url = self.helpers.createRequestUrl(self.apiEndpoints.getGroups, null, false);
return $.getJSON(url, function (res) {
successFunc(res);
//self.chosenUserDetails().Groups = res;
//self.chosenUserDetails.valueHasMutated();
}).fail(function (resp, status, error) {
console.log("error - getGroups");
var errObj = self.processRequestFailure(resp, status, error);
var errObj = self.helpers.processRequestFailure(resp, status, error);
self.assignErrorObject(errObj.errorCode, errObj.errorMessage, "getGroups");
});
};
self.createManualLog = function(newLog) {
var url = self.helpers.createRequestUrl(self.apiEndpoints.manualLogsCreate, null, false, false);
$.post(url, newLog, function () {
}, "json")
.done(function () {
self.manualLog(null);
$('#manualLogDialog').modal("hide");
self.goToMenuOption(self.uiPages.home());
})
.fail(function (resp, status, error) {
var errObj = self.helpers.processRequestFailure(resp, status, error);
self.assignErrorObject(errObj.errorCode, errObj.errorMessage, "createManualLog");
self.chosenUserDetails(null);
self.goToMenuOption(self.uiPages.home());
});
};
self.deleteManualLog = function (logToDelete) {
var url = self.helpers.createRequestUrl(self.apiEndpoints.manualLogsDelete, null, false, false);
$.ajax({
url: url,
type: "DELETE",
data: logToDelete,
success: function (result) {
console.log("successfully deleted .." + result);
self.goToMenuOption(self.uiPages.home());
}
});
};
self.createContextMenu = ko.observableArray([
{ text: "Create", action: createlog }
]);
self.editContextMenu = ko.observableArray([
{ text: "Create", action: createlog },
{ text: "Edit", action: editlog },
{ text: "Delete", action: deleteLog }
]);
function editlog (data) {
self.manualLog(data);
$('#manualLogDialog').modal("show");
$('#datetimepicker1').datetimepicker({
format: "YYYY-DD-MM HH:mm:ss",
date: new Date(data.EventTime),
minDate: moment(new Date(data.EventTime)).startOf('week'),
maxDate: moment(new Date(data.EventTime)).endOf('week')
});
self.assignUpdateHandler();
};
function createlog(data) {
self.manualLog({
CalendarWeek:-1,
Direction:-1,
EventTime: new Date().toISOString(),
Id: -1,
IdentifierId: -1,
UserId: self.chosenTimeLogUserId,
Year: 0
});
$('#manualLogDialog').modal("show");
$('#datetimepicker1').datetimepicker({
format: "YYYY-DD-MM HH:mm:ss",
minDate: moment(self.selectedTimeLogDate()).startOf("week"),
maxDate: moment(self.selectedTimeLogDate()).endOf("week")
});
self.assignUpdateHandler();
};
function deleteLog(data) {
if (confirm("Are you sure you want to delete this log?")) {
self.deleteManualLog(data);
}
};
Sammy(function () {
this.get("#users", function () {
var query = this.params.query;
@ -389,9 +408,11 @@
var pageNumber = this.params.pageNumber;
var groupId = this.params.groupId;
self.chosenMenuItemId("Home");
self.groupsList(null);
self.chosenUserDetails(null);
self.userList(null);
self.userTimeLogData(null);
self.manualLog(null);
if (self.appDetails() === null) {
self.getAppDetails();
}
@ -405,18 +426,28 @@
});
this.get("#userData/:userId", function () {
self.chosenMenuItemId("Data");
self.groupsList(null);
self.chosenUserDetails(null);
self.userList(null);
self.getUserDetails(this.params.userId);
self.userTimeLogData(null);
self.manualLog(null);
self.getUserDetails(this.params.userId);
self.getUnassignedCardData();
});
this.get("#timelogs/:userId", function () {
var selectedDate = this.params.selectedDate;
self.chosenMenuItemId("Other");
self.userList(null);
self.chosenUserDetails(null);
if (this.params.selectedDate) {
self.selectedTimeLogDate(this.params.selectedDate);
} else {
self.selectedTimeLogDate(new Date());
}
self.chosenTimeLogUserId = this.params.userId;
self.getTimeLogData(this.params.userId, selectedDate);
self.chosenMenuItemId("Other");
self.groupsList(null);
self.chosenUserDetails(null);
self.userList(null);
self.userTimeLogData(null);
self.manualLog(null);
self.getTimeLogData(this.params.userId, self.selectedTimeLogDate());
});
this.get("#newUser", function () {
self.chosenMenuItemId("newUser");
@ -455,14 +486,21 @@
self.submitChangedUser(self.chosenUserDetails());
return false;
});
this.post("#manualLog",
function() {
self.createManualLog(self.manualLog());
$('#manualLogDialog').modal("hide");
//self.goToTimeLogs(self.chosenTimeLogUserId, null, [{ key: "selectedDate", value: self.selectedTimeLogDate() }]);
});
//default route (home page)
this.get("", function () { this.app.runRoute("get", "#" + self.uiPages.home()) });
}).run();
};
ko.applyBindings(new DataVM());
$(document).on("mouseenter", ".datepicker-days tbody tr", function () {
$(this).addClass('highlight');
});
$(document).on("mouseleave", ".datepicker-days tbody tr", function () {
$(this).removeClass('highlight');
});
//$(document).on("mouseenter", ".datepicker-days tbody tr", function () {
// $(this).addClass("highlight");
//});
//$(document).on("mouseleave", ".datepicker-days tbody tr", function () {
// $(this).removeClass("highlight");
//});

View File

@ -1 +0,0 @@
.table td.fit,.table th.fit{white-space:nowrap;width:1%}.table>tbody>tr>td.valign{vertical-align:middle}@media(max-width:576px){ul>li>a.indent-nav-xs{padding-left:50px}}.bootstrap-datetimepicker-widget tr:hover{background-color:#808080}.datepicker tr.highlight{background:#eee;cursor:pointer}.footer{position:absolute;bottom:0;width:100%;height:132px}.footerBody{margin-bottom:132px}

File diff suppressed because one or more lines are too long

View File

@ -32,6 +32,26 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DebugInstallers|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\DebugInstallers\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ReleaseInstallers|AnyCPU'">
<OutputPath>bin\ReleaseInstallers\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll</HintPath>