This commit is contained in:
2026-04-17 14:55:32 -04:00
commit bc3ac1d4c9
18017 changed files with 4371742 additions and 0 deletions

View File

@@ -0,0 +1 @@
12

View File

@@ -0,0 +1 @@
12

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace DTS.Slice.Users
{
public partial class ChallengeDialog : Form
{
public ChallengeDialog()
{
InitializeComponent();
}
}
}

View File

@@ -0,0 +1,38 @@
using System.ComponentModel;
using Users.UserSettings;
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users.UserSettings
{
/// <summary>
/// this class overrides the DisplayNameAttribute to provide a translated string name, and also
/// to allow us to use an enum to create the attribute
/// to be translated a string resource should exist in the form of PropertyName_DisplayName
/// otherwise ##DisplayNameNotFound## will be returned
/// </summary>
public class DisplayAttributeEx : DisplayNameAttribute
{
private readonly PropertyEnums.PropertyIds _propertyId;
private readonly string _propertyIdString = null;
public DisplayAttributeEx(PropertyEnums.PropertyIds propertyId)
{
_propertyId = propertyId;
}
public DisplayAttributeEx(string propertyId)
{
_propertyIdString = propertyId;
}
public override string DisplayName
{
get
{
if (!string.IsNullOrWhiteSpace(_propertyIdString))
{
return StringResources.ResourceManager.GetString(_propertyIdString + "_DisplayName") ?? @"##DisplayNameNotFound##" + _propertyIdString;
}
return StringResources.ResourceManager.GetString(_propertyId + "_DisplayName") ?? @"##DisplayNameNotFound##" + _propertyId;
}
}
}
}

View File

@@ -0,0 +1,19 @@
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users
{
public class UIItemHelper
{
public long UIItemId { get; private set; }
public string UIItemName { get; private set; }
public bool IsVisible { get; private set; }
public short Permission { get; private set; }
public UIItemHelper(long uiItemId, short permission, bool visible, string uiItemName)
{
UIItemId = uiItemId;
Permission = permission;
IsVisible = visible;
UIItemName = uiItemName;
}
}
}

View File

@@ -0,0 +1,588 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="DefaultPostTriggerSeconds_Description" xml:space="preserve">
<value>ポストトリガー 記録時間(サーキュラーバッファーモード)または記録時間(レコーダーモード)の設定です。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultPostTriggerSeconds_DisplayName" xml:space="preserve">
<value>ポストトリガー 記録時間 / 記録時間 の既定値(秒)</value>
</data>
<data name="DefaultTestSampleRate_Description" xml:space="preserve">
<value>サンプルレート(sps)の設定。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultTestSampleRate_DisplayName" xml:space="preserve">
<value>サンプルレートの既定値(sps)</value>
</data>
<data name="DefaultTestSettings" xml:space="preserve">
<value>Test settings</value>
</data>
<data name="DefaultUploadEnabled" xml:space="preserve">
<value>Upload</value>
</data>
<data name="test" xml:space="preserve">
<value>試験</value>
</data>
<data name="ArmChecklistRequiredIfTOM_Description" xml:space="preserve">
<value>この項目をチェックすると、TOMが存在する場合には「アーム直前診断を使う」のオンオフにかかわらずARM直前診断を実行します。</value>
</data>
<data name="ArmChecklistRequiredIfTOM_DisplayName" xml:space="preserve">
<value>TOMが存在する場合はARM直前診断を実行する (推奨)</value>
</data>
<data name="ArmTriggerDiagnosticsRunOnNextStep_Description" xml:space="preserve">
<value>ダイアグのステップが選択されたらすぐにユーザの入力を待たずに全チャンネルのダイアグを開始します</value>
</data>
<data name="ArmTriggerDiagnosticsRunOnNextStep_DisplayName" xml:space="preserve">
<value>ダイアグのステップが選択されたらすぐに全チャンネルのダイアグを開始する</value>
</data>
<data name="DefaultAllowMissingSensors_Description" xml:space="preserve">
<value>すべてのセンサがみつからない場合に試験を続行できるかの設定。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultAllowMissingSensors_DisplayName" xml:space="preserve">
<value>センサーが見つからない状態を許可</value>
</data>
<data name="DefaultRequireSensorIdFound_Description" xml:space="preserve">
<value>この項目がチェックされていると、センサID照合の時にセンサーIDの登録されているセンサのマニュアルアサインは不可能になります。</value>
</data>
<data name="DefaultRequireSensorIdFound_DisplayName" xml:space="preserve">
<value>センサーIDが登録されている場合はIDを認識しないと進めない</value>
</data>
<data name="DefaultArmCheckListStep_Description" xml:space="preserve">
<value>アーム直前診断を実行するかどうか。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultArmCheckListStep_DisplayName" xml:space="preserve">
<value>アーム直前診断を使う</value>
</data>
<data name="DefaultCheckListBatteryVoltageCheck_Description" xml:space="preserve">
<value>アーム直前診断でバッテリー電圧の診断をするかどうか。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultCheckListBatteryVoltageCheck_DisplayName" xml:space="preserve">
<value>バッテリー電圧診断</value>
</data>
<data name="DefaultCheckListInputVoltageCheck_Description" xml:space="preserve">
<value>アーム直前診断で外部電源電圧の診断をするかどうか。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultCheckListInputVoltageCheck_DisplayName" xml:space="preserve">
<value>外部電源電圧診断</value>
</data>
<data name="DefaultCheckListMustPass_Description" xml:space="preserve">
<value>この項目がチェックされていると、アーム直前診断ですべてがパスしないとARMができません。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultCheckListMustPass_DisplayName" xml:space="preserve">
<value>全ユニットがアーム直前診断をパスすることを要求</value>
</data>
<data name="DefaultCheckListSensorIdCheck_Description" xml:space="preserve">
<value>アーム直前診断でセンサIDの照合をするかどうか。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultCheckListSensorIdCheck_DisplayName" xml:space="preserve">
<value>センサーID照合</value>
</data>
<data name="DefaultCheckListSquibResistanceCheck_Description" xml:space="preserve">
<value>アーム直前診断でスクイブ抵抗値のチェックをするかどうか。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultCheckListSquibResistanceCheck_DisplayName" xml:space="preserve">
<value>スクイブ抵抗診断(推奨)</value>
</data>
<data name="DefaultCheckListTriggerStartCheck_Description" xml:space="preserve">
<value>この項目サポートされていませんのではチェックをしないでください</value>
</data>
<data name="DefaultCheckListTriggerStartCheck_DisplayName" xml:space="preserve">
<value>(この項目はチェックしないでください)</value>
</data>
<data name="DefaultDownloadAll_Description" xml:space="preserve">
<value>全記録時間のダウンロードを実行する場合にチェックします。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultDownloadAll_DisplayName" xml:space="preserve">
<value>全記録時間をダウンロードする</value>
</data>
<data name="DefaultDownloadROI_Description" xml:space="preserve">
<value>指定時間(ROI)のダウンロードを実行する場合にチェックします。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultDownloadROI_DisplayName" xml:space="preserve">
<value>指定時間(ROI)をダウンロードする</value>
</data>
<data name="DefaultExport_Description" xml:space="preserve">
<value>データのエクスポートを実行する場合にチェックします。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultExport_DisplayName" xml:space="preserve">
<value>データのエクスポートをする</value>
</data>
<data name="DefaultPreTriggerSeconds_Description" xml:space="preserve">
<value>プリトリガー 記録時間の設定です。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultPreTriggerSeconds_DisplayName" xml:space="preserve">
<value>プリトリガー 記録時間の既定値(秒)</value>
</data>
<data name="DefaultRealtimeGraphCount_Description" xml:space="preserve">
<value>リアルタイム表示の同時表示チャンネル数の設定です。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultRealtimeGraphCount_DisplayName" xml:space="preserve">
<value> グラフの数</value>
</data>
<data name="DefaultRequireAllUnitsPassDiagnostics_Description" xml:space="preserve">
<value>全てのダイアグ項目がパスにならなかった場合、試験を続けられるかの設定。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultRequireAllUnitsPassDiagnostics_DisplayName" xml:space="preserve">
<value>全ユニットがダイアグをパスすることを要求</value>
</data>
<data name="DefaultRequireUserConfirmationOnErrors_Description" xml:space="preserve">
<value>ダイアグまたは試験実施においてエラーは発生した場合、ユーザーに確認を要求するかどうか。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultRequireUserConfirmationOnErrors_DisplayName" xml:space="preserve">
<value>エラーの確認をユーザーに要求する</value>
</data>
<data name="DefaultROIEnd_Description" xml:space="preserve">
<value>指定時間の終了時刻の設定です。トリガ前はマイナス、トリガ後はプラスの値になります。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultROIEnd_DisplayName" xml:space="preserve">
<value>指定時間 終了(秒)</value>
</data>
<data name="DefaultROIStart_Description" xml:space="preserve">
<value>指定時間の開始時刻の設定です。トリガ前はマイナス、トリガ後はプラスの値になります。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultROIStart_DisplayName" xml:space="preserve">
<value>指定時間 開始(秒)</value>
</data>
<data name="DefaultRunPostTestDiagnostics_Description" xml:space="preserve">
<value>試験後ダイアグを実行するかどうかの設定。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultRunPostTestDiagnostics_DisplayName" xml:space="preserve">
<value>試験後ダイアグの実行</value>
</data>
<data name="DefaultSuppressMissingSensorsWarning_Description" xml:space="preserve">
<value>すべてのセンサが接続されていない時の警告の有無を設定します</value>
</data>
<data name="DefaultSuppressMissingSensorsWarning_DisplayName" xml:space="preserve">
<value>すべてのセンサが接続されていない時の警告を表示しない</value>
</data>
<data name="DefaultTreeModeDiagnostics_Description" xml:space="preserve">
<value>ダイアグ結果のデフォルト表示方法。チェックするとツリービュー、チェックしないとテーブル ビューになります。</value>
</data>
<data name="DefaultTreeModeDiagnostics_DisplayName" xml:space="preserve">
<value>ダイアグでツリー ビューを使用する (チェックしないとテーブル ビュー)</value>
</data>
<data name="DefaultTriggerCheckStep_Description" xml:space="preserve">
<value>トリガーチェックを実行するかどうか、新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultTriggerCheckStep_DisplayName" xml:space="preserve">
<value>トリガーチェックを実行する</value>
</data>
<data name="DefaultUploadEnabled_Description" xml:space="preserve">
<value>データのアップロードをするかどうかの設定。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultUploadEnabled_DisplayName" xml:space="preserve">
<value>データのアップロードをする</value>
</data>
<data name="DefaultViewAll_Description" xml:space="preserve">
<value>全記録時間の表示を行うかどうかの設定。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultViewAll_DisplayName" xml:space="preserve">
<value>全記録時間の表示</value>
</data>
<data name="DefaultViewRealtime_Description" xml:space="preserve">
<value>リアルタイム表示を行うかどうかの設定。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultViewRealtime_DisplayName" xml:space="preserve">
<value>リアルタイム表示をする</value>
</data>
<data name="DefaultViewROI_Description" xml:space="preserve">
<value>指定時間の表示/非表示設定。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultViewROI_DisplayName" xml:space="preserve">
<value>指定時間の表示</value>
</data>
<data name="LastRunTestSetup_Description" xml:space="preserve">
<value>The last run test setup</value>
</data>
<data name="LastRunTestSetup_DisplayName" xml:space="preserve">
<value>Last run test setup</value>
</data>
<data name="LastUsedSampleRate_Description" xml:space="preserve">
<value>The last used sample rate (per second)</value>
</data>
<data name="LastUsedSampleRate_DisplayName" xml:space="preserve">
<value>Last used sample rate</value>
</data>
<data name="RealtimeChartWidthInSeconds_Description" xml:space="preserve">
<value> 横軸に表示する時間(秒)の設定。</value>
</data>
<data name="RealtimeChartWidthInSeconds_DisplayName" xml:space="preserve">
<value> 横軸に表示する時間(秒)</value>
</data>
<data name="RealtimeSettings" xml:space="preserve">
<value>Realtime settings</value>
</data>
<data name="TestOptions" xml:space="preserve">
<value>Test options</value>
</data>
<data name="UserHistory" xml:space="preserve">
<value>User history</value>
</data>
<data name="UsersCurrentTestSetup_Description" xml:space="preserve">
<value>The active test setup</value>
</data>
<data name="UsersCurrentTestSetup_DisplayName" xml:space="preserve">
<value>Current test setup</value>
</data>
<data name="DefaultCheckListTiltSensorCheck_Description" xml:space="preserve">
<value>アーム直前診断でチルトセンサーのチェックをするかどうか。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultCheckListTiltSensorCheck_DisplayName" xml:space="preserve">
<value>チルトセンサーのチェック</value>
</data>
<data name="AllowAdvancedRecordingModes_Description" xml:space="preserve">
<value>サーキュラーバッファモード、レコーダーモード以外の記録モードを選択可能にします</value>
</data>
<data name="AllowAdvancedRecordingModes_DisplayName" xml:space="preserve">
<value>アドバンス記録モードを使用可能にする</value>
</data>
<data name="ArmChecklist" xml:space="preserve">
<value>(4) アーム直前診断</value>
</data>
<data name="DefaultAutoArm_Description" xml:space="preserve">
<value>DASをオートアームモードに設定するにはこの項目をチェックしてください。</value>
</data>
<data name="DefaultAutoArm_DisplayName" xml:space="preserve">
<value>DASをオートアームモードに設定する</value>
</data>
<data name="DefaultAutomaticMode_Description" xml:space="preserve">
<value>自動モードを使用するかどうか 新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultAutomaticMode_DisplayName" xml:space="preserve">
<value>自動モードを使用する</value>
</data>
<data name="DefaultCheckoutMode_Description" xml:space="preserve">
<value>新規にテストセトアップを作成する時、チェックアウトモードをオンにします。</value>
</data>
<data name="DefaultCheckoutMode_DisplayName" xml:space="preserve">
<value>チェックアウトモード ==スクイブ出力をしない== (通常OFF)</value>
</data>
<data name="DefaultCommonStatusLine_Description" xml:space="preserve">
<value>ステータス信号の相互監視機能の有無、新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultCommonStatusLine_DisplayName" xml:space="preserve">
<value>ステータス信号の相互監視(通常ON)</value>
</data>
<data name="DefaultRecordingMode_Description" xml:space="preserve">
<value>記録モードの設定です。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultRecordingMode_DisplayName" xml:space="preserve">
<value>記録モード</value>
</data>
<data name="DefaultTestSetupAutomaticProgressDelaySeconds_Description" xml:space="preserve">
<value>自動モードで次のステップに進むまでの待機時間(秒)。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultTestSetupAutomaticProgressDelaySeconds_DisplayName" xml:space="preserve">
<value>自動モードで次のステップに進むまでの待機時間(秒)</value>
</data>
<data name="DefaultUploadFolder_Description" xml:space="preserve">
<value>新規テストセトアップにおけるデフォルトアップロードフォルダを設定します。</value>
</data>
<data name="DefaultUploadFolder_DisplayName" xml:space="preserve">
<value>アップロード先フォルダ</value>
</data>
<data name="DefaultWarnOnFailedBattery_Description" xml:space="preserve">
<value>バッテリー異常、バッテリーなしを警告するかどうかの設定。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultWarnOnFailedBattery_DisplayName" xml:space="preserve">
<value>バッテリー異常、バッテリーなしを警告する</value>
</data>
<data name="DiagnosticOptions" xml:space="preserve">
<value>(2) ダイアグオプション</value>
</data>
<data name="DownloadAndViewOptions" xml:space="preserve">
<value>(6) ダウンロード/表示 オプション</value>
</data>
<data name="ExportChryslerDDAS_Description" xml:space="preserve">
<value>Controls whether export DDAS unfiltered EU data is enabled by default for new test setups</value>
</data>
<data name="ExportChryslerDDAS_DisplayName" xml:space="preserve">
<value>DDAS EU フィルタ有り </value>
</data>
<data name="ExportCSVFiltered_Description" xml:space="preserve">
<value>CSV EU フィルタ有り のエクスポートを有効にします。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="ExportCSVFiltered_DisplayName" xml:space="preserve">
<value>CSV EU フィルタ有り</value>
</data>
<data name="ExportCSVUnfiltered_Description" xml:space="preserve">
<value>CSV EU フィルタ無し のエクスポートを有効にします。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="ExportCSVUnfiltered_DisplayName" xml:space="preserve">
<value>CSV EU フィルタ無し</value>
</data>
<data name="ExportHDFADC_Description" xml:space="preserve">
<value>Controls whether export HDF ADC data is enabled by default for new test setups</value>
</data>
<data name="ExportHDFADC_DisplayName" xml:space="preserve">
<value>HDF ADC</value>
</data>
<data name="ExportHDFFiltered_Description" xml:space="preserve">
<value>Controls whether export HDF filtered EU </value>
</data>
<data name="ExportHDFFiltered_DisplayName" xml:space="preserve">
<value>HDF EU フィルタ有り </value>
</data>
<data name="ExportHDFMV_Description" xml:space="preserve">
<value>Controls whether export HDF mV data is enabled by default for new test setups</value>
</data>
<data name="ExportHDFMV_DisplayName" xml:space="preserve">
<value>HDF mV</value>
</data>
<data name="ExportHDFUnfiltered_Description" xml:space="preserve">
<value>Controls whether export HDF unfiltered EU data is enabled by default for new test setups</value>
</data>
<data name="ExportHDFUnfiltered_DisplayName" xml:space="preserve">
<value>HDF EU フィルタ無し</value>
</data>
<data name="ExportISOFiltered_Description" xml:space="preserve">
<value>ISO形式 EU フィルタ有り のエクスポートを有効にします。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="ExportISOFiltered_DisplayName" xml:space="preserve">
<value>ISO EU フィルタ有り</value>
</data>
<data name="ExportISOUnFiltered_Description" xml:space="preserve">
<value>ISO形式 EU フィルタ無し のエクスポートを有効にします。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="ExportISOUnFiltered_DisplayName" xml:space="preserve">
<value>ISO EU フィルタ無し</value>
</data>
<data name="ExportOptions" xml:space="preserve">
<value>(7) エクスポートの設定</value>
</data>
<data name="ExportRDFADC_Description" xml:space="preserve">
<value>Controls whether export RDF ADC data is enabled by default for new test setups</value>
</data>
<data name="ExportRDFADC_DisplayName" xml:space="preserve">
<value>RDF ADC</value>
</data>
<data name="ExportSomatFiltered_Description" xml:space="preserve">
<value>Controls whether export Somat filtered data is enabled by default for new test setups</value>
</data>
<data name="ExportSomatFiltered_DisplayName" xml:space="preserve">
<value>Somat filtered EU</value>
</data>
<data name="ExportSomatUnfiltered_Description" xml:space="preserve">
<value>Controls whether export Somat unfiltered data is enabled by default for new test setups</value>
</data>
<data name="ExportSomatUnfiltered_DisplayName" xml:space="preserve">
<value>Somat EU フィルタ無し</value>
</data>
<data name="ExportTDASADC_Description" xml:space="preserve">
<value>Controls whether export TDAS ADCdata is enabled by default for new test setups</value>
</data>
<data name="ExportTDASADC_DisplayName" xml:space="preserve">
<value>TDAS ADC</value>
</data>
<data name="ExportTDMSADC_Description" xml:space="preserve">
<value>Controls whether export TDMS ADC data is enabled by default for new test setups</value>
</data>
<data name="ExportTDMSADC_DisplayName" xml:space="preserve">
<value>TDMS ADC</value>
</data>
<data name="ExportToyotaFiltered_Description" xml:space="preserve">
<value>Controls whether export TTS EU filtered EU data is enabled by default for new test setups</value>
</data>
<data name="ExportToyotaFiltered_DisplayName" xml:space="preserve">
<value>TTS EU フィルタ無し</value>
</data>
<data name="ExportToyotaUnfiltered_Description" xml:space="preserve">
<value>Controls whether export TTS unfiltered EU data is enabled by default for new test setups</value>
</data>
<data name="ExportToyotaUnfiltered_DisplayName" xml:space="preserve">
<value>(この項目は使用しません)</value>
</data>
<data name="ExportTSVFiltered_Description" xml:space="preserve">
<value>Controls whether export TSV filtered EU data is enabled by default for new test setups</value>
</data>
<data name="ExportTSVFiltered_DisplayName" xml:space="preserve">
<value>TSV EU フィルタ有り</value>
</data>
<data name="ExportTSVUnfiltered_Description" xml:space="preserve">
<value>Controls whether export TSV unfiltered EU data is enabled by default for new test setups</value>
</data>
<data name="ExportTSVUnfiltered_DisplayName" xml:space="preserve">
<value>TSV EU フィルタ無し</value>
</data>
<data name="ExportXLSXFiltered_Description" xml:space="preserve">
<value>Microsoft Excel (XLSX) EU フィルタ有り のエクスポートを有効にします。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="ExportXLSXFiltered_DisplayName" xml:space="preserve">
<value>XLSX EU フィルタ有り</value>
</data>
<data name="ExportXLSXUnfiltered_Description" xml:space="preserve">
<value>Microsoft Excel (XLSX) EU フィルタ無し のエクスポートを有効にします。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="ExportXLSXUnfiltered_DisplayName" xml:space="preserve">
<value>XLSX EU フィルタ無し</value>
</data>
<data name="RealtimeOptions" xml:space="preserve">
<value>(3) リアルタイム設定</value>
</data>
<data name="RecordingOptions" xml:space="preserve">
<value>(5) 記録設定</value>
</data>
<data name="SuppressViewAllRealtime_Description" xml:space="preserve">
<value>リアルタイムモードを終了する時の警告の有無、新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="SuppressViewAllRealtime_DisplayName" xml:space="preserve">
<value>リアルタイムモードを終了する時に警告を表示しない</value>
</data>
<data name="SupressQuitTestWarning_Description" xml:space="preserve">
<value>試験を中断する時の警告の有無、新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="SupressQuitTestWarning_DisplayName" xml:space="preserve">
<value>試験を中断する時に警告を表示しない</value>
</data>
<data name="SupressViewAllViewer_Description" xml:space="preserve">
<value>データ表示を終了する時の警告の有無、新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="SupressViewAllViewer_DisplayName" xml:space="preserve">
<value>データ表示を終了する時に警告を表示しない</value>
</data>
<data name="TestInfo" xml:space="preserve">
<value>(1) 試験情報</value>
</data>
<data name="UploadOptions" xml:space="preserve">
<value>(8) アップロードの設定</value>
</data>
<data name="ExportDiademADC_Description" xml:space="preserve">
<value>Controls whether export ADC is enabled by default for new test setups</value>
</data>
<data name="ExportDiademADC_DisplayName" xml:space="preserve">
<value>DIAdem ADC</value>
</data>
<data name="DefaultTestExcitationWarmupSeconds_Description" xml:space="preserve">
<value>センサウォームアップ時間の設定。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultTestExcitationWarmupSeconds_DisplayName" xml:space="preserve">
<value>センサーウォーム アップ(秒) &lt; suggested</value>
</data>
<data name="DefaultCheckListTemperatureCheck_Description" xml:space="preserve">
<value>アーム直前診断で温度のチェックをするかどうか。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultCheckListTemperatureCheck_DisplayName" xml:space="preserve">
<value>温度のチェック</value>
</data>
<data name="DefaultUploadExportsOnly_Description" xml:space="preserve">
<value>アップロードの時、すべてのテストファイルをアップロードするかエクスポートされたファイルのみアップロードするかを設定します。</value>
</data>
<data name="DefaultUploadExportsOnly_DisplayName" xml:space="preserve">
<value>エクスポートファイルのみアップロードする</value>
</data>
</root>

View File

@@ -0,0 +1,378 @@
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users.UserSettings
{
/// <summary>
/// this class holds enums used for user properties/settings
/// </summary>
public abstract class PropertyEnums
{
/// <summary>
/// here are all the categories that user settings can come in currently
/// this is used to group properties in a propertygrid
/// </summary>
public enum PropertyCategories
{
TestInfo,
TestDetails,
DiagnosticOptions,
RealtimeOptions,
ArmChecklist,
ExportOptions,
UploadOptions,
UserHistory,
ClockSyncOptions,
UARTOptions,
EmbeddedSensorSampleRateOptions,
WakeMethodOptions,
EmbeddedSensorTriggerOptions,
TestHistoryOptions
}
/// <summary>
/// used to order the properties within a category
///
/// </summary>
public enum PropertyOrders
{
//test info
AutoExpandInfoSections,
AllowAdvanceRecordingModes,
AllowTSRAIRRecordingModes,
AllowUARTRecordingModes,
AllowActiveRamRecordingModes,
UseAdvancedStreamingProfiles,
DefaultRecordingMode,
DefaultNumberOfEvents,
DefaultSampleRate,
DefaultPreTriggerSeconds,
DefaultPostTriggerSeconds,
AllowStreamingModes,
DefaultStreaming,
DefaultAutoArm,
DefaultAutoArmRepeatEnable,
DefaultAutoArmPreserveDiagnostics,
DefaultDownloadROI,
DefaultROIStart,
DefaultROIEnd,
DefaultViewROI,
DefaultDownloadAll,
DefaultViewAll,
DefaultWarnMissingTrigger,
DefaultTestSetupTag,
//test details
DefaultCheckoutMode,
AlignUDPToPPS,
DefaultSuppressMissingSensorsWarning,
DefaultSensorCalibrationBehavior,
SupressQuitTestWarning,
SuppressViewAllRealtime,
SupressViewAllViewer,
DefaultCommonStatusLine,
DefaultTriggerCheckStep,
DefaultMeasureSquibResistancesStep,
DefaultAutomaticMode,
DefaultTestSetupAutomaticProgressDelaySeconds,
DefaultWarnOnFailedBattery,
DefaultIgnoreShortedStart,
DefaultIgnoreShortedTrigger,
//diagnostic options
DefaultRequireAllUnitsPassDiagnostics,
DefaultRequireUserConfirmationOnErrors,
DefaultAllowMissingSensors,
DefaultRequireSensorIdFound,
DefaultTestExcitationWarmupSeconds,
DefaultTestExcitationTOMWarmupDelayMS,
DefaultTestExcitationIEPEWarmupDelayMS,
DefaultRunPostTestDiagnostics,
DefaultTreeModeDiagnostics,
ArmTriggerDiagnosticsRunOnNextStep,
//RealtimeOptions
DefaultViewRealtime,
DefaultRealtimeGraphCount,
RealtimeChartWidthInSeconds,
DefaultUDPStreamProfile,
DefaultUDPStreamAddress,
DefaultUDPStreamTimeChannelId,
DefaultUDPStreamDataChannelId,
DefaultUDPStreamTmNSConfig,
DefaultIRIGTimeDataPacketIntervalMs,
DefaultUDPStreamMaskEUMetaData,
//15959 Realtime Sample Rate needs to be per seat instead of site wide
RealtimeSampleRateEthernetSLICE,
RealtimeSampleRateSLICE6,
RealtimeSampleRateUSBSLICE,
RealtimeSampleRateTDAS,
RealtimeSampleRateTDASSIM,
//armchecklist
DefaultArmCheckListStep,
DefaultCheckListBatteryVoltageCheck,
DefaultCheckListInputVoltageCheck,
ArmChecklistRequiredIfTOM,
DefaultCheckListSquibResistanceCheck,
DefaultCheckListSensorIdCheck,
DefaultCheckListTriggerStartCheck,
DefaultCheckListTiltSensorCheck,
DefaultCheckListTemperatureCheck,
DefaultCheckListClockSyncCheck,
DefaultCheckListMustPass,
//ExportOptions
DefaultExport,
ExportCSVUnfiltered,
ExportCSVFiltered,
ExportCSVMV,
ExportCSVADC,
ExportDiademADC,
ExportISOUnFiltered,
ExportISOFiltered,
ExportTDASADC,
ExportToyotaUnfiltered,
ExportToyotaFiltered,
ExportTSVUnfiltered,
ExportTSVFiltered,
ExportRDFADC,
ExportTDMSADC,
ExportChryslerDDAS,
ExportHDFUnfiltered,
ExportHDFFiltered,
ExportHDFMV,
ExportHDFADC,
ExportXLSXUnfiltered,
ExportXLSXFiltered,
ExportSomatUnfiltered,
ExportSomatFiltered,
ExportASC,
//UploadOptions
UploadData,
DefaultUploadFolder,
DefaultUploadExportsOnly,
//clock sync
DefaultClockSyncProfileMaster,
DefaultClockSyncProfileSlave,
DefaultPTPDomainID,
//uart
DefaultUARTBaudRate,
DefaultUARTDataBits,
DefaultUARTStopBits,
DefaultUARTParity,
DefaultUARTFlowControl,
DefaultUARTDataFormat,
//embedded sensors
DefaultEmbeddedLowGLinearAccelerometerSampleRate,
DefaultEmbeddedHighGLinearAccelerometerSampleRate,
DefaultEmbeddedAngularAccelerometerSampleRate,
DefaultEmbeddedAngularAccelerometerAndRateSensorSampleRate,
DefaultEmbeddedAtmosphericSensorSampleRate,
//power management
//wake up
DefaultMotionDetectDelayMs,
DefaultMotionQualificationPeriodMs,
DefaultMotionDetectInactivityS,
DefaultTimeSessionDuration,
//embedded sensor triggers
DefaultEmbeddedHighGLinearAccelerometerTrigger,
DefaultEmbeddedHighGLinearAccelerometerTriggerAboveAndBelow,
DefaultTimedIntervalTrigger,
DefaultIntervalBetweenEventStartsMinutes,
DefaultTimedIntervalUnit,
DefaultTimedIntervalEventDurationMs,
DefaultTimedIntervalNumberOfEvents,
DefaultRTCScheduleTrigger,
DefaultRTCScheduleStartTime,
DefaultRTCScheduleDuration,
DefaultStoreTestHistoryInDb,
DefaultStoreSensorTestHistoryInDb,
DefaultStoreTestSetupXmlInDb
}
/// <summary>
/// this is used to define the id for all known properties, which is used
/// in serializing/deserializing to the db
/// it's also used to handle displayname and description translations
/// </summary>
public enum PropertyIds
{
DefaultUploadEnabled = 102,
DefaultTestSampleRate = 103,
DefaultPostTriggerSeconds = 104,
DefaultPreTriggerSeconds = 105,
DefaultTriggerCheckStep = 106,
DefaultRealtimeGraphCount = 107,
DefaultROIStart = 108,
DefaultROIEnd = 109,
DefaultDownloadROI = 110,
DefaultViewROI = 111,
DefaultDownloadAll = 112,
DefaultViewAll = 113,
DefaultRequireAllUnitsPassDiagnostics = 115,
DefaultRequireUserConfirmationOnErrors = 116,
DefaultAllowMissingSensors = 117,
DefaultRunPostTestDiagnostics = 124,
DefaultArmCheckListStep = 126,
DefaultCheckListInputVoltageCheck = 127,
DefaultCheckListBatteryVoltageCheck = 128,
DefaultCheckListSquibResistanceCheck = 129,
DefaultCheckListSensorIdCheck = 130,
DefaultCheckListTriggerStartCheck = 131,
DefaultRequireSensorIdFound = 132,
DefaultCheckListMustPass = 133,
DefaultViewRealtime = 134,
DefaultExport = 135,
DefaultExportFormat = 137,
DefaultCheckListTiltSensorCheck = 138,
ExportCSVUnfiltered = 139,
ExportCSVFiltered = 140,
ExportISOUnFiltered = 141,
ExportISOFiltered = 142,
ExportSomatUnfiltered = 143,
ExportSomatFiltered = 144,
ExportTDMSADC = 145,
ExportToyotaUnfiltered = 146,
ExportToyotaFiltered = 147,
ExportTSVUnfiltered = 148,
ExportTSVFiltered = 149,
ExportTDASADC = 150,
ExportRDFADC = 151,
ExportChryslerDDAS = 152,
ExportHDFUnfiltered = 153,
ExportHDFFiltered = 154,
ExportHDFMV = 155,
ExportHDFADC = 156,
ExportXLSXUnfiltered = 157,
ExportXLSXFiltered = 158,
DefaultCheckoutMode = 159,
SupressQuitTestWarning = 160,
SuppressViewAllRealtime = 161,
SupressViewAllViewer = 162,
DefaultCommonStatusLine = 163,
DefaultAutomaticMode = 164,
DefaultTestSetupAutomaticProgressDelaySeconds = 165,
DefaultWarnOnFailedBattery = 166,
DefaultUploadFolder = 167,
DefaultAutoArm = 168,
AllowAdvancedRecordingModes = 169,
DefaultRecordingMode = 170,
ExportDiademADC = 171,
DefaultTestExcitationWarmupSeconds = 172,
DefaultCheckListTemperatureCheck = 173,
DefaultUploadExportsOnly = 174,
ExportCSVMV = 175,
ExportCSVADC = 176,
DefaultTestExcitationTOMWarmupDelayMS = 177,
DefaultTestExcitationIEPEWarmupDelayMS = 178,
RealtimeChartWidthInSeconds = 301,
DefaultTreeModeDiagnostics = 302,
ArmChecklistRequiredIfTOM = 303,
DefaultSuppressMissingSensorsWarning = 304,
ArmTriggerDiagnosticsRunOnNextStep = 305,
DefaultSensorCalibrationBehavior = 306,
RealtimeSampleRateEthernetSLICE = 307,
RealtimeSampleRateSLICE6 = 308,
RealtimeSampleRateUSBSLICE = 309,
RealtimeSampleRateTDAS = 310,
RealtimeSampleRateTDASSIM = 311,
UsersCurrentTestSetup = 401,
LastRunTestSetup = 402,
LastUsedSampleRate = 403,
ApplySensorDataToBlankChannels = 404,
ShowOptionsWhenApplyingSensorToBlankChannel = 405,
DefaultStreaming = 406,
DefaultCheckListClockSyncCheck = 407,
DefaultClockSyncProfileMaster = 408,
DefaultClockSyncProfileSlave = 409,
AllowUARTRecordingModes = 410,
DefaultUARTBaudRate = 411,
DefaultUARTDataBits = 412,
DefaultUARTStopBits = 413,
DefaultUARTParity = 414,
DefaultUARTFlowControl = 415,
DefaultUDPStreamProfile = 416,
DefaultUDPStreamTimeChannelId = 417,
DefaultUDPStreamDataChannelId = 418,
DefaultUDPStreamTmNSConfig = 419,
DefaultIRIGTimeDataPacketIntervalMs = 420,
DefaultAutoArmRepeatEnable = 421,
DefaultAutoArmPreserveDiagnostics = 422,
DefaultMeasureSquibResistancesStep = 423,
DefaultNumberOfEvents = 424,
//17566 Config option to "Auto expand" test info sections.
AutoExpandInfoSections = 425,
ExpandMainInfo = 426,
ExpandTestInfo = 427,
ExpandTestDiag = 428,
ExpandTestRealtime = 429,
ExpandTestClockSync = 430,
ExpandTestArmChecklist = 431,
ExpandTestUpload = 432,
ExpandTestExport = 433,
ApplyHardwareAssignmentInHardwareDisco = 434,
DefaultEmbeddedLowGLinearAccelerometerSampleRate = 435,
DefaultEmbeddedHighGLinearAccelerometerSampleRate = 436,
DefaultEmbeddedAngularAccelerometerSampleRate = 437,
DefaultEmbeddedAngularAccelerometerAndRateSensorSampleRate = 438,
DefaultEmbeddedAtmosphericSensorSampleRate = 439,
DefaultWakeMethod = 441,
DefaultMotionDetectDelayMs = 442,
DefaultMotionQualificationPeriodMs = 443,
DefaultMotionDetectInactivityS = 444,
DefaultTimeSessionDuration = 447,
DefaultEmbeddedHighGLinearAccelerometerTrigger = 453,
DefaultEmbeddedHighGLinearAccelerometerTriggerAboveAndBelow = 454,
DefaultTimedIntervalTrigger = 468,
DefaultIntervalBetweenEventStartsMinutes = 469,
DefaultTimedIntervalUnit = 470,
DefaultTimedIntervalEventDurationMs = 471,
DefaultTimedIntervalNumberOfEvents = 472,
DefaultRTCScheduleTrigger = 473,
DefaultRTCScheduleStartTime = 474,
DefaultRTCScheduleDuration = 475,
DefaultStoreTestHistoryInDb = 476,
DefaultStoreSensorTestHistoryInDb = 477,
DefaultStoreTestSetupXmlInDb = 478,
DefaultWarnMissingTrigger = 479,
AllowStreamingModes = 480,
//whether to remember test id prefix/suffix
//18028 Remember test id suffix drop down state
StoreTestIdAffixes = 481,
TestIdPrefix = 482,
TestIdSuffix = 483,
//18361
DefaultUARTDataFormat = 484,
//18362
DefaultUDPStreamAddress = 485,
DefaultUDPStreamMaskEUMetaData = 486,
DefaultTestSetupTag = 487,
AllowTSRAIRRecordingModes = 488,
ExportASC = 489,
//29835
DefaultIgnoreShortedStart = 490,
DefaultIgnoreShortedTrigger = 491,
//31840
DefaultUseAdvancedUDPStreamProfiles = 492,
//30513
DefaultPTPDomainID = 493,
//31841
AllowActiveRamRecordingModes = 494,
//39470
AlignUDPToPPS = 495
}
}
}

View File

@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Globalization;
using DTS.Common.Settings;
namespace DTS.Slice.Users.UserSettings
{
public class SampleRateConverter : DoubleConverter
{
List<double> _validSampleRateList = new List<double>();
private const int SampleRateIndiceCountDefault = 24;
private const int SPSINDICE_COUNT = 56;
private const string SAMPLERATE_INDEX = "SPSINDEX_";
public static int[] AvailableSampleRatesDefault = new int[]
{
5,
50,
100,
200,
250, //TDC rates start here, everything from here to next comment is in default TDC.ini
500,
1000,
2000,
2500,
5000,
8000,
10000,
12500,
20000,
25000,
40000,
50000,
60000,
75000,
100000,
150000,
300000, //TDC rates end here
400000,
500000,
1000000
};
public SampleRateConverter()
{
}
//public SampleRateConverter(List<double> validSampleRateList)
//{
// _validSampleRateList = validSampleRateList;
//}
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
var SampleRateIndiceCount = SettingsDB.GetGlobalValueInt(SPSINDICE_COUNT.ToString(), SampleRateIndiceCountDefault);
_validSampleRateList.Clear();
for (var i = 0; i < SampleRateIndiceCount; i++)
{
var defaultValue = -1;
if (i < AvailableSampleRatesDefault.Length) { defaultValue = AvailableSampleRatesDefault[i]; }
var value = SettingsDB.GetGlobalValueInt(SAMPLERATE_INDEX + i.ToString(CultureInfo.InvariantCulture), defaultValue);
if (_validSampleRateList.Contains(value)) continue;
if (value > 0) { _validSampleRateList.Add(Convert.ToDouble(value)); }
}
return new StandardValuesCollection(_validSampleRateList.ToArray());
}
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
return true;
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
return base.ConvertTo(context, culture, value, destinationType);
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type t)
{
return base.CanConvertTo(context, t);
}
}
}

View File

@@ -0,0 +1,386 @@
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users.UserSettings
{
/// <summary>
/// this class holds enums used for user properties/settings
/// </summary>
public abstract class PropertyEnums
{
/// <summary>
/// here are all the categories that user settings can come in currently
/// this is used to group properties in a propertygrid
/// </summary>
public enum PropertyCategories
{
TestInfo,
TestDetails,
DiagnosticOptions,
RealtimeOptions,
ArmChecklist,
ExportOptions,
UploadOptions,
UserHistory,
ClockSyncOptions,
UARTOptions,
EmbeddedSensorSampleRateOptions,
WakeMethodOptions,
EmbeddedSensorTriggerOptions,
TestHistoryOptions
}
/// <summary>
/// used to order the properties within a category
///
/// </summary>
public enum PropertyOrders
{
//test info
AutoExpandInfoSections,
AllowAdvanceRecordingModes,
AllowTSRAIRRecordingModes,
AllowUARTRecordingModes,
AllowActiveRamRecordingModes,
UseAdvancedStreamingProfiles,
DefaultRecordingMode,
DefaultNumberOfEvents,
DefaultSampleRate,
DefaultPreTriggerSeconds,
DefaultPostTriggerSeconds,
AllowStreamingModes,
DefaultStreaming,
DefaultAutoArm,
DefaultAutoArmRepeatEnable,
DefaultAutoArmPreserveDiagnostics,
DefaultDownloadROI,
DefaultROIStart,
DefaultROIEnd,
DefaultViewROI,
DefaultDownloadAll,
DefaultViewAll,
DefaultWarnMissingTrigger,
DefaultTestSetupTag,
//test details
DefaultCheckoutMode,
AlignUDPToPPS,
DefaultSuppressMissingSensorsWarning,
DefaultSensorCalibrationBehavior,
SupressQuitTestWarning,
SuppressViewAllRealtime,
SupressViewAllViewer,
DefaultCommonStatusLine,
DefaultTriggerCheckStep,
DefaultMeasureSquibResistancesStep,
DefaultAutomaticMode,
DefaultTestSetupAutomaticProgressDelaySeconds,
DefaultWarnOnFailedBattery,
DefaultIgnoreShortedStart,
DefaultIgnoreShortedTrigger,
//diagnostic options
DefaultRequireAllUnitsPassDiagnostics,
DefaultRequireUserConfirmationOnErrors,
DefaultAllowMissingSensors,
DefaultRequireSensorIdFound,
DefaultTestExcitationWarmupSeconds,
DefaultTestExcitationTOMWarmupDelayMS,
DefaultTestExcitationIEPEWarmupDelayMS,
DefaultRunPostTestDiagnostics,
DefaultTreeModeDiagnostics,
ArmTriggerDiagnosticsRunOnNextStep,
//RealtimeOptions
DefaultViewRealtime,
DefaultRealtimeGraphCount,
RealtimeChartWidthInSeconds,
DefaultUDPStreamProfile,
DefaultUDPStreamAddress,
DefaultUDPStreamTimeChannelId,
DefaultUDPStreamDataChannelId,
DefaultUDPStreamTmNSConfig,
DefaultIRIGTimeDataPacketIntervalMs,
DefaultUDPStreamMaskEUMetaData,
//15959 Realtime Sample Rate needs to be per seat instead of site wide
RealtimeSampleRateEthernetSLICE,
RealtimeSampleRateSLICE6,
RealtimeSampleRateUSBSLICE,
RealtimeSampleRateTDAS,
RealtimeSampleRateTDASSIM,
//armchecklist
DefaultArmCheckListStep,
DefaultCheckListBatteryVoltageCheck,
DefaultCheckListInputVoltageCheck,
ArmChecklistRequiredIfTOM,
DefaultCheckListSquibResistanceCheck,
DefaultCheckListSensorIdCheck,
DefaultCheckListTriggerStartCheck,
DefaultCheckListTiltSensorCheck,
DefaultCheckListTemperatureCheck,
DefaultCheckListClockSyncCheck,
DefaultCheckListMustPass,
//ExportOptions
DefaultExport,
ExportCSVUnfiltered,
ExportCSVFiltered,
ExportCSVMV,
ExportCSVADC,
ExportDiademADC,
ExportISOUnFiltered,
ExportISOFiltered,
ExportTDASADC,
ExportToyotaUnfiltered,
ExportToyotaFiltered,
ExportTSVUnfiltered,
ExportTSVFiltered,
ExportRDFADC,
ExportTDMSADC,
ExportChryslerDDAS,
ExportHDFUnfiltered,
ExportHDFFiltered,
ExportHDFMV,
ExportHDFADC,
ExportXLSXUnfiltered,
ExportXLSXFiltered,
ExportSomatUnfiltered,
ExportSomatFiltered,
ExportASC,
//UploadOptions
UploadData,
DefaultUploadFolder,
DefaultUploadExportsOnly,
//clock sync
DefaultClockSyncProfileMaster,
DefaultClockSyncProfileSlave,
DefaultPTPDomainID,
//uart
DefaultUARTBaudRate,
DefaultUARTDataBits,
DefaultUARTStopBits,
DefaultUARTParity,
DefaultUARTFlowControl,
DefaultUARTDataFormat,
//embedded sensors
DefaultEmbeddedLowGLinearAccelerometerSampleRate,
DefaultEmbeddedHighGLinearAccelerometerSampleRate,
DefaultEmbeddedAngularAccelerometerSampleRate,
DefaultEmbeddedAngularAccelerometerAndRateSensorSampleRate,
DefaultEmbeddedAtmosphericSensorSampleRate,
//power management
//wake up
DefaultMotionDetectDelayMs,
DefaultMotionQualificationPeriodMs,
DefaultMotionDetectInactivityS,
DefaultTimeSessionDuration,
//embedded sensor triggers
DefaultEmbeddedHighGLinearAccelerometerTrigger,
DefaultEmbeddedHighGLinearAccelerometerTriggerAboveAndBelow,
DefaultTimedIntervalTrigger,
DefaultIntervalBetweenEventStartsMinutes,
DefaultTimedIntervalUnit,
DefaultTimedIntervalEventDurationMs,
DefaultTimedIntervalNumberOfEvents,
DefaultRTCScheduleTrigger,
DefaultRTCScheduleStartTime,
DefaultRTCScheduleDuration,
DefaultStoreTestHistoryInDb,
DefaultStoreSensorTestHistoryInDb,
DefaultStoreTestSetupXmlInDb
}
/// <summary>
/// this is used to define the id for all known properties, which is used
/// in serializing/deserializing to the db
/// it's also used to handle displayname and description translations
/// </summary>
public enum PropertyIds
{
DefaultUploadEnabled = 102,
DefaultTestSampleRate = 103,
DefaultPostTriggerSeconds = 104,
DefaultPreTriggerSeconds = 105,
DefaultTriggerCheckStep = 106,
DefaultRealtimeGraphCount = 107,
DefaultROIStart = 108,
DefaultROIEnd = 109,
DefaultDownloadROI = 110,
DefaultViewROI = 111,
DefaultDownloadAll = 112,
DefaultViewAll = 113,
DefaultRequireAllUnitsPassDiagnostics = 115,
DefaultRequireUserConfirmationOnErrors = 116,
DefaultAllowMissingSensors = 117,
DefaultRunPostTestDiagnostics = 124,
DefaultArmCheckListStep = 126,
DefaultCheckListInputVoltageCheck = 127,
DefaultCheckListBatteryVoltageCheck = 128,
DefaultCheckListSquibResistanceCheck = 129,
DefaultCheckListSensorIdCheck = 130,
DefaultCheckListTriggerStartCheck = 131,
DefaultRequireSensorIdFound = 132,
DefaultCheckListMustPass = 133,
DefaultViewRealtime = 134,
DefaultExport = 135,
DefaultExportFormat = 137,
DefaultCheckListTiltSensorCheck = 138,
ExportCSVUnfiltered = 139,
ExportCSVFiltered = 140,
ExportISOUnFiltered = 141,
ExportISOFiltered = 142,
ExportSomatUnfiltered = 143,
ExportSomatFiltered = 144,
ExportTDMSADC = 145,
ExportToyotaUnfiltered = 146,
ExportToyotaFiltered = 147,
ExportTSVUnfiltered = 148,
ExportTSVFiltered = 149,
ExportTDASADC = 150,
ExportRDFADC = 151,
ExportChryslerDDAS = 152,
ExportHDFUnfiltered = 153,
ExportHDFFiltered = 154,
ExportHDFMV = 155,
ExportHDFADC = 156,
ExportXLSXUnfiltered = 157,
ExportXLSXFiltered = 158,
DefaultCheckoutMode = 159,
SupressQuitTestWarning = 160,
SuppressViewAllRealtime = 161,
SupressViewAllViewer = 162,
DefaultCommonStatusLine = 163,
DefaultAutomaticMode = 164,
DefaultTestSetupAutomaticProgressDelaySeconds = 165,
DefaultWarnOnFailedBattery = 166,
DefaultUploadFolder = 167,
DefaultAutoArm = 168,
AllowAdvancedRecordingModes = 169,
DefaultRecordingMode = 170,
ExportDiademADC = 171,
DefaultTestExcitationWarmupSeconds = 172,
DefaultCheckListTemperatureCheck = 173,
DefaultUploadExportsOnly = 174,
ExportCSVMV = 175,
ExportCSVADC = 176,
DefaultTestExcitationTOMWarmupDelayMS = 177,
DefaultTestExcitationIEPEWarmupDelayMS = 178,
RealtimeChartWidthInSeconds = 301,
DefaultTreeModeDiagnostics = 302,
ArmChecklistRequiredIfTOM = 303,
DefaultSuppressMissingSensorsWarning = 304,
ArmTriggerDiagnosticsRunOnNextStep = 305,
DefaultSensorCalibrationBehavior = 306,
RealtimeSampleRateEthernetSLICE = 307,
RealtimeSampleRateSLICE6 = 308,
RealtimeSampleRateUSBSLICE = 309,
RealtimeSampleRateTDAS = 310,
RealtimeSampleRateTDASSIM = 311,
UsersCurrentTestSetup = 401,
LastRunTestSetup = 402,
LastUsedSampleRate = 403,
ApplySensorDataToBlankChannels = 404,
ShowOptionsWhenApplyingSensorToBlankChannel = 405,
DefaultStreaming = 406,
DefaultCheckListClockSyncCheck = 407,
DefaultClockSyncProfileMaster = 408,
DefaultClockSyncProfileSlave = 409,
AllowUARTRecordingModes = 410,
DefaultUARTBaudRate = 411,
DefaultUARTDataBits = 412,
DefaultUARTStopBits = 413,
DefaultUARTParity = 414,
DefaultUARTFlowControl = 415,
DefaultUDPStreamProfile = 416,
DefaultUDPStreamTimeChannelId = 417,
DefaultUDPStreamDataChannelId = 418,
DefaultUDPStreamTmNSConfig = 419,
DefaultIRIGTimeDataPacketIntervalMs = 420,
DefaultAutoArmRepeatEnable = 421,
DefaultAutoArmPreserveDiagnostics = 422,
DefaultMeasureSquibResistancesStep = 423,
DefaultNumberOfEvents = 424,
//17566 Config option to "Auto expand" test info sections.
AutoExpandInfoSections = 425,
ExpandMainInfo = 426,
ExpandTestInfo = 427,
ExpandTestDiag = 428,
ExpandTestRealtime = 429,
ExpandTestClockSync = 430,
ExpandTestArmChecklist = 431,
ExpandTestUpload = 432,
ExpandTestExport = 433,
ApplyHardwareAssignmentInHardwareDisco = 434,
DefaultEmbeddedLowGLinearAccelerometerSampleRate = 435,
DefaultEmbeddedHighGLinearAccelerometerSampleRate = 436,
DefaultEmbeddedAngularAccelerometerSampleRate = 437,
DefaultEmbeddedAngularAccelerometerAndRateSensorSampleRate = 438,
DefaultEmbeddedAtmosphericSensorSampleRate = 439,
DefaultWakeMethod = 441,
DefaultMotionDetectDelayMs = 442,
DefaultMotionQualificationPeriodMs = 443,
DefaultMotionDetectInactivityS = 444,
DefaultTimeSessionDuration = 447,
DefaultEmbeddedHighGLinearAccelerometerTrigger = 453,
DefaultEmbeddedHighGLinearAccelerometerTriggerAboveAndBelow = 454,
DefaultTimedIntervalTrigger = 468,
DefaultIntervalBetweenEventStartsMinutes = 469,
DefaultTimedIntervalUnit = 470,
DefaultTimedIntervalEventDurationMs = 471,
DefaultTimedIntervalNumberOfEvents = 472,
DefaultRTCScheduleTrigger = 473,
DefaultRTCScheduleStartTime = 474,
DefaultRTCScheduleDuration = 475,
DefaultStoreTestHistoryInDb = 476,
DefaultStoreSensorTestHistoryInDb = 477,
DefaultStoreTestSetupXmlInDb = 478,
DefaultWarnMissingTrigger = 479,
AllowStreamingModes = 480,
//whether to remember test id prefix/suffix
//18028 Remember test id suffix drop down state
StoreTestIdAffixes = 481,
TestIdPrefix = 482,
TestIdSuffix = 483,
//18361
DefaultUARTDataFormat = 484,
//18362
DefaultUDPStreamAddress = 485,
DefaultUDPStreamMaskEUMetaData = 486,
DefaultTestSetupTag = 487,
AllowTSRAIRRecordingModes = 488,
ExportASC = 489,
//29835
DefaultIgnoreShortedStart = 490,
DefaultIgnoreShortedTrigger = 491,
//31840
DefaultUseAdvancedUDPStreamProfiles = 492,
//30513
DefaultPTPDomainID = 493,
//31841
AllowActiveRamRecordingModes = 494,
//39470
AlignUDPToPPS = 495,
//44881
DefaultCANIsFD = 497,
DefaultCANArbBaseBitrate = 498,
DefaultCANArbBaseSJW = 499,
DefaultCANDataBitrate = 500,
DefaultCANDataSJW = 501,
DefaultCANFileType = 502,
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,253 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using DTS.Common.Storage;
using DTS.Common.Utilities.Logging;
namespace DTS.Slice.Users
{
public abstract class TagAwareBase : Common.Base.BasePropertyChanged
{
public enum TagTypes
{
User,
Group,
Template,
TestSetup,
Sensors,
SensorModels
}
public abstract TagTypes TagType { get; }
#region Tags
public byte[] TagsBlobBytes
{
get
{
var result = new byte[TagIDs.Length * sizeof(int)];
Buffer.BlockCopy(TagIDs, 0, result, 0, result.Length);
return result;
}
set
{
if (value.Length < sizeof(int)) return;
var tagsBlob = new int[value.Length / sizeof(int)];
try
{
Buffer.BlockCopy(value, 0, tagsBlob, 0, value.Length);
TagIDs = tagsBlob;
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
}
private int[] _tagIDs = new int[0];
public int[] TagIDs
{
get => _tagIDs;
set => _tagIDs = value ?? new int[0];
}
public void SetTagsFromCommaSeparatedString(string tagText)
{
//if (string.IsNullOrEmpty(tagText)) { return; } // http://fogbugz/fogbugz/default.asp?7176
SetTags(tagText.Split(','));
}
public virtual void SetTags(string[] tagsText)
{
Tags.AddRange(tagsText);
TagIDs = Tags.GetIDsFromTagText(tagsText);
OnPropertyChanged("TagIDs");
}
public string GetTagsAsCommaSeparatedString()
{
var sb = new StringBuilder();
foreach (var s in GetTagsArray())
{
if (sb.Length > 0) { sb.Append(","); }
sb.Append(s);
}
return sb.ToString();
}
#region ITagAware
public virtual string[] GetTagsArray()
{
return Tags.GetTagTextFromIDs(TagIDs);
}
public virtual int[] GetTagIDs() { return TagIDs; }
public virtual void RemoveTags(string[] tagsText)
{
// remove tags!!!
//-;
}
public bool TagCompatible(string tags)
{
//Make sure there are Tags to check
if (string.IsNullOrWhiteSpace(tags)) return true;
var newTagsArray = tags.Split(',');
//Make sure all Tags are not empty strings
if (newTagsArray.All(string.IsNullOrWhiteSpace)) return true;
var comparisonArray = GetTagsArray();
foreach (var tag in newTagsArray)
{
//If a Tag is an empty string, ignore it
if (string.IsNullOrWhiteSpace(tag)) continue;
if (comparisonArray.Contains(tag.Trim()))
{
return true;
}
}
return false;
}
public virtual bool TagCompatible(int[] tags)
{
return !tags.Any() || HasIntersectingTag(tags);
}
public virtual bool HasIntersectingTag(int[] tags)
{
return tags.Intersect(TagIDs).Any();
}
#endregion
#endregion
public void InsertTagsFromCommaSeparatedString(int id, TagTypes tagType, string tags)
{
SetTagsFromCommaSeparatedString(tags);
Commit(id, tagType);
}
public void Commit(int id, TagTypes tagType)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_TagAssignmentsDelete.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@ObjectID", SqlDbType.Int) { Value = id });
cmd.Parameters.Add(new SqlParameter("@ObjectType", SqlDbType.SmallInt) { Value = tagType });
var errorNumberParam = new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam = new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
if (!TagIDs.Any()) return;
foreach (var tagId in TagIDs)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_TagAssignmentsInsert.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@ObjectID", SqlDbType.Int) { Value = id });
cmd.Parameters.Add(new SqlParameter("@ObjectType", SqlDbType.SmallInt) { Value = tagType });
cmd.Parameters.Add(new SqlParameter("@TagID", SqlDbType.Int) { Value = tagId });
var errorNumberParam = new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam = new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
}
}
public List<int> GetTagIdList(int objectId, TagTypes tagType)
{
var tagIdList = new List<int>();
try
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_TagAssignmentsGet.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@ObjectType", SqlDbType.Int) { Value = tagType });
#endregion params
//cmd.ExecuteNonQuery();
using (var ds = DbOperations.Connection.QueryDataSet(cmd))
{
foreach (DataRow dr in ds.Tables[0].Rows)
{
if (Convert.ToInt32(dr[DbOperations.Tags.TagAssignmentFields.ObjectID.ToString()]) != objectId) continue;
var tagId = Convert.ToInt32(dr[DbOperations.Tags.TagAssignmentFields.TagID.ToString()]);
if (!tagIdList.Contains(tagId))
{
tagIdList.Add(tagId);
}
}
}
}
finally
{
cmd.Connection.Dispose();
}
}
}
catch (Exception ex)
{
APILogger.Log("failed to retrieve object tags", ex);
}
return tagIdList;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,570 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using DTS.Common.Classes;
using DTS.Common.Interface.Tags;
using DTS.Common.Storage;
using DTS.Common.Utilities.Logging;
using DTS.Slice.Users.UserSettings;
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users
{
public class UserCollection : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T storage, T value, string propertyName = null)
{
if (Equals(storage, value)) return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged(string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private static readonly object MyLock = new object();
private static UserCollection _userList;
public static UserCollection UsersList
{
get
{
lock (MyLock)
{
return _userList ?? (_userList = new UserCollection());
}
}
}
private UserCollection() { }
public static Dictionary<int, List<int>> GetUserToTagIdLookup()
{
var lookup = new Dictionary<int, List<int>>();
var hr = DbOperations.TagAssignmentsGet(TagTypes.User, out var records);
if (0 == hr && null != records && records.Any())
{
foreach (var record in records)
{
if (!lookup.ContainsKey(record.ObjectID))
{
lookup.Add(record.ObjectID, new List<int>());
}
lookup[record.ObjectID].Add(record.TagID);
}
}
return lookup;
}
public static User[] GetAllUsers(IUIItems[] allItems, int? uid = null)
{
lock (MyLock)
{
//keyed by user and then uiitem id
var permissionLookup = new Dictionary<int, Dictionary<long, UIItemHelper>>();
var tagsLookup = GetUserToTagIdLookup();
try
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UserUIItemSettingsGet.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = uid });
#endregion params
using (var ds = DbOperations.Connection.QueryDataSet(cmd))
{
if (ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
foreach (DataRow dr in ds.Tables[0].Rows)
{
var userId = Convert.ToInt32(dr["UserID"]);
var uiItemId = Convert.ToInt64(dr["UIItemID"]);
var permission = Convert.ToInt16(dr["Permission"]);
var visible = Convert.ToBoolean(dr["Visible"]);
var uiItemName = Convert.ToString(dr["NAME"]);
var helper = new UIItemHelper(uiItemId, permission, visible, uiItemName);
if (!permissionLookup.ContainsKey(userId))
{
permissionLookup.Add(userId, new Dictionary<long, UIItemHelper>());
}
permissionLookup[userId][uiItemId] = helper;
}
}
}
}
finally
{
cmd.Connection.Dispose();
}
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
var users = new List<User>();
try
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UsersGet.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = uid });
#endregion params
using (var ds = DbOperations.Connection.QueryDataSet(cmd))
{
if (ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
foreach (DataRow dr in ds.Tables[0].Rows)
{
try
{
users.Add(new User(dr, allItems, permissionLookup, tagsLookup));
}
catch (Exception ex)
{
APILogger.Log("Failed to read user", ex);
}
}
}
}
}
finally
{
cmd.Connection.Dispose();
}
}
}
catch (Exception ex)
{
APILogger.Log("problem getting user", ex);
}
// uid is null when we are requesting all users. This function is dual purpose and can be used to request
// a single user by passing a uid
if (null != uid) return users.ToArray();
var roles = Enum.GetValues(typeof(User.DefaultRoles)).Cast<User.DefaultRoles>().ToArray();
foreach (var role in roles)
{
var user = User.CreateDefault(role, allItems);
var bFound = users.Exists(u => u.UserName == user.UserName);
if (!bFound)
{
UsersList.Commit(user, user.UserName, allItems);
}
}
//Now add the users that are not the default for a role
var nonDefaultUser = User.CreateNonDefaultPowerUser(User.DefaultAeroUsername, allItems);
var nonDefaultUserFound = users.Exists(u => u.UserName == nonDefaultUser.UserName);
if (!nonDefaultUserFound)
{
UsersList.Commit(nonDefaultUser, nonDefaultUser.UserName, allItems);
}
nonDefaultUser = User.CreateNonDefaultPowerUser(User.DefaultCrashUsername, allItems);
nonDefaultUserFound = users.Exists(u => u.UserName == nonDefaultUser.UserName);
if (!nonDefaultUserFound)
{
UsersList.Commit(nonDefaultUser, nonDefaultUser.UserName, allItems);
}
nonDefaultUser = User.CreateNonDefaultPowerUser(User.DefaultTSRAIRUsername, allItems);
nonDefaultUserFound = users.Exists(u => u.UserName == nonDefaultUser.UserName);
if (!nonDefaultUserFound)
{
UsersList.Commit(nonDefaultUser, nonDefaultUser.UserName, allItems);
}
return users.ToArray();
}
}
public static User GetUser(int uid, IUIItems[] items)
{
var users = GetAllUsers(items, uid);
var enumerable = users ?? users.ToArray();
return !enumerable.Any() ? null : enumerable[0];
}
public static User GetUser(string username, IUIItems[] items)
{
try
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UsersGetId.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@UserName", SqlDbType.NVarChar, 50) { Value = username });
var newIdParam =
new SqlParameter("@UserId", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(newIdParam);
#endregion params
cmd.ExecuteNonQuery();
if (DBNull.Value.Equals(newIdParam.Value))
{
return null;
}
var id = int.Parse(newIdParam.Value.ToString());
return id != 0 ? GetUser(id, items) : null;
}
finally
{
cmd.Connection.Dispose();
}
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
return null;
}
public void Commit(User user, string username, IUIItems[] items)
{
try
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UsersUpdateInsert.ToString();
#region params
//cmd.Parameters.Add(new SqlParameter("@Id", SqlDbType.NVarChar, 50) { Value = user.Id });
cmd.Parameters.Add(
new SqlParameter("@UserName", SqlDbType.NVarChar, 50) { Value = user.UserName });
cmd.Parameters.Add(
new SqlParameter("@DisplayName", SqlDbType.NVarChar, 50) { Value = user.Name });
cmd.Parameters.Add(
new SqlParameter("@Password", SqlDbType.NVarChar, 2048) { Value = user.GetPasswordHash() });
cmd.Parameters.Add(new SqlParameter("@Role", SqlDbType.SmallInt) { Value = user.Role });
cmd.Parameters.Add(
new SqlParameter("@LastModified", SqlDbType.DateTime) { Value = DateTime.Now });
cmd.Parameters.Add(
new SqlParameter("@LastModifiedBy", SqlDbType.NVarChar, 50) { Value = username });
cmd.Parameters.Add(new SqlParameter("@LocalOnly", SqlDbType.Bit) { Value = user.LocalOnly });
var newIdParam =
new SqlParameter("@new_id", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(newIdParam);
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
var id = int.Parse(newIdParam.Value.ToString());
user.Id = id == 0 ? user.Id : id;
}
finally
{
cmd.Connection.Dispose();
}
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
var settings = TestSetupDefaults.GetUserSettings(user.Id);
var properties = settings.GetType().GetProperties();
Defaults.CreateOrUpdateUserSettingProperties(user.Id, properties);
InsertPermissionsAndVisibility(user, items);
InsertTags(user);
OnPropertyChanged("AllUsers");
}
/// <summary>
/// associates tags to a user
/// </summary>
/// <param name="user"></param>
private static void InsertTags(User user)
{
_ = DbOperations.TagAssignmentsDelete(user.TagType, user.Id);
if (!user.TagIDs.Any()) return;
foreach (var tag in user.TagIDs)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_TagAssignmentsInsert.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@ObjectID", SqlDbType.Int) { Value = user.Id });
cmd.Parameters.Add(new SqlParameter("@ObjectType", SqlDbType.SmallInt) { Value = user.TagType });
cmd.Parameters.Add(new SqlParameter("@TagID", SqlDbType.Int) { Value = tag });
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
}
}
public void Delete(User user)
{
lock (MyLock)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UsersDelete.ToString();
#region params
if (user.IsADefaultUser)
{
cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = user.Id });
}
cmd.Parameters.Add(
new SqlParameter("@UserName", SqlDbType.NVarChar, 50) { Value = user.UserName });
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
OnPropertyChanged("AllUsers");
}
}
public void Delete(User[] users)
{
foreach (var user in users)
{
Delete(user);
}
}
private static void InsertPermissionsAndVisibility(User user, IReadOnlyList<IUIItems> items)
{
try
{
//all our UIItems should already be in the db, so we just have to associate them now...
//but first, I guess just remove any existing associations.
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UserUIItemSettingsDelete.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@UserID", SqlDbType.NVarChar, 50) { Value = user.Id });
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
//now to insert them ... there could be a lot so we have to put them into a bunches
foreach (var item in items)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UserUIItemSettingsInsert.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@UserID", SqlDbType.Int) { Value = user.Id });
var uiItemId = item.GetID();
var userPermission = user.GetPermission(item);
var isShow = user.IsShowTabFlagSet(item);
cmd.Parameters.Add(new SqlParameter("@UIItemID", SqlDbType.Int) { Value = uiItemId });
cmd.Parameters.Add(
new SqlParameter("@Permission", SqlDbType.SmallInt) { Value = userPermission });
cmd.Parameters.Add(new SqlParameter("@Visible", SqlDbType.SmallInt) { Value = isShow });
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
//private static void UpdateAll(User user, string username)
//{
// try
// {
// using (var cmd = DbOperations.GetSQLCommand(true))
// {
// try
// {
// cmd.CommandType = CommandType.StoredProcedure;
// cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UserUpdate.ToString();
// #region params
// cmd.Parameters.Add(new SqlParameter("@UserName", SqlDbType.NVarChar, 50) {Value = user.Name});
// cmd.Parameters.Add(
// new SqlParameter("@DisplayName", SqlDbType.NVarChar, 50) {Value = user.Name});
// cmd.Parameters.Add(
// new SqlParameter("@Password", SqlDbType.NVarChar, 2048) {Value = user.GetPasswordHash()});
// cmd.Parameters.Add(new SqlParameter("@Role", SqlDbType.SmallInt) {Value = user.Role});
// cmd.Parameters.Add(
// new SqlParameter("@LastModified", SqlDbType.DateTime) {Value = DateTime.Now});
// cmd.Parameters.Add(
// new SqlParameter("@LastModifiedBy", SqlDbType.NVarChar, 50) {Value = username});
// cmd.Parameters.Add(new SqlParameter("@LocalOnly", SqlDbType.Bit) {Value = user.LocalOnly});
// var errorNumberParam =
// new SqlParameter("@errorNumber", SqlDbType.Int) {Direction = ParameterDirection.Output};
// cmd.Parameters.Add(errorNumberParam);
// var errorMessageParam =
// new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
// {
// Direction = ParameterDirection.Output
// };
// cmd.Parameters.Add(errorMessageParam);
// #endregion params
// cmd.ExecuteNonQuery();
// if (int.Parse(errorNumberParam.Value.ToString()) != 0)
// {
// //errorMessageParam.Value
// }
// }
// finally
// {
// cmd.Connection.Dispose();
// }
// }
// }
// catch (Exception ex)
// {
// APILogger.Log("Failed to update user", user.UserName, ex);
// throw;// TODO: handle exception properly
// }
//}
}
}

View File

@@ -0,0 +1,14 @@
namespace DTS.Slice.Users
{
public interface IUIItems
{
User.UserPermissionLevels GetDefaultRolePermission(User.DefaultRoles role);
bool GetDefaultRoleVisibility(User.DefaultRoles role);
void SetVisible(bool bShow);
void SetEnabled(bool bEnabled);
User.UserPermissionLevels GetRequiredPermission();
string GetName();
long GetID();
void SetID(long id);
}
}

View File

@@ -0,0 +1,157 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{BE8D217D-6DA9-4BCA-B62A-A82325B33979}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Users</RootNamespace>
<AssemblyName>Users</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>3.5</OldToolsVersion>
<TargetFrameworkProfile />
<SccProjectName>
</SccProjectName>
<SccLocalPath>
</SccLocalPath>
<SccAuxPath>
</SccAuxPath>
<SccProvider>
</SccProvider>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Xceed.Wpf.Toolkit, Version=3.8.19076.18510, Culture=neutral, PublicKeyToken=ba83ff368b7563c6, processorArchitecture=MSIL">
<HintPath>..\..\Common\DTS.Common\lib\Xceed.Wpf.Toolkit\Xceed.Wpf.Toolkit.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ChallengeDialog.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ChallengeDialog.designer.cs">
<DependentUpon>ChallengeDialog.cs</DependentUpon>
</Compile>
<Compile Include="IUIItems.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UIItemHelper.cs" />
<Compile Include="User.cs" />
<Compile Include="UserCollection.cs" />
<Compile Include="UserSettings\Defaults.cs" />
<Compile Include="UserSettings\OptimizationSettings.cs" />
<Compile Include="UserSettings\PropertyIdAttribute.cs" />
<Compile Include="UserSettings\DescriptionAttributeEx.cs" />
<Compile Include="UserSettings\DisplayAttributeEx.cs" />
<Compile Include="UserSettings\CategoryAttributeEx.cs" />
<Compile Include="UserSettings\PropertyEnums.cs" />
<Compile Include="UserSettings\SampleRateConverter.cs" />
<Compile Include="UserSettings\StringResources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>StringResources.resx</DependentUpon>
</Compile>
<Compile Include="UserSettings\UserHistory.cs" />
<Compile Include="UserSettings\TestSetupDefaults.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="ChallengeDialog.resx">
<DependentUpon>ChallengeDialog.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="UserSettings\StringResources.ja.resx" />
<EmbeddedResource Include="UserSettings\StringResources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>StringResources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Common\DTS.Common.SettingsDB\DTS.Common.Settings.csproj">
<Project>{61017104-D8EE-41D1-B9CA-DAD863FF78B2}</Project>
<Name>DTS.Common.Settings</Name>
</ProjectReference>
<ProjectReference Include="..\..\Common\DTS.Common.Storage\DTS.Common.Storage.csproj">
<Project>{e3be457c-0ac7-4a9c-bc81-eafeb3217878}</Project>
<Name>DTS.Common.Storage</Name>
</ProjectReference>
<ProjectReference Include="..\..\Common\DTS.Common.Utilities\DTS.Common.Utilities.csproj">
<Project>{d6da1b74-c711-43c2-91b1-1908a8d04dbf}</Project>
<Name>DTS.Common.Utilities</Name>
</ProjectReference>
<ProjectReference Include="..\..\Common\DTS.Common\DTS.Common.csproj">
<Project>{f7a0804f-61a4-40ae-83d0-f1137622b592}</Project>
<Name>DTS.Common</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="Design\UsersClassDiagram.cd" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,53 @@
using System;
using System.Linq;
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users.UserSettings
{
/// <summary>
/// this PropertyId attribute is a little more complex than some of the other attributes
/// it can be associated with an enum or an integer, in the db obviously properties are keyed by
/// property id as an integer, but for convenience in code we use the enum form
/// this attribute lets you store the property id for a property and get either the id or enum value
/// </summary>
public class PropertyIdAttribute : Attribute
{
private readonly PropertyEnums.PropertyIds _propertyId;
/// <summary>
/// returns the property id from a property
/// </summary>
/// <param name="o"></param>
/// <returns></returns>
public static int GetPropertyId(System.Reflection.PropertyInfo o)
{
if (o == null) throw new NullReferenceException("GetPropertyId called on a null reference");
var attr = o.GetCustomAttributes(typeof(PropertyIdAttribute), false);
if (null == attr || 0 == attr.Length)
{
throw new NullReferenceException("GetPropertyId called on an object with no PropertyIdAttribute, object: " + o);
}
return (int)((PropertyIdAttribute)attr.First())._propertyId;
}
/// <summary>
/// returns the propertyid (as an enum) from a property
/// </summary>
/// <param name="o"></param>
/// <returns></returns>
public static PropertyEnums.PropertyIds GetPropertyIdEnum(System.Reflection.PropertyInfo o)
{
if (o == null) throw new NullReferenceException();
var attr = o.GetCustomAttributes(typeof(PropertyIdAttribute), false);
if (null == attr || 0 == attr.Length)
{
throw new NullReferenceException();
}
return ((PropertyIdAttribute)attr.First())._propertyId;
}
public PropertyIdAttribute(PropertyEnums.PropertyIds propertyId)
{
_propertyId = propertyId;
}
}
}

View File

@@ -0,0 +1,34 @@
using DTS.Common.Enums.Hardware;
using DTS.Common.Utilities.Xml;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Users.UserSettings
{
public class OptimizationSettings
{
public List<Setting> Settings { get; set; }
public OptimizationSettings()
{
}
public OptimizationSettings(string xmlOptimizationSettings)
{
Settings = XmlToObject<OptimizationSettings>.FromXml(xmlOptimizationSettings).Settings;
}
public class Setting
{
public HardwareTypes HardwareType { get; set; }
public List<TransferSpeedSampleRate> TransferSpeedSampleRateSettings { get; set; }
}
public class TransferSpeedSampleRate
{
public float MaxTransferSpeed { get; set; }
public float MinTransferSpeed { get; set; }
public double SampleRate { get; set; }
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Users")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Users")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("7baff2aa-d701-4d98-b20e-872f21431990")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,736 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Globalization;
using System.IO.Ports;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using DTS.Common;
using DTS.Common.Enums;
using DTS.Common.Enums.Sensors;
using DTS.Common.Storage;
using DTS.Common.Utilities.Logging;
namespace DTS.Slice.Users.UserSettings
{
public abstract class Defaults
{
#region Static Methods
/// <summary>
/// this function is designed to create any missing property settings if needed
/// this might happen if the database table was just created for instance
/// it will create defaults for all the settings in the db, and also settings for all users
/// currently it's used by DataPRO.App
/// </summary>
internal static void CreateAnyMissingUserSettingPropertyDefaults(Defaults userSetting)
{
//get a list of all known properties
var properties = userSetting.GetType().GetProperties();
var needToBeAdded = new Dictionary<int, PropertyInfo>();
foreach (var property in properties)
{
var id = PropertyIdAttribute.GetPropertyId(property);
needToBeAdded[id] = property;
}
//find if the property already exists in the db, if so, no need to add...
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
sql.CommandType = CommandType.Text;
sql.CommandText = "SELECT [PropertyId] from [DefaultProperties]";
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
var id = Convert.ToInt32(row["PropertyId"]);
if (needToBeAdded.ContainsKey(id))
{
needToBeAdded.Remove(id);
}
}
}
}
finally
{
sql.Connection.Dispose();
}
}
//if we have nothing to add, we are all done
if (needToBeAdded.Values.Count <= 0) return;
//otherwise add the defaults
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
var sb = new StringBuilder();
sb.Append(DbOperations.BEGIN_STATEMENT);
using (var needToBeAddedEnumerator = needToBeAdded.GetEnumerator())
{
var iIndex = 0;
while (needToBeAddedEnumerator.MoveNext())
{
var currentProperty = needToBeAddedEnumerator.Current.Value;
sb.AppendFormat(
"INSERT INTO [DefaultProperties] ([PropertyId],[PropertyName],[DefaultValue]) VALUES (@1_{0}, @2_{0}, @3_{0});",
iIndex);
DbOperations.CreateParam(sql, $"@1_{iIndex}", SqlDbType.Int,
PropertyIdAttribute.GetPropertyId(currentProperty));
DbOperations.CreateParam(sql, $"@2_{iIndex}", SqlDbType.NVarChar,
PropertyIdAttribute.GetPropertyIdEnum(currentProperty).ToString());
DbOperations.CreateParam(sql, $"@3_{iIndex}", SqlDbType.NVarChar,
GetDefaultValueAsString(currentProperty));
iIndex++;
}
}
sb.Append(DbOperations.COMMIT_STATEMENT);
sql.CommandText = sb.ToString();
DbOperations.Connection.ExecuteCommand(sql);
}
finally
{
sql.Connection.Dispose();
}
}
//finally add settings for any users we have currently
CreateMissingUserSettingProperties(needToBeAdded.Values.ToArray());
}
/// <summary>
/// creates missing user settings (for all users)
/// </summary>
/// <param name="needToBeAdded"></param>
internal static void CreateMissingUserSettingProperties(PropertyInfo[] needToBeAdded)
{
var userIds = new List<int>();
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
sql.CommandText = "SELECT ID FROM [Users]";
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
var id = Convert.ToInt32(row["ID"]);
if (!userIds.Contains(id))
{
userIds.Add(id);
}
}
}
}
finally
{
sql.Connection.Dispose();
}
}
foreach (var id in userIds)
{
CreateMissingUserSettingProperties(id, needToBeAdded);
}
}
/// <summary>
/// Inserts missing properties, and updates existing ones for given user
/// </summary>
/// <param name="id"></param>
/// <param name="allProperties"></param>
internal static void CreateOrUpdateUserSettingProperties(int id, PropertyInfo[] allProperties)
{
var existing = new HashSet<int>();
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
sql.CommandType = CommandType.Text;
sql.CommandText = "SELECT PropertyId FROM [UserProperties] WHERE UserId=@1";
DbOperations.CreateParam(sql, "@1", SqlDbType.Int, id);
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
var propertyId = Convert.ToInt32(row[0]);
existing.Add(propertyId);
}
}
}
finally
{
sql.Connection.Dispose();
}
}
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
sql.CommandType = CommandType.Text;
var index = 0;
var sb = new StringBuilder();
sb.Append(DbOperations.BEGIN_STATEMENT);
foreach (var property in allProperties)
{
var propId = PropertyIdAttribute.GetPropertyId(property);
if (existing.Contains(propId))
{
continue;
}
sb.AppendFormat(
"INSERT INTO [UserProperties] ([UserId],[PropertyId], [PropertyValue]) VALUES (@1_{0},@2_{0},@3_{0});",
index);
DbOperations.CreateParam(sql, $"@1_{index}", SqlDbType.Int, id);
DbOperations.CreateParam(sql, $"@2_{index}", SqlDbType.Int, propId);
DbOperations.CreateParam(sql, $"@3_{index}", SqlDbType.NVarChar,
GetDefaultValueAsString(property));
index++;
}
sb.Append(DbOperations.COMMIT_STATEMENT);
sql.CommandText = sb.ToString();
DbOperations.Connection.ExecuteCommand(sql);
}
finally
{
sql.Connection.Dispose();
}
}
if (existing.Any())
{
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
var index = 0;
var sb = new StringBuilder();
sb.Append(DbOperations.BEGIN_STATEMENT);
foreach (var property in allProperties)
{
var propId = PropertyIdAttribute.GetPropertyId(property);
if (!existing.Contains(propId))
{
continue;
}
sb.AppendFormat(
"UPDATE [UserProperties] SET PropertyValue=@1_{0} WHERE UserId=@2_{0} AND PropertyId=@3_{0};",
index);
DbOperations.CreateParam(sql, $"@1_{index}", SqlDbType.NVarChar,
GetUserSettingValue(id, (PropertyEnums.PropertyIds)propId, true) ?? string.Empty);
DbOperations.CreateParam(sql, $"@2_{index}", SqlDbType.Int, id);
DbOperations.CreateParam(sql, $"@3_{index}", SqlDbType.Int, propId);
index++;
}
sb.Append(DbOperations.COMMIT_STATEMENT);
sql.CommandText = sb.ToString();
sql.CommandType = CommandType.Text;
DbOperations.Connection.ExecuteCommand(sql);
}
finally { sql.Connection.Dispose(); }
}
}
}
/// <summary>
/// this funtion creates a list of settings for a specific user
/// this may happen with a new database, it's called by the
/// CreateAnyMissingUserSettingPropertyDefaults function above
/// </summary>
/// <param name="id"></param>
/// <param name="needToBeAdded"></param>
internal static void CreateMissingUserSettingProperties(int id, PropertyInfo[] needToBeAdded)
{
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
sql.CommandType = CommandType.Text;
var index = 0;
var sb = new StringBuilder();
sb.Append(DbOperations.BEGIN_STATEMENT);
foreach (var property in needToBeAdded)
{
sb.AppendFormat(
"INSERT INTO [UserProperties] ([UserId],[PropertyId], [PropertyValue]) VALUES (@1_{0},@2_{0},@3_{0});",
index);
DbOperations.CreateParam(sql, $"@1_{index}", SqlDbType.Int, id);
DbOperations.CreateParam(sql, $"@2_{index}", SqlDbType.Int,
PropertyIdAttribute.GetPropertyId(property));
DbOperations.CreateParam(sql, $"@3_{index}", SqlDbType.NVarChar,
GetDefaultValueAsString(property));
index++;
}
sb.Append(DbOperations.COMMIT_STATEMENT);
sql.CommandText = sb.ToString();
DbOperations.Connection.ExecuteCommand(sql);
}
finally
{
sql.Connection.Dispose();
}
}
}
/// <summary>
/// get an invariant version of the value for db storage
/// this is used when we create or insert a new default into the db
/// </summary>
/// <param name="property"></param>
/// <returns></returns>
internal static string GetDefaultValueAsString(PropertyInfo property)
{
if (property == null) return "";
var attr = (DefaultValueAttribute)property.GetCustomAttribute(typeof(DefaultValueAttribute));
if (attr.Value is double d)
{
return d.ToString(CultureInfo.InvariantCulture);
}
if (attr.Value is float f)
{
return f.ToString(CultureInfo.InvariantCulture);
}
return attr.Value?.ToString() ?? string.Empty;
}
/// <summary>
/// gets a collection of all settings for a given user
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
protected static Defaults GetUserSettings(int userId, Defaults settings)
{
var properties = settings.GetType().GetProperties();
//first get all properties as filled out by code
foreach (var property in properties)
{
var d = property.GetCustomAttribute<DefaultValueAttribute>();
if (d != null)
{
property.SetValue(settings, d.Value);
}
}
//next make sure we get all the defaults from the db
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_DefaultPropertiesGet.ToString();
cmd.Parameters.Add(new SqlParameter("@PropertyId", SqlDbType.Int) { Value = null });
using (var ds = DbOperations.Connection.QueryDataSet(cmd))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
var id = Convert.ToInt32(row["PropertyId"]);
var dv = Convert.ToString(row["DefaultValue"]);
settings.SetValue(id, dv);
}
}
}
catch (Exception ex) { APILogger.Log("Failed to get Default Property", ex); }
finally { cmd.Connection.Dispose(); }
}
//finally get the user specific values
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UserPropertiesGet.ToString();
cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = userId });
cmd.Parameters.Add(new SqlParameter("@PropertyId", SqlDbType.Int) { Value = null });
using (var ds = DbOperations.Connection.QueryDataSet(cmd))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
var id = Convert.ToInt32(row["PropertyId"]);
var value = Convert.ToString(row["PropertyValue"]);
settings.SetValue(id, value);
}
}
}
catch (Exception ex) { APILogger.Log("Failed to get User Property", ex); }
finally
{
cmd.Connection.Dispose();
}
}
//if a user setting for a defaults type wasn't found, handle it in the inherited class
return settings;
}
protected static Defaults _allUserSettings = null;
/// <summary>
/// sets a specific user setting in the db
/// function should handle the invariant nature of values
/// </summary>
/// <param name="userId"></param>
/// <param name="id"></param>
/// <param name="value"></param>
public static void SetUserSetting(int userId, PropertyEnums.PropertyIds id, object value)
{
var sValue = value.ToString();
if (value is double d)
{
sValue = d.ToString(CultureInfo.InvariantCulture);
}
else if (value is float f)
{
sValue = f.ToString(CultureInfo.InvariantCulture);
}
try
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UserPropertiesUpdateInsert.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = userId });
cmd.Parameters.Add(new SqlParameter("@PropertyId", SqlDbType.Int) { Value = (int)id });
cmd.Parameters.Add(new SqlParameter("@PropertyValue", SqlDbType.NVarChar) { Value = sValue });
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
catch (Exception ex) { APILogger.Log("Failed to set User Property", ex); }
finally
{
cmd.Connection.Dispose();
}
}
}
catch (Exception ex) { APILogger.LogException(ex); }
}
/// <summary>
/// inserts a default setting into the db
/// written for 18028 Remember test id suffix drop down state
/// this is in place of a migration script and updating the db when there's a new user
/// setting, instead if a setting is absent we can insert one
/// </summary>
public static void InsertUserSetting(PropertyEnums.PropertyIds property, string value)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandText =
"INSERT INTO [DefaultProperties] ([PropertyId],[PropertyName],[DefaultValue]) VALUES (@1,@2,@3)";
cmd.Parameters.Add(new SqlParameter("@1", SqlDbType.Int) { Value = (int)property });
cmd.Parameters.Add(new SqlParameter("@2", SqlDbType.NVarChar, 255) { Value = property.ToString() });
cmd.Parameters.Add(new SqlParameter("@3", SqlDbType.NVarChar, 255) { Value = value });
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
APILogger.Log(ex);
}
finally
{
cmd.Connection.Dispose();
}
}
}
/// <summary>
/// gets a specific user setting as a bool
/// </summary>
/// <param name="userId"></param>
/// <param name="property"></param>
/// <param name="defaultValue">optional parameter allowing inserting a setting if absent</param>
/// <returns></returns>
public static bool GetUserSettingValueBool(int userId, PropertyEnums.PropertyIds property, bool? defaultValue = false)
{
var defaultV = false;
var val = GetUserSettingValue(userId, property);
if (null != defaultValue && null == val)
{
//if we get here the user supplied a default value for the property
//and the property is not in the db, so insert it
InsertUserSetting(property, ((bool)defaultValue).ToString());
return (bool)defaultValue;
}
//if the string is empty or null, it won't convert, so just return the default
//otherwise return the converted value
return string.IsNullOrWhiteSpace(val) ? defaultV : Convert.ToBoolean(val);
}
/// <summary>
/// gets a specific user setting as a double
/// </summary>
/// <param name="userId"></param>
/// <param name="property"></param>
/// <returns></returns>
public static double GetUserSettingValueDouble(int userId, PropertyEnums.PropertyIds property)
{
return Convert.ToDouble(GetUserSettingValue(userId, property) ?? "0", CultureInfo.InvariantCulture);
}
/// <summary>
/// gets a specific user setting as an integer
/// </summary>
/// <param name="userId"></param>
/// <param name="property"></param>
/// <returns></returns>
public static int GetUserSettingValueInt(int userId, PropertyEnums.PropertyIds property)
{
return Convert.ToInt32(GetUserSettingValue(userId, property) ?? "0", CultureInfo.InvariantCulture);
}
/// <summary>
/// Gets a specific user setting as a string
/// </summary>
/// <param name="userid"></param>
/// <param name="property"></param>
/// <param name="defaultValue">optional parameter, if specified and the property is missing will insert the property</param>
/// <returns></returns>
public static string GetUserSettingValueString(int userid, PropertyEnums.PropertyIds property, string defaultValue = null)
{
return GetUserSettingValue(userid, property, true, defaultValue) ?? string.Empty;
}
/// <summary>
/// gets a user setting out of the db, this is an internal function used by all the public
/// single setting accessors.
/// setting is determined by user settings table, default values table
/// </summary>
/// <param name="userId"></param>
/// <param name="propertyId">numeric id if the property</param>
/// <param name="dontUseCache">whether to use cache when retrieving property value</param>
/// <param name="defaultValue">optional parameter, if setting is missing will insert property with this default value</param>
/// <returns></returns>
private static string GetUserSettingValue(int userId,
PropertyEnums.PropertyIds propertyId,
bool dontUseCache = true,
string defaultValue = null)
{
if (_allUserSettings != null && !dontUseCache)
{
var properties = _allUserSettings.GetType().GetProperties();
foreach (var prop in properties)
{
var id = PropertyIdAttribute.GetPropertyId(prop);
if (id == (int)propertyId) { return GetDefaultValueAsString(prop); }
}
}
//if the user has a specific value set for this property, just return it directly
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UserPropertiesGet.ToString();
cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = userId });
cmd.Parameters.Add(new SqlParameter("@PropertyId", SqlDbType.Int) { Value = propertyId });
using (var ds = DbOperations.Connection.QueryDataSet(cmd))
{
if (ds.Tables[0].Rows.Count > 0)
{
return Convert.ToString(ds.Tables[0].Rows[0]["PropertyValue"]);
}
}
}
catch (Exception ex) { APILogger.Log("failed to retrieve user setting, ", ex); }
finally
{
cmd.Connection.Dispose();
}
}
//if there exists a specific default value set for this property, return that
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_DefaultPropertiesGet.ToString();
cmd.Parameters.Add(new SqlParameter("@PropertyId", SqlDbType.Int) { Value = propertyId });
using (var ds = DbOperations.Connection.QueryDataSet(cmd))
{
if (ds.Tables[0].Rows.Count > 0)
{
return Convert.ToString(ds.Tables[0].Rows[0]["DefaultValue"]);
}
//there's no value, no default value, setting is unknown
//if we have a default value go ahead and insert a setting
else if (null != defaultValue)
{
InsertUserSetting(propertyId, defaultValue);
}
}
}
catch (Exception ex) { APILogger.Log("failed to retrieve default setting, ", ex); }
finally { cmd.Connection.Dispose(); }
}
//FB16165: we can get here if the db connection drops. It's been noted in the logs, so don't crash
return null;
}
#endregion
#region methods
/// <summary>
/// sets a specific value given a property id
/// this is used when deserializing values out of the db
///
/// </summary>
/// <param name="id"></param>
/// <param name="dv"></param>
protected abstract void SetValue(int id, string dv);
/// <summary>
/// resets all the settings for a user in the db, using the default settings in the db
/// </summary>
/// <param name="userId"></param>
public void ResetUserSettings(int userId)
{
//TODO: move to stored procedure
//you can do this with one command with SQL, ie like
//http://stackoverflow.com/questions/224732/sql-update-from-one-table-to-another-based-on-a-id-match
//but since we haven't ditched SQlite yet, lets include support for both by separating it into two statements
var properties = new List<Tuple<int, string>>();
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_DefaultPropertiesGet.ToString();
cmd.Parameters.Add(new SqlParameter("@PropertyId", SqlDbType.Int) { Value = null });
using (var ds = DbOperations.Connection.QueryDataSet(cmd))
{
properties.AddRange(from DataRow row in ds.Tables[0].Rows
let id = Convert.ToInt32(row["PropertyId"])
let value = Convert.ToString(row["DefaultValue"])
select new Tuple<int, string>(id, value));
}
}
finally
{
cmd.Connection.Dispose();
}
}
foreach (var property in properties)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UserPropertiesUpdateInsert.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = userId });
cmd.Parameters.Add(
new SqlParameter("@PropertyId", SqlDbType.Int) { Value = property.Item1 });
cmd.Parameters.Add(
new SqlParameter("@PropertyValue", SqlDbType.NVarChar) { Value = property.Item2 });
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
}
}
#endregion
}
/// <summary>
/// Subcategory example
/// </summary>
[TypeConverter(typeof(ExpandableObjectConverter))]
public class SubCategory1
{
public string Property1 { get; set; }
public string Property2 { get; set; }
public override string ToString()
{
return string.Empty;
}
}
[TypeConverter(typeof(ExpandableObjectConverter))]
public class SubCategory2
{
public string Property3 { get; set; }
public override string ToString()
{
return string.Empty;
}
}
}

View File

@@ -0,0 +1,143 @@
namespace DTS.Slice.Users
{
partial class ChallengeDialog
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.tbPassword = new System.Windows.Forms.TextBox();
this.lblLoginFailedMessage = new System.Windows.Forms.Label();
this.btnCancel = new System.Windows.Forms.Button();
this.btnContinue = new System.Windows.Forms.Button();
this.label2 = new System.Windows.Forms.Label();
this.tableLayoutPanel1.SuspendLayout();
this.SuspendLayout();
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.ColumnCount = 2;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel1.Controls.Add(this.tbPassword, 0, 2);
this.tableLayoutPanel1.Controls.Add(this.lblLoginFailedMessage, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.btnCancel, 1, 3);
this.tableLayoutPanel1.Controls.Add(this.btnContinue, 0, 3);
this.tableLayoutPanel1.Controls.Add(this.label2, 0, 0);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(10);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 4;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.64378F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.Size = new System.Drawing.Size(632, 120);
this.tableLayoutPanel1.TabIndex = 0;
//
// tbPassword
//
this.tbPassword.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.tableLayoutPanel1.SetColumnSpan(this.tbPassword, 2);
this.tbPassword.Location = new System.Drawing.Point(3, 66);
this.tbPassword.Name = "tbPassword";
this.tbPassword.PasswordChar = '*';
this.tbPassword.Size = new System.Drawing.Size(626, 22);
this.tbPassword.TabIndex = 1;
this.tbPassword.UseSystemPasswordChar = true;
//
// lblLoginFailedMessage
//
this.lblLoginFailedMessage.AutoSize = true;
this.tableLayoutPanel1.SetColumnSpan(this.lblLoginFailedMessage, 2);
this.lblLoginFailedMessage.Dock = System.Windows.Forms.DockStyle.Fill;
this.lblLoginFailedMessage.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.lblLoginFailedMessage.ForeColor = System.Drawing.Color.DarkRed;
this.lblLoginFailedMessage.Location = new System.Drawing.Point(3, 45);
this.lblLoginFailedMessage.Name = "lblLoginFailedMessage";
this.lblLoginFailedMessage.Size = new System.Drawing.Size(626, 18);
this.lblLoginFailedMessage.TabIndex = 2;
this.lblLoginFailedMessage.Text = "Login failed";
this.lblLoginFailedMessage.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// btnCancel
//
this.btnCancel.Location = new System.Drawing.Point(319, 94);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 4;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
//
// btnContinue
//
this.btnContinue.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.btnContinue.Location = new System.Drawing.Point(238, 94);
this.btnContinue.Name = "btnContinue";
this.btnContinue.Size = new System.Drawing.Size(75, 23);
this.btnContinue.TabIndex = 5;
this.btnContinue.Text = "Continue";
this.btnContinue.UseVisualStyleBackColor = true;
//
// label2
//
this.label2.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.label2.AutoSize = true;
this.tableLayoutPanel1.SetColumnSpan(this.label2, 2);
this.label2.Location = new System.Drawing.Point(18, 0);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(595, 34);
this.label2.TabIndex = 6;
this.label2.Text = "Admin access needed to update Master User db. Please enter the Adminsitrator pas" +
"sword to continue or press cancel to skip updating the master.";
this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// ChallengeDialog
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(632, 120);
this.Controls.Add(this.tableLayoutPanel1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
this.Name = "ChallengeDialog";
this.Text = "Admin Access Needed";
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.TextBox tbPassword;
private System.Windows.Forms.Label lblLoginFailedMessage;
private System.Windows.Forms.Button btnCancel;
private System.Windows.Forms.Button btnContinue;
private System.Windows.Forms.Label label2;
}
}

View File

@@ -0,0 +1,37 @@
using System.ComponentModel;
using Users.UserSettings;
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users.UserSettings
{
/// <summary>
/// this class overloads the description attribute to allow us to use an enum
/// to set the description and to lookup the description in the string resources
/// to be translated the property should have a string resource in the form of PropertyName_Description
/// otherwise ##DescriptionNotFound## will be returned as the translated string
/// </summary>
public class DescriptionAttributeEx : DescriptionAttribute
{
private readonly PropertyEnums.PropertyIds _propertyId;
private readonly string _propertyIdString = null;
public DescriptionAttributeEx(PropertyEnums.PropertyIds propertyId)
{
_propertyId = propertyId;
}
public DescriptionAttributeEx(string propertyId)
{
_propertyIdString = propertyId;
}
public override string Description
{
get
{
if (!string.IsNullOrEmpty(_propertyIdString))
{
return StringResources.ResourceManager.GetString(_propertyIdString + "_Description") ?? @"##DescriptionNotFound##" + _propertyIdString;
}
return StringResources.ResourceManager.GetString(_propertyId + "_Description") ?? @"##DescriptionNotFound##" + _propertyId;
}
}
}
}

View File

@@ -0,0 +1,741 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using DTS.Storage;
// ReSharper disable RedundantEmptyDefaultSwitchBranch
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users.UserSettings
{
/// <summary>
/// user specific properties, stored in db
///
/// these are all the user specific settings we are storing in the db currently as generic settings
/// we have a few user specific settings like last used hardware that are stored in other places, that maybe
/// should be stored here as well
///
/// it's possible to retrieve all the settings at once (more efficient, only one db query), or retrieve settings individually
/// one by one using the static accessors
/// each setting has a default specified both in code and in the db.
/// when retrieving a setting we fall back to the default if a user specific value is not found
/// if the default setting in the db is not found, we can further fall back to the default specified in code
///
/// in the db we have a table that lists all the settings with their fall back default value
/// we have a separate table that stores the user specific values for any of those settings, which may or may not match the fall
/// back default value
///
/// the data should always be stored in invariant form in the db
/// DisplayName, Description attributes translate so the properties can be displayed in a property grid
/// </summary>
public class UserSettings
{
#region properties
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultUploadEnabled)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultUploadEnabled)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultUploadEnabled)]
[DefaultValue(false)]
public bool UploadDefault { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultTestSampleRate)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultTestSampleRate)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultTestSampleRate)]
[DefaultValue(10000D)]
public double DefaultSampleRate { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultPostTriggerSeconds)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultPostTriggerSeconds)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultPostTriggerSeconds)]
[DefaultValue(1D)]
public double DefaultPostTriggerSeconds { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultPreTriggerSeconds)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultPreTriggerSeconds)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultPreTriggerSeconds)]
[DefaultValue(1D)]
public double DefaultPreTriggerSeconds { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultTriggerCheckStep)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultTriggerCheckStep)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultTriggerCheckStep)]
[DefaultValue(true)]
public bool DefaultTriggerCheckStep { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultRealtimeGraphCount)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultRealtimeGraphCount)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultRealtimeGraphCount)]
[DefaultValue(6)]
public int DefaultRealtimeGraphCount { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultROIStart)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultROIStart)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultROIStart)]
[DefaultValue(-1D)]
public double DefaultROIStart { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultROIEnd)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultROIEnd)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultROIEnd)]
[DefaultValue(1D)]
public double DefaultROIEnd { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultDownloadROI)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultDownloadROI)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultDownloadROI)]
[DefaultValue(true)]
public bool DefaultDownloadROI { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultViewROI)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultViewROI)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultViewROI)]
[DefaultValue(true)]
public bool DefaultViewROI { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultDownloadAll)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultDownloadAll)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultDownloadAll)]
[DefaultValue(true)]
public bool DefaultDownloadAll { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultViewAll)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultViewAll)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultViewAll)]
[DefaultValue(false)]
public bool DefaultViewAll { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultRequireAllUnitsPassDiagnostics)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultRequireAllUnitsPassDiagnostics)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultRequireAllUnitsPassDiagnostics)]
[DefaultValue(true)]
public bool DefaultRequireAllUnitsPassDiagnostics { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultRequireUserConfirmationOnErrors)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultRequireUserConfirmationOnErrors)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultRequireUserConfirmationOnErrors)]
[DefaultValue(true)]
public bool DefaultRequireUserConfirmationOnErrors { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultAllowMissingSensors)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultAllowMissingSensors)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultAllowMissingSensors)]
[DefaultValue(false)]
public bool DefaultAllowMissingSensors { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultRunPostTestDiagnostics)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultRunPostTestDiagnostics)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultRunPostTestDiagnostics)]
[DefaultValue(false)]
public bool DefaultRunPostTestDiagnostics { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultArmCheckListStep)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultArmCheckListStep)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultArmCheckListStep)]
[DefaultValue(false)]
public bool DefaultArmCheckListStep { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultCheckListInputVoltageCheck)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListInputVoltageCheck)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListInputVoltageCheck)]
[DefaultValue(true)]
public bool DefaultCheckListInputVoltageCheck { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultCheckListBatteryVoltageCheck)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListBatteryVoltageCheck)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListBatteryVoltageCheck)]
[DefaultValue(true)]
public bool DefaultCheckListBatteryVoltageCheck { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultCheckListSquibResistanceCheck)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListSquibResistanceCheck)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListSquibResistanceCheck)]
[DefaultValue(true)]
public bool DefaultCheckListSquibResistanceCheck { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultCheckListSensorIdCheck)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListSensorIdCheck)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListSensorIdCheck)]
[DefaultValue(true)]
public bool DefaultCheckListSensorIdCheck { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultCheckListTriggerStartCheck)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListTriggerStartCheck)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListTriggerStartCheck)]
[DefaultValue(true)]
public bool DefaultCheckListTriggerStartCheck { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultCheckListTiltSensorCheck)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListTiltSensorCheck)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListTiltSensorCheck)]
[DefaultValue(true)]
public bool DefaultCheckListTiltSensorCheck { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultAllowSensorIdToBlankChannel)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultAllowSensorIdToBlankChannel)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultAllowSensorIdToBlankChannel)]
[DefaultValue(true)]
public bool DefaultAllowSensorIdToBlankChannel { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultCheckListMustPass)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListMustPass)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListMustPass)]
[DefaultValue(false)]
public bool DefaultChecklistMustPass { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultViewRealtime)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultViewRealtime)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultViewRealtime)]
[DefaultValue(true)]
public bool DefaultViewRealtime { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultExport)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultExport)]
[PropertyId(PropertyEnums.PropertyIds.DefaultExport)]
[DefaultValue(false)]
public bool DefaultExport { get; set; }
[DefaultValue(0)]
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultExportFormat)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultExportFormat)]
[PropertyId(PropertyEnums.PropertyIds.DefaultExportFormat)]
public int DefaultExportFormat { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.RealtimeSettings)]
[PropertyId(PropertyEnums.PropertyIds.RealtimeChartWidthInSeconds)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.RealtimeChartWidthInSeconds)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.RealtimeChartWidthInSeconds)]
[DefaultValue(2)]
public double RealtimeChartWidthInSeconds { get; set; }
[DefaultValue(true)]
[CategoryAttributeEx(PropertyEnums.PropertyCategories.TestOptions)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultTreeModeDiagnostics)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultTreeModeDiagnostics)]
[PropertyId(PropertyEnums.PropertyIds.DefaultTreeModeDiagnostics)]
public bool DefaultTreeModeDiagnostics { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.TestOptions)]
[PropertyId(PropertyEnums.PropertyIds.ArmChecklistRequiredIfTOM)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.ArmChecklistRequiredIfTOM)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.ArmChecklistRequiredIfTOM)]
[DefaultValue(true)]
public bool ArmChecklistRequiredIfTOM { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.TestOptions)]
[PropertyId(PropertyEnums.PropertyIds.DefaultSuppressMissingSensorsWarning)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultSuppressMissingSensorsWarning)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultSuppressMissingSensorsWarning)]
[DefaultValue(true)]
public bool DefaultSuppressMissingSensorsWarning { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.TestOptions)]
[PropertyId(PropertyEnums.PropertyIds.ArmTriggerDiagnosticsRunOnNextStep)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.ArmTriggerDiagnosticsRunOnNextStep)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.ArmTriggerDiagnosticsRunOnNextStep)]
[DefaultValue(false)]
public bool ArmTriggerDiagnosticsRunOnNextStep { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.UserHistory)]
[PropertyId(PropertyEnums.PropertyIds.UsersCurrentTestSetup)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.UsersCurrentTestSetup)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.UsersCurrentTestSetup)]
[DefaultValue("")]
[ReadOnly(true)]
public string UsersCurrentTestSetup { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.UserHistory)]
[PropertyId(PropertyEnums.PropertyIds.LastRunTestSetup)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.LastRunTestSetup)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.LastRunTestSetup)]
[DefaultValue("")]
[ReadOnly(true)]
public string LastRunTestSetup { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.UserHistory)]
[PropertyId(PropertyEnums.PropertyIds.LastUsedSampleRate)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.LastUsedSampleRate)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.LastUsedSampleRate)]
[DefaultValue(20000D)]
[ReadOnly(true)]
public double LastUsedSampleRate { get; set; }
/*
* Subcategory example
*/
//[Category("Category1")]
//public SubCategory1 Subcategory1 { get; set; }
//[Category("Category1")]
//public SubCategory2 Subcategory2 { get; set; }
#endregion properties
#region Static Methods
/// <summary>
/// this function is designed to create any missing property settings if needed
/// this might happen if the database table was just created for instance
/// it will create defaults for all the settings in the db, and also settings for all users
/// currently it's used by DataPRO.App
/// </summary>
public static void CreateAnyMissingUserSettingPropertyDefaults()
{
//get a list of all known properties
var userSetting = new UserSettings();
var properties = userSetting.GetType().GetProperties();
var needToBeAdded = new Dictionary<int, PropertyInfo>();
foreach (var property in properties)
{
var id = PropertyIdAttribute.GetPropertyId(property);
needToBeAdded[id] = property;
}
//find if the property already exists in the db, if so, no need to add...
using (var sql = DbOperations.GetCommand())
{
sql.CommandText = "SELECT [PropertyId] from [DefaultProperties]";
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
var id = Convert.ToInt32(row["PropertyId"]);
if (needToBeAdded.ContainsKey(id))
{
needToBeAdded.Remove(id);
}
}
}
}
//if we have nothing to add, we are all done
if (needToBeAdded.Values.Count <= 0) return;
//otherwise add the defaults
using (var sql = DbOperations.GetCommand())
{
var sb = new StringBuilder();
sb.Append(DbOperations.BEGIN_STATEMENT);
var needToBeAddedEnumerator = needToBeAdded.GetEnumerator();
int iIndex = 0;
while (needToBeAddedEnumerator.MoveNext())
{
var currentProperty = needToBeAddedEnumerator.Current.Value;
sb.AppendFormat("INSERT INTO [DefaultProperties] ([PropertyId],[PropertyName],[DefaultValue]) VALUES (@1_{0}, @2_{0}, @3_{0});", iIndex);
DbOperations.CreateParam(sql, string.Format("@1_{0}", iIndex), SqlDbType.Int, PropertyIdAttribute.GetPropertyId(currentProperty));
DbOperations.CreateParam(sql, string.Format("@2_{0}", iIndex), SqlDbType.NVarChar, PropertyIdAttribute.GetPropertyIdEnum(currentProperty).ToString());
DbOperations.CreateParam(sql, string.Format("@3_{0}", iIndex), SqlDbType.NVarChar, GetDefaultValueAsString(currentProperty));
iIndex++;
}
sb.Append(DbOperations.COMMIT_STATEMENT);
sql.CommandText = sb.ToString();
DbOperations.Connection.ExecuteCommand(sql);
}
//finally add settings for any users we have currently
CreateMissingUserSettingProperties(needToBeAdded.Values.ToArray());
}
/// <summary>
/// creates missing user settings (for all users)
/// </summary>
/// <param name="needToBeAdded"></param>
private static void CreateMissingUserSettingProperties(PropertyInfo[] needToBeAdded)
{
var userIds = new List<int>();
using (var sql = DbOperations.GetCommand())
{
sql.CommandText = "SELECT ID FROM [DataPROUsers]";
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
var id = Convert.ToInt32(row["ID"]);
if (!userIds.Contains(id))
{
userIds.Add(id);
}
}
}
}
foreach (var id in userIds)
{
CreateMissingUserSettingProperties(id, needToBeAdded);
}
}
/// <summary>
/// this funtion creates a list of settings for a specific user
/// this may happen with a new database, it's called by the
/// CreateAnyMissingUserSettingPropertyDefaults function above
/// </summary>
/// <param name="id"></param>
/// <param name="needToBeAdded"></param>
internal static void CreateMissingUserSettingProperties(int id, PropertyInfo[] needToBeAdded)
{
using (var sql = DbOperations.GetCommand())
{
var index = 0;
var sb = new StringBuilder();
sb.Append(DbOperations.BEGIN_STATEMENT);
foreach (var property in needToBeAdded)
{
sb.AppendFormat(
"INSERT INTO [UserProperties] ([UserId],[PropertyId], [PropertyValue]) VALUES (@1_{0},@2_{0},@3_{0});",
index);
DbOperations.CreateParam(sql, string.Format("@1_{0}", index), SqlDbType.Int, id);
DbOperations.CreateParam(sql, string.Format("@2_{0}", index), SqlDbType.Int,
PropertyIdAttribute.GetPropertyId(property));
DbOperations.CreateParam(sql, string.Format("@3_{0}", index), SqlDbType.NVarChar,
GetDefaultValueAsString(property));
index++;
}
sb.Append(DbOperations.COMMIT_STATEMENT);
sql.CommandText = sb.ToString();
DbOperations.Connection.ExecuteCommand(sql);
}
}
/// <summary>
/// get an invariant version of the value for db storage
/// this is used when we create or insert a new default into the db
/// </summary>
/// <param name="property"></param>
/// <returns></returns>
private static string GetDefaultValueAsString(PropertyInfo property)
{
if (property == null) return "";
var attr = (DefaultValueAttribute)property.GetCustomAttribute(typeof(DefaultValueAttribute));
if (attr.Value is double)
{
return ((double) attr.Value).ToString(CultureInfo.InvariantCulture);
}
if (attr.Value is float)
{
return ((float) attr.Value).ToString(CultureInfo.InvariantCulture);
}
return attr.Value.ToString();
}
/// <summary>
/// gets a collection of all settings for a given user
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public static UserSettings GetUserSettings(int userId)
{
var settings = new UserSettings();
var properties = settings.GetType().GetProperties();
//first get all properties as filled out by code
foreach (var property in properties)
{
var d = property.GetCustomAttribute<DefaultValueAttribute>();
if (d != null)
{
property.SetValue(settings, d.Value);
}
}
//next make sure we get all the defaults from the db
using (var sql = DbOperations.GetCommand())
{
sql.CommandText = "SELECT [PropertyId], [DefaultValue] from [DefaultProperties]";
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
var id = Convert.ToInt32(row["PropertyId"]);
var dv = Convert.ToString(row["DefaultValue"]);
settings.SetValue(id, dv);
}
}
}
//finally get the user specific values
using (var sql = DbOperations.GetCommand())
{
sql.CommandText = "SELECT [PropertyId], [PropertyValue] FROM [UserProperties] WHERE [UserId]=@1";
DbOperations.CreateParam(sql, "@1", SqlDbType.Int, userId);
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
var id = Convert.ToInt32(row["PropertyId"]);
var value = Convert.ToString(row["PropertyValue"]);
settings.SetValue(id, value);
}
}
}
return settings;
}
/// <summary>
/// sets a specific user setting in the db
/// function should handle the invariant nature of values
/// </summary>
/// <param name="userId"></param>
/// <param name="id"></param>
/// <param name="value"></param>
public static void SetUserSetting(int userId, PropertyEnums.PropertyIds id, object value)
{
var sValue = value.ToString();
if (value is double)
{
sValue = ((double)value).ToString(CultureInfo.InvariantCulture);
}
else if (value is float)
{
sValue = ((float)value).ToString(CultureInfo.InvariantCulture);
}
using (var sql = DbOperations.GetCommand())
{
sql.CommandText = "UPDATE [UserProperties] SET [PropertyValue]=@1 WHERE [UserId]=@2 AND [PropertyId]=@3";
DbOperations.CreateParam(sql, "@1", SqlDbType.NVarChar, sValue);
DbOperations.CreateParam(sql, "@2", SqlDbType.Int, userId);
DbOperations.CreateParam(sql, "@3", SqlDbType.Int, (int)id);
DbOperations.Connection.ExecuteCommand(sql);
}
}
/// <summary>
/// gets a specific user setting as a bool
/// </summary>
/// <param name="userId"></param>
/// <param name="property"></param>
/// <returns></returns>
public static bool GetUserSettingValueBool(int userId, PropertyEnums.PropertyIds property)
{
return Convert.ToBoolean(GetUserSettingValue(userId, property));
}
/// <summary>
/// gets a specific user setting as a double
/// </summary>
/// <param name="userId"></param>
/// <param name="property"></param>
/// <returns></returns>
public static double GetUserSettingValueDouble(int userId, PropertyEnums.PropertyIds property)
{
return Convert.ToDouble(GetUserSettingValue(userId, property), CultureInfo.InvariantCulture);
}
/// <summary>
/// gets a specific user setting as an integer
/// </summary>
/// <param name="userId"></param>
/// <param name="property"></param>
/// <returns></returns>
public static int GetUserSettingValueInt(int userId, PropertyEnums.PropertyIds property)
{
return Convert.ToInt32(GetUserSettingValue(userId, property), CultureInfo.InvariantCulture);
}
/// <summary>
/// Gets a specific user setting as a string
/// </summary>
/// <param name="userid"></param>
/// <param name="property"></param>
/// <returns></returns>
public static string GetUserSettingValueString(int userid, PropertyEnums.PropertyIds property)
{
return GetUserSettingValue(userid, property);
}
/// <summary>
/// gets a user setting out of the db, this is an internal function used by all the public
/// single setting accessors.
/// setting is determined by user settings table, default values table
/// </summary>
/// <param name="userid"></param>
/// <param name="property"></param>
/// <returns></returns>
private static string GetUserSettingValue(int userid, PropertyEnums.PropertyIds property)
{
//if the user has a specific value set for this property, just return it directly
using (var sql = DbOperations.GetCommand())
{
sql.CommandText = "SELECT [PropertyValue] FROM [UserProperties] WHERE [UserId]=@1 AND [PropertyId]=@2";
DbOperations.CreateParam(sql, "@1", SqlDbType.Int, userid);
DbOperations.CreateParam(sql, "@2", SqlDbType.Int, (int)property);
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
if (ds.Tables[0].Rows.Count > 0)
{
return Convert.ToString(ds.Tables[0].Rows[0]["PropertyValue"]);
}
}
}
//if there exists a specific default value set for this property, return that
using (var sql = DbOperations.GetCommand())
{
sql.CommandText = "SELECT [DefaultValue] FROM [DefaultProperties] WHERE [PropertyId] =@1";
DbOperations.CreateParam(sql, "@1", SqlDbType.Int, (int)property);
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
if (ds.Tables[0].Rows.Count > 0)
{
return Convert.ToString(ds.Tables[0].Rows[0]["DefaultValue"]);
}
}
}
//we could return the default value in code here, but we don't expect to get here, so
//we can treat this as an exception for now
throw new NullReferenceException(property.ToString());
}
#endregion
#region methods
/// <summary>
/// sets a specific value given a property id
/// this is used when deserializing values out of the db
///
/// </summary>
/// <param name="id"></param>
/// <param name="dv"></param>
protected void SetValue(int id, string dv)
{
var property = (PropertyEnums.PropertyIds)id;
switch (property)
{
case PropertyEnums.PropertyIds.ArmChecklistRequiredIfTOM: ArmChecklistRequiredIfTOM = Convert.ToBoolean(dv); break;
case PropertyEnums.PropertyIds.ArmTriggerDiagnosticsRunOnNextStep: ArmTriggerDiagnosticsRunOnNextStep = Convert.ToBoolean(dv); break;
case PropertyEnums.PropertyIds.DefaultAllowMissingSensors: DefaultAllowMissingSensors = Convert.ToBoolean(dv); break;
case PropertyEnums.PropertyIds.DefaultAllowSensorIdToBlankChannel: DefaultAllowSensorIdToBlankChannel = Convert.ToBoolean(dv); break;
case PropertyEnums.PropertyIds.DefaultArmCheckListStep: DefaultArmCheckListStep = Convert.ToBoolean(dv); break;
case PropertyEnums.PropertyIds.DefaultCheckListBatteryVoltageCheck: DefaultCheckListBatteryVoltageCheck = Convert.ToBoolean(dv); break;
case PropertyEnums.PropertyIds.DefaultUploadEnabled: UploadDefault = Convert.ToBoolean(dv); break;
case PropertyEnums.PropertyIds.DefaultTestSampleRate: DefaultSampleRate = Convert.ToDouble(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultPostTriggerSeconds: DefaultPostTriggerSeconds = Convert.ToDouble(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultPreTriggerSeconds: DefaultPreTriggerSeconds = Convert.ToDouble(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultTriggerCheckStep: DefaultTriggerCheckStep = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultRealtimeGraphCount: DefaultRealtimeGraphCount = Convert.ToInt32(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultROIStart: DefaultROIStart = Convert.ToDouble(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultROIEnd: DefaultROIEnd = Convert.ToDouble(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultDownloadROI: DefaultDownloadROI = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultViewROI: DefaultViewROI = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultDownloadAll: DefaultDownloadAll = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultViewAll: DefaultViewAll = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultRequireAllUnitsPassDiagnostics: DefaultRequireAllUnitsPassDiagnostics = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultRequireUserConfirmationOnErrors: DefaultRequireUserConfirmationOnErrors = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultRunPostTestDiagnostics: DefaultRunPostTestDiagnostics = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultCheckListInputVoltageCheck: DefaultCheckListInputVoltageCheck = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultCheckListSquibResistanceCheck: DefaultCheckListSquibResistanceCheck = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultCheckListSensorIdCheck: DefaultCheckListSensorIdCheck = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultCheckListTriggerStartCheck: DefaultCheckListTriggerStartCheck = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultCheckListTiltSensorCheck: DefaultCheckListTiltSensorCheck = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultCheckListMustPass: DefaultChecklistMustPass = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultViewRealtime: DefaultViewRealtime = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultExport: DefaultExport = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultExportFormat: DefaultExportFormat = Convert.ToInt32(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.RealtimeChartWidthInSeconds: RealtimeChartWidthInSeconds = Convert.ToDouble(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultTreeModeDiagnostics: DefaultTreeModeDiagnostics = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultSuppressMissingSensorsWarning: DefaultSuppressMissingSensorsWarning = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.UsersCurrentTestSetup: UsersCurrentTestSetup = dv; break;
case PropertyEnums.PropertyIds.LastRunTestSetup: LastRunTestSetup = dv; break;
case PropertyEnums.PropertyIds.LastUsedSampleRate: LastUsedSampleRate = Convert.ToDouble(dv, CultureInfo.InvariantCulture); break;
default:
break;//ignore unknown property, just just ignore it
}
}
/// <summary>
/// resets all the settings for a user in the db, using the default settings in the db
/// </summary>
/// <param name="userId"></param>
public void ResetUserSettings(int userId)
{
//you can do this with one command with SQL, ie like
//http://stackoverflow.com/questions/224732/sql-update-from-one-table-to-another-based-on-a-id-match
//but since we haven't ditched SQlite yet, lets include support for both by separating it into two statements
var properties = new List<Tuple<int, string>>();
using (var sql = DbOperations.GetCommand())
{
sql.CommandText = "SELECT [PropertyId],[DefaultValue] from [DefaultProperties]";
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
properties.AddRange(from DataRow row in ds.Tables[0].Rows let id = Convert.ToInt32(row["PropertyId"]) let value = Convert.ToString(row["DefaultValue"]) select new Tuple<int, string>(id, value));
}
}
using (var sql = DbOperations.GetCommand())
{
var sb = new StringBuilder();
sb.Append(DbOperations.BEGIN_STATEMENT);
for (var i = 0; i < properties.Count; i ++)
{
sb.AppendFormat("UPDATE [UserProperties] SET [PropertyValue]=@1_{0} WHERE [PropertyId]=@2_{0} AND [UserId]=@3_{0};",i);
DbOperations.CreateParam(sql, string.Format("@1_{0}", i), SqlDbType.NVarChar, properties[i].Item2);
DbOperations.CreateParam(sql, string.Format("@2_{0}", i), SqlDbType.Int, properties[i].Item1);
DbOperations.CreateParam(sql, string.Format("@3_{0}",i), SqlDbType.Int, userId);
}
sb.Append(DbOperations.COMMIT_STATEMENT);
sql.CommandText = sb.ToString();
DbOperations.Connection.ExecuteCommand(sql);
}
}
#endregion
}
/// <summary>
/// Subcategory example
/// http://stackoverflow.com/questions/9379353/category-hierarchy-in-winforms-propertygrid
/// </summary>
[TypeConverter(typeof(ExpandableObjectConverter))]
public class SubCategory1
{
public String Property1 { get; set; }
public String Property2 { get; set; }
public override string ToString()
{
return String.Empty;
}
}
[TypeConverter(typeof(ExpandableObjectConverter))]
public class SubCategory2
{
public String Property3 { get; set; }
public override string ToString()
{
return String.Empty;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,364 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using DTS.Common.Storage;
using DTS.Common.Utilities.Logging;
// ReSharper disable InconsistentNaming
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users
{
public class Tags
{
/// <summary>
/// represents a single tag, which is composed of an ID and a string of text
/// we don't currently let you obsolete, delete, or edit tags, just add
/// </summary>
public class Tag: ICloneable
{
public Tag(string tagText, int tagId)
{
ID = tagId;
Text = tagText;
IsObsolete = false;
}
public const int INVALID_ID = -1;
public int ID { get; set; }
public string Text { get; set; }
public bool IsObsolete { get; set; }
public Tag(Tag copy)
{
ID = copy.ID;
Text = copy.Text;
IsObsolete = copy.IsObsolete;
}
public Tag(IDataRecord reader)
{
try
{
ID = Convert.ToInt32(reader[DbOperations.Tags.TagFields.TagId.ToString()]);
IsObsolete = Convert.ToBoolean(reader[DbOperations.Tags.TagFields.Obsolete.ToString()]);
Text = Convert.ToString(reader[DbOperations.Tags.TagFields.TagText.ToString()]);
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
public Tag(DataRow dr)
{
try
{
IsObsolete = Convert.ToBoolean(dr[DbOperations.Tags.TagFields.Obsolete.ToString()]);
ID = Convert.ToInt32(dr[DbOperations.Tags.TagFields.TagId.ToString()]);
Text = Convert.ToString(dr[DbOperations.Tags.TagFields.TagText.ToString()]);
}
catch (Exception ex) { APILogger.Log(ex); }
}
public object Clone()
{
return new Tag(this);
}
}
private static Tags _tagsInstance;
public static Tags TagsInstance
{
get
{
if (null == _tagsInstance) { _tagsInstance = new Tags(); }
return _tagsInstance;
}
}
private static readonly object LOCK_OBJECT = new object();
public Tags()
{
_tagsLookup = new Dictionary<string, Tag>();
UpdateList();
}
/// <summary>
/// holds a cached collection of tags. This collection however is currently only populated on startup
/// and not updated except explicitly when a user adds a tag
/// </summary>
// ReSharper disable once RedundantDefaultMemberInitializer
private readonly Dictionary<string, Tag> _tagsLookup = null;
/// <summary>
/// Adds a tag if not present in memory cache to db
/// </summary>
/// <param name="tagText"></param>
/// <returns></returns>
public static bool AddTag(string tagText)
{
if (string.IsNullOrEmpty(tagText)) { return false; }
// is it already in the dictionary?
if (TagsInstance.ContainsTag(tagText)) return false;
TagsInstance.Commit(new Tag(tagText, Tag.INVALID_ID));
return true;
}
/// <summary>
/// Changes the ID of a tag during database migration
/// </summary>
/// <param name="tagText"></param>
/// <returns></returns>
public static bool MigrateTag(string tagText)
{
if (string.IsNullOrEmpty(tagText)) { return false; }
TagsInstance.Commit(new Tag(tagText, Tag.INVALID_ID));
return true;
}
/// <summary>
/// commits a tag to db if doesn't already exist in db
/// </summary>
/// <param name="tag"></param>
private void Commit(Tag tag)
{
try
{
if (-1 == GetIDFromTagText(tag.Text))
{
Insert(tag);
}
else { UpdateAll(tag); }
lock (LOCK_OBJECT)
{
_tagsLookup[tag.Text] = tag;
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
private void UpdateAll(Tag tag)
{
//nothing to do currently? (we don't let you rename or edit, or obsolete, or delete ...)
tag.ID = GetTagIdFromText(tag.Text);
}
/// <summary>
/// inserts a tag into the db
/// </summary>
/// <param name="tag"></param>
private void Insert(Tag tag)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_TagsInsert.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@TagText", SqlDbType.NVarChar, 255) {Value = tag.Text});
cmd.Parameters.Add(new SqlParameter("@Obsolete", SqlDbType.Bit) {Value = tag.IsObsolete});
var newIdParam = new SqlParameter("@new_id", SqlDbType.Int) {Direction = ParameterDirection.Output};
cmd.Parameters.Add(newIdParam);
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) {Direction = ParameterDirection.Output};
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
tag.ID = int.Parse(newIdParam.Value.ToString());
}
finally
{
cmd.Connection.Dispose();
}
}
}
/// <summary>
/// retrieves a string text associated with an ID FROM CACHED copies
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
private string GetTagTextFromId(int id)
{
lock (LOCK_OBJECT)
{
if (_tagsLookup == null) return null;
var e = _tagsLookup.GetEnumerator();
while (e.MoveNext())
{
if (e.Current.Value.ID != id) continue;
var returnText = e.Current.Value.Text;
e.Dispose();
return returnText;
}
}
return null;
}
/// <summary>
/// Gets an ID for a given tag text FROM DB
/// returns InvalidID if not found
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
private int GetTagIdFromText(string text)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_TagsGetId.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@TagText", SqlDbType.NVarChar, 255) {Value = text});
var tagIdParam = new SqlParameter("@TagId", SqlDbType.Int) {Direction = ParameterDirection.Output};
cmd.Parameters.Add(tagIdParam);
#endregion params
cmd.ExecuteNonQuery();
if (DBNull.Value.Equals(tagIdParam.Value))
{
return Tag.INVALID_ID;
}
var tagIdtemp = int.Parse(tagIdParam.Value.ToString());
return tagIdtemp == 0 ? Tag.INVALID_ID : tagIdtemp;
}
finally
{
cmd.Connection.Dispose();
}
}
}
/// <summary>
/// returns true if a given tag text is contained in cached in memory tags
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public bool ContainsTag(string text)
{
lock (LOCK_OBJECT)
{
return _tagsLookup.ContainsKey(text);
}
}
/// <summary>
/// adds multiple tags at once
/// note that tags will have their start trimmed before commiting
/// </summary>
/// <param name="tagText"></param>
/// <returns></returns>
public static bool[] AddRange(string[] tagText)
{
List<bool> rv = new List<bool>();
if (null == tagText || 0 == tagText.Length) { return null; }
foreach (string s in tagText)
{
var tag = s.TrimStart();
rv.Add(AddTag(tag));
}
return rv.ToArray();
}
/// <summary>
/// gets an ID for a given tag text FROM DB
/// </summary>
/// <param name="tagText"></param>
/// <returns></returns>
public static int GetIDFromTagText(string tagText)
{
return TagsInstance.GetTagIdFromText(tagText);
}
/// <summary>
/// gets an array of ids given an array of tag texts
/// </summary>
/// <param name="tagText"></param>
/// <returns></returns>
public static int[] GetIDsFromTagText(string[] tagText)
{
if (null == tagText || 0 == tagText.Length) { return null; }
return tagText.Select(s => s.TrimStart()).Select(text => GetIDFromTagText(text)).Where(id => id != Tag.INVALID_ID).ToArray();
}
/// <summary>
/// returns a string for a given id from memory cache
/// returns null if it doesn't exist or is an invalid id
/// </summary>
/// <param name="tagID"></param>
/// <returns></returns>
public static string GetTagTextFromID(int tagID)
{
if (0 > tagID || tagID == Tag.INVALID_ID)
{
// Not a valid ID
return null;
}
return TagsInstance.GetTagTextFromId(tagID);
}
/// <summary>
/// returns an array of tag text given an array of tag ids.
/// skips invalid tags or tag text
/// </summary>
/// <param name="tagId"></param>
/// <returns></returns>
public static string[] GetTagTextFromIDs(int[] tagId)
{
if (null == tagId || 0 == tagId.Length) { return new string [0]; }
return tagId.Where(i => i != Tag.INVALID_ID).Select(i => GetTagTextFromID(i)).Where(tag => !string.IsNullOrWhiteSpace(tag)).ToArray();
}
/// <summary>
/// retrieves all tags and updates the cached dictionary of tags
/// </summary>
public void UpdateList()
{
lock (LOCK_OBJECT)
{
_tagsLookup.Clear();
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_TagsGet.ToString();
cmd.Parameters.Add(new SqlParameter("@TagId", SqlDbType.Int) {Value = null});
var reader = cmd.ExecuteReader();
while (reader.Read())
{
var t = new Tag(reader);
if (t.ID == 0) continue;
_tagsLookup[t.Text] = t;
}
reader.Close();
}
finally
{
cmd.Connection.Dispose();
}
}
}
}
}
}

View File

@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Class Name="DTS.Slice.Users.ChallengeDialog" Collapsed="true">
<Position X="4.75" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAACAAABGAAACAAAACAAAAAAAAAAAAAAAEACI=</HashCode>
<FileName>ChallengeDialog.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.TagAwareBase" Collapsed="true">
<Position X="0.5" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAEAAAAUBAAAAAgAAIAAAAACAAAQAQAAAAgABAAAAAA=</HashCode>
<FileName>ITagAware.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.Tags" Collapsed="true">
<Position X="4.75" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAIAAEACAAAAASMBAgEAAAAAAAAAgAAFAAAAAQBEAAE=</HashCode>
<FileName>Tags.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.UIItemHelper" Collapsed="true">
<Position X="8.25" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAEAAAAAAAAAAAAAAgQgAAAAAAAAAAAAA=</HashCode>
<FileName>UIItemHelper.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.User" Collapsed="true">
<Position X="0.5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>IAQSIKSwECCAKADkEoBAABQLiAgAAwEAAYMQgqwAAYA=</HashCode>
<FileName>User.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.UserCollection" Collapsed="true" BaseTypeListCollapsed="true">
<Position X="3" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAEAAAAAAAAAAIAAAAAAogEEAAAACEAAAQEEAAAA=</HashCode>
<FileName>UserCollection.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" Collapsed="true" />
</Class>
<Class Name="DTS.Slice.Users.UserSettings.CategoryAttributeEx" Collapsed="true">
<Position X="3" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAgABAAAAAAAAAAAAAAAgAAAAAAAAAAAAAA=</HashCode>
<FileName>UserSettings\CategoryAttributeEx.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.UserSettings.DescriptionAttributeEx" Collapsed="true">
<Position X="6.5" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAA=</HashCode>
<FileName>UserSettings\DescriptionAttributeEx.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.UserSettings.DisplayAttributeEx" Collapsed="true">
<Position X="8.25" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAA=</HashCode>
<FileName>UserSettings\DisplayAttributeEx.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.UserSettings.PropertyEnums" Collapsed="true">
<Position X="3" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>UserSettings\PropertyEnums.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.UserSettings.PropertyIdAttribute" Collapsed="true">
<Position X="4.75" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAQAAgAA=</HashCode>
<FileName>UserSettings\PropertyIdAttribute.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.UserSettings.TestSetupDefaults" Collapsed="true">
<Position X="6.5" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>DCCSAgkyKgDiIqqAGgkjYiGOgSEARAAovFkgICiXAVg=</HashCode>
<FileName>UserSettings\TestSetupDefaults.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.UserSettings.SubCategory1" Collapsed="true">
<Position X="8.25" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAQAAAAA=</HashCode>
<FileName>UserSettings\TestSetupDefaults.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.UserSettings.SubCategory2" Collapsed="true">
<Position X="3" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAQAAAAA=</HashCode>
<FileName>UserSettings\TestSetupDefaults.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.UserSettings.UserHistory" Collapsed="true">
<Position X="4.75" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAIAAAEAAAAAAAAAgAAAAAAAAAAAAAAIAAAAAAA=</HashCode>
<FileName>UserSettings\UserHistory.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Users.UserSettings.StringResources" Collapsed="true">
<Position X="6.5" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>i9gDcyyAqknaWcIt528ZuBMcd7UxA2Uto2jXQsmxQ/E=</HashCode>
</TypeIdentifier>
</Class>
<Interface Name="DTS.Slice.Users.ITagAware" Collapsed="true">
<Position X="3" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAEAAAAEBAAAAAAAAIAAAAAAAAAQAAAAAAAAAAAAAAA=</HashCode>
<FileName>ITagAware.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="DTS.Slice.Users.IUIItems" Collapsed="true">
<Position X="4.75" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAIIAAAQAAIAAAAgAAAgAAAAAAAAAAAAAAAAAAABIA=</HashCode>
<FileName>IUIItems.cs</FileName>
</TypeIdentifier>
</Interface>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>

View File

@@ -0,0 +1,182 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using DTS.Common.Storage;
// ReSharper disable RedundantEmptyDefaultSwitchBranch
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users.UserSettings
{
/// <summary>
/// user specific properties, stored in db
///
/// these are all the user specific settings we are storing in the db currently as generic settings
/// we have a few user specific settings like last used hardware that are stored in other places, that maybe
/// should be stored here as well
///
/// it's possible to retrieve all the settings at once (more efficient, only one db query), or retrieve settings individually
/// one by one using the static accessors
/// each setting has a default specified both in code and in the db.
/// when retrieving a setting we fall back to the default if a user specific value is not found
/// if the default setting in the db is not found, we can further fall back to the default specified in code
///
/// in the db we have a table that lists all the settings with their fall back default value
/// we have a separate table that stores the user specific values for any of those settings, which may or may not match the fall
/// back default value
///
/// the data should always be stored in invariant form in the db
/// DisplayName, Description attributes translate so the properties can be displayed in a property grid
/// </summary>
public class UserHistory
{
#region properties
[CategoryAttributeEx(PropertyEnums.PropertyCategories.UserHistory)]
[PropertyId(PropertyEnums.PropertyIds.UsersCurrentTestSetup)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.UsersCurrentTestSetup)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.UsersCurrentTestSetup)]
[DefaultValue("")]
[ReadOnly(true)]
public string UsersCurrentTestSetup { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.UserHistory)]
[PropertyId(PropertyEnums.PropertyIds.LastRunTestSetup)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.LastRunTestSetup)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.LastRunTestSetup)]
[DefaultValue("")]
[ReadOnly(true)]
public string LastRunTestSetup { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.UserHistory)]
[PropertyId(PropertyEnums.PropertyIds.LastUsedSampleRate)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.LastUsedSampleRate)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.LastUsedSampleRate)]
[DefaultValue(20000D)]
[ReadOnly(true)]
public double LastUsedSampleRate { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.UserHistory)]
[PropertyId(PropertyEnums.PropertyIds.ApplySensorDataToBlankChannels)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.ApplySensorDataToBlankChannels)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.ApplySensorDataToBlankChannels)]
[DefaultValue(true)]
[ReadOnly(true)]
public bool ApplySensorDataToBlankChannels { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.UserHistory)]
[PropertyId(PropertyEnums.PropertyIds.ApplyHardwareAssignmentInHardwareDisco)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.ApplyHardwareAssignmentInHardwareDisco)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.ApplyHardwareAssignmentInHardwareDisco)]
[DefaultValue(true)]
[ReadOnly(true)]
[Browsable(false)]
public bool ApplyHardwareAssignmentInHardwareDisco { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.UserHistory)]
[PropertyId(PropertyEnums.PropertyIds.ShowOptionsWhenApplyingSensorToBlankChannel)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.ShowOptionsWhenApplyingSensorToBlankChannel)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.ShowOptionsWhenApplyingSensorToBlankChannel)]
[DefaultValue(true)]
[ReadOnly(true)]
public bool ShowOptionsWhenApplyingSensorToBlankChannel { get; set; }
#endregion properties
#region Static Methods
/// <summary>
/// this function is designed to create any missing property settings if needed
/// this might happen if the database table was just created for instance
/// it will create defaults for all the settings in the db, and also settings for all users
/// currently it's used by DataPRO.App
/// </summary>
public static void CreateAnyMissingUserHistory()
{
//get a list of all known properties
var userHistory = new UserHistory();
var properties = userHistory.GetType().GetProperties();
var needToBeAdded = new Dictionary<int, PropertyInfo>();
foreach (var property in properties)
{
var id = PropertyIdAttribute.GetPropertyId(property);
needToBeAdded[id] = property;
}
//find if the property already exists in the db, if so, no need to add...
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
sql.CommandText = "SELECT [PropertyId] from [DefaultProperties]";
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
var id = Convert.ToInt32(row["PropertyId"]);
if (needToBeAdded.ContainsKey(id))
{
needToBeAdded.Remove(id);
}
}
}
}
finally
{
sql.Connection.Dispose();
}
}
//if we have nothing to add, we are all done
if (needToBeAdded.Values.Count <= 0) return;
//otherwise add the defaults
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
var sb = new StringBuilder();
sb.Append(DbOperations.BEGIN_STATEMENT);
using (var needToBeAddedEnumerator = needToBeAdded.GetEnumerator())
{
var iIndex = 0;
while (needToBeAddedEnumerator.MoveNext())
{
var currentProperty = needToBeAddedEnumerator.Current.Value;
sb.AppendFormat(
"INSERT INTO [DefaultProperties] ([PropertyId],[PropertyName],[DefaultValue]) VALUES (@1_{0}, @2_{0}, @3_{0});",
iIndex);
DbOperations.CreateParam(sql, string.Format("@1_{0}", iIndex), SqlDbType.Int,
PropertyIdAttribute.GetPropertyId(currentProperty));
DbOperations.CreateParam(sql, string.Format("@2_{0}", iIndex), SqlDbType.NVarChar,
PropertyIdAttribute.GetPropertyIdEnum(currentProperty).ToString());
DbOperations.CreateParam(sql, string.Format("@3_{0}", iIndex), SqlDbType.NVarChar,
TestSetupDefaults.GetDefaultValueAsString(currentProperty));
iIndex++;
}
}
sb.Append(DbOperations.COMMIT_STATEMENT);
sql.CommandText = sb.ToString();
DbOperations.Connection.ExecuteCommand(sql);
}
finally
{
sql.Connection.Dispose();
}
}
//finally add settings for any users we have currently
TestSetupDefaults.CreateMissingUserSettingProperties(needToBeAdded.Values.ToArray());
}
#endregion
#region methods
#endregion
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,803 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Globalization;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using DTS.Common.Classes;
using DTS.Common.Interface.Tags;
using DTS.Common.Storage;
// ReSharper disable GenericEnumeratorNotDisposed
// ReSharper disable InconsistentNaming
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users
{
/// <summary>
/// this class encapsulates a single user
/// </summary>
public class User : TagAwareBase
{
public override TagTypes TagType => TagTypes.User;
#region constants and enums
public enum DefaultRoles
{
Administrator = 0,
PowerUser = 1,
User = 2,
Guest = 3
}
public enum UserPermissionLevels
{
Deny = 0,
Read = 1,
ReadAndExecute = 2,
Edit = 3,
Admin = 4
}
public enum Tags
{
User,
Role,
Version,
LastModified,
LastModifiedBy,
Name,
UserName,
Password,
LocalOnly,
Permissions,
Visibility,
Id
}
public enum XmlFields
{
UserName,
DisplayName,
Password,
// ReSharper disable once InconsistentNaming
IUIItemPermissions,
// ReSharper disable once InconsistentNaming
IUIItemVisibility,
Role,
LastModified,
LastModifiedBy,
Version,
LocalOnly,
UserTags
}
private const string DefaultLastModifiedBy = "---";
private const string DefaultAdminPwd = "DTSAdmin";
public const string DefaultPoweruserPwd = "PowerUser123";
private const string DefaultUserPwd = "UserNormal";
private const string DefaultAdminUsername = "Admin";
private const string DefaultGuestUsername = "Guest";
private const string DefaultPoweruserUsername = "PowerUser";
private const string DefaultUserUsername = "User";
private const int InvalidId = -1;
public const string DefaultAerouserPwd = "AeroUser123";
public const string DefaultCrashuserPwd = "CrashUser123";
public const string DefaultTSRAIRuserPwd = "TSRAIRUser123";
public const string DefaultAeroUsername = "AeroUser";
public const string DefaultCrashUsername = "CrashUser";
public const string DefaultTSRAIRUsername = "TSRAIRUser";
#endregion
#region properties
/// <summary>
/// a default user is a user with one of the default roles and names, like Admin or Guest
/// return true if is a default user
/// </summary>
public bool IsADefaultUser => UserName == GetDefaultUserName(Role);
/// <summary>
/// a default user id is 1, 2, 3, or 4 based on the default name
/// </summary>
public bool IsADefaultID => Id == GetDefaultUserId(Role);
/// <summary>
/// considered a duplicate if the same default name exists in the db
/// </summary>
public bool IsADuplicate => DuplicateFound(Role);
/// <summary>
/// hash of password is seeded and stored in xml
/// hash is seeded with computable information known about the user
/// hash is base64encoding for xml niceness
/// xml is encrypted prior to writing to file
/// </summary>
private string _password = "";
public void SetPassword(string s)
{
var b = Encoding.UTF8.GetBytes($"{s}_{UserName}");
var sha2 = SHA256.Create();
var hashed = sha2.ComputeHash(b);
s = Convert.ToBase64String(hashed);
_password = s;
OnPropertyChanged(Tags.Password.ToString());
}
/// <summary>
/// the user friendly name for a user, a display name
/// </summary>
private string _name;
public string Name
{
get => _name;
set => SetProperty(ref _name, value, Tags.Name.ToString());
}
/// <summary>
/// the user name for the user, a short unique name for the user
/// </summary>
private string _userName = string.Empty;
public string UserName
{
get => _userName;
set => SetProperty(ref _userName, value, Tags.UserName.ToString());
}
private int _id = InvalidId;
public int Id
{
get => _id;
set => SetProperty(ref _id, value, Tags.Id.ToString());
}
/// <summary>
/// the default role for the user, if a permission is not explicitly set for the user
/// it will use this default role to determine the effect permission
/// </summary>
private DefaultRoles _myRole = DefaultRoles.Guest;
public DefaultRoles Role
{
get => _myRole;
set
{
if (IsADefaultUser && _myRole != value) { throw new NotSupportedException(); }
SetProperty(ref _myRole, value, Tags.Role.ToString());
}
}
/// <summary>
/// right now the version field is updated whenever the user is updated, so it keeps
/// track of how many times it has been modified
/// </summary>
private int _version;
public int Version
{
get => _version;
set => SetProperty(ref _version, value, Tags.Version.ToString());
}
/// <summary>
/// the time the user was last modified or commited to the db
/// </summary>
private DateTime _lastModified = DateTime.MinValue;
public DateTime LastModified
{
get => _lastModified;
set => SetProperty(ref _lastModified, value, Tags.LastModified.ToString());
}
/// <summary>
/// the user that last modified the user
/// </summary>
private string _lastModifiedBy = DefaultLastModifiedBy;
public string LastModifiedBy
{
get => _lastModifiedBy;
set => SetProperty(ref _lastModifiedBy, value, Tags.LastModifiedBy.ToString());
}
/// <summary>
/// a remnant of the multiple database era, this was to mark a user as being local to this db and should never
/// be pushed to the central db
/// </summary>
private bool _bLocalOnly;
public bool LocalOnly
{
get => _bLocalOnly;
set => SetProperty(ref _bLocalOnly, value, Tags.LocalOnly.ToString());
}
/// <summary>
/// returns true if the user's role is Administrator
/// </summary>
public bool IsAdmin => Role == DefaultRoles.Administrator;
/// <summary>
/// returns true if the user's role is guest
/// </summary>
public bool IsGuest => Role == DefaultRoles.Guest;
/// <summary>
/// lookup of permissions by UI item
/// </summary>
private readonly Dictionary<IUIItems, UserPermissionLevels> _tabPermissions = new Dictionary<IUIItems, UserPermissionLevels>();
/// <summary>
/// lookup of visibility by UI item
/// </summary>
private readonly Dictionary<IUIItems, bool> _showTabs = new Dictionary<IUIItems, bool>();
/// <summary>
/// lock for accessing tab permissions or visibility
/// </summary>
private static readonly object TAB_PERMISSIONS_LOCK = new object();
#endregion properties
#region Constructors and Initializers
/// <summary>
/// used by Add user page to create a new user
/// </summary>
/// <param name="items"></param>
public User(IEnumerable<IUIItems> items)
{
Role = DefaultRoles.Guest;
foreach (var item in items)
{
SetPermission(item, item.GetDefaultRolePermission(Role));
SetShowTabFlag(item, item.GetDefaultRoleVisibility(Role));
}
}
/// <summary>
/// deep copy constructor
/// </summary>
/// <param name="user"></param>
public User(User user)
{
Name = user.Name;
UserName = user.UserName;
Version = user.Version;
_password = user._password;
Role = user.Role;
LastModified = user.LastModified;
LastModifiedBy = user.LastModifiedBy;
LocalOnly = user.LocalOnly;
var e = user._tabPermissions.GetEnumerator();
while (e.MoveNext()) { SetPermission(e.Current.Key, e.Current.Value); }
var e2 = user._showTabs.GetEnumerator();
while (e2.MoveNext()) { SetShowTabFlag(e2.Current.Key, e2.Current.Value); }
TagIDs = user.TagIDs;
}
/// <summary>
/// reserved for when creating a default user
/// </summary>
/// <param name="username"></param>
public User(string username)
{
_userName = username;
_name = username;
}
/// <summary>
/// creates a user given a role and a list of UI items
/// </summary>
/// <param name="role"></param>
/// <param name="uiItems"></param>
/// <returns></returns>
public static User CreateDefault(DefaultRoles role, IUIItems[] uiItems)
{
var uName = GetDefaultUserName(role);
var user = new User(uName)
{
_version = 1,
_myRole = role
};
switch (role)
{
case DefaultRoles.Administrator:
user.SetPassword(DefaultAdminPwd);
break;
case DefaultRoles.Guest:
user.SetPassword("");
break;
case DefaultRoles.PowerUser:
user.SetPassword(DefaultPoweruserPwd);
break;
case DefaultRoles.User:
user.SetPassword(DefaultUserPwd);
break;
default:
throw new NotSupportedException("Unknown role " + role);// TODO: handle exception properly
}
user._lastModified = DateTime.Now;
bool bShow;
UserPermissionLevels permission;
Parallel.ForEach(uiItems, uiItem =>
{
permission = uiItem.GetDefaultRolePermission(role);
bShow = uiItem.GetDefaultRoleVisibility(role);
lock (user)
{
user.SetShowTabFlag(uiItem, bShow);
user.SetPermission(uiItem, permission);
}
});
return user;
}
public static User CreateNonDefaultPowerUser(string username, IUIItems[] uiItems)
{
var user = new User(username)
{
_version = 1,
_myRole = DefaultRoles.PowerUser
};
switch (username)
{
case DefaultAeroUsername:
user.SetPassword(DefaultAerouserPwd);
break;
case DefaultCrashUsername:
user.SetPassword(DefaultCrashuserPwd);
break;
case DefaultTSRAIRUsername:
user.SetPassword(DefaultTSRAIRuserPwd);
break;
}
user._lastModified = DateTime.Now;
bool bShow;
UserPermissionLevels permission;
Parallel.ForEach(uiItems, uiItem =>
{
permission = uiItem.GetDefaultRolePermission(user.Role);
bShow = uiItem.GetDefaultRoleVisibility(user.Role);
lock (user)
{
user.SetShowTabFlag(uiItem, bShow);
user.SetPermission(uiItem, permission);
}
});
return user;
}
/// <summary>
/// constructor using db row
/// </summary>
/// <param name="row"></param>
/// <param name="items"></param>
/// <param name="permissionLookup"></param>
/// <param name="tagLookup"></param>
public User(DataRow row, IEnumerable<IUIItems> items, IReadOnlyDictionary<int, Dictionary<long, UIItemHelper>> permissionLookup, IReadOnlyDictionary<int, List<int>> tagLookup)
{
var nameToUiItem = new Dictionary<string, IUIItems>();
foreach (var item in items)
{
nameToUiItem[item.GetName()] = item;
}
var fields = Enum.GetValues(typeof(DbOperations.Users.UserFields)).Cast<DbOperations.Users.UserFields>().ToArray();
foreach (var field in fields)
{
if (DBNull.Value.Equals(row[field.ToString()])) { continue; }
switch (field)
{
case DbOperations.Users.UserFields.ID: Id = Convert.ToInt32(row[field.ToString()]); break;
case DbOperations.Users.UserFields.UserName: UserName = (string)row[field.ToString()]; break;
case DbOperations.Users.UserFields.Role: _myRole = (DefaultRoles)Convert.ToInt32(row[field.ToString()]); break;
case DbOperations.Users.UserFields.Password: _password = (string)row[field.ToString()]; break;
case DbOperations.Users.UserFields.LocalOnly: LocalOnly = Convert.ToBoolean(row[field.ToString()]); break;
case DbOperations.Users.UserFields.LastModifiedBy: LastModifiedBy = (string)row[field.ToString()]; break;
case DbOperations.Users.UserFields.LastModified: LastModified = (DateTime)row[field.ToString()]; break;
case DbOperations.Users.UserFields.DisplayName: Name = (string)row[field.ToString()]; break;
default: throw new NotSupportedException("unknown field: " + field);// TODO: handle exception properly
}
}
if (permissionLookup.ContainsKey(Id))
{
var e = permissionLookup[Id].GetEnumerator();
while (e.MoveNext())
{
if (!nameToUiItem.ContainsKey(e.Current.Value.UIItemName)) continue;
SetPermission(nameToUiItem[e.Current.Value.UIItemName], (UserPermissionLevels)e.Current.Value.Permission);
SetShowTabFlag(nameToUiItem[e.Current.Value.UIItemName], e.Current.Value.IsVisible);
}
}
if (tagLookup.ContainsKey(Id))
{
TagIDs = tagLookup[Id].ToArray();
}
}
private User() { }
#endregion
#region Methods
public void MarkChanged()
{
OnPropertyChanged(Tags.User.ToString());
}
public string GetPasswordHash() { return _password; }
public void SetPasswordHash(string value)
{
_password = value;
OnPropertyChanged(Tags.Password.ToString());
}
public bool CheckPasswordHash(string hash)
{
if (null == _password && string.IsNullOrEmpty(hash)) { return true; }
if (null == _password) { return false; }
return _password == hash;
}
public bool CheckPassword(string password)
{
try
{
if (null == _password && string.IsNullOrEmpty(password)) { return true; }
if (null == _password) { return false; }
var b = Encoding.UTF8.GetBytes(string.Format("{0}_{1}", password, UserName));
var sha2 = SHA256.Create();
var hashed = sha2.ComputeHash(b);
password = Convert.ToBase64String(hashed);
return _password == password;
}
catch (Exception) { return false; }// TODO: handle exception properly
}
public UserPermissionLevels GetPermission(IUIItems tab, IUIItems parent = null)
{
if (IsAdmin) { return UserPermissionLevels.Admin; }
lock (TAB_PERMISSIONS_LOCK)
{
if (!_tabPermissions.ContainsKey(tab))
{
return null != parent ? GetPermission(parent) : tab.GetDefaultRolePermission(Role);
}
return _tabPermissions[tab];
}
}
public string GetPermissionSerialized()
{
var sb = new StringBuilder();
lock (TAB_PERMISSIONS_LOCK)
{
var i = _tabPermissions.GetEnumerator();
while (i.MoveNext())
{
if (sb.Length > 0) { sb.Append(","); }
sb.Append(i.Current.Key.GetName());
sb.Append("=");
sb.Append(((int)i.Current.Value).ToString());
}
}
return sb.ToString();
}
public void SetPermission(IUIItems tab, UserPermissionLevels permission)
{
lock (TAB_PERMISSIONS_LOCK)
{
if (!_tabPermissions.ContainsKey(tab)) { _tabPermissions.Add(tab, permission); }
else { _tabPermissions[tab] = permission; }
OnPropertyChanged(Tags.Permissions.ToString());
}
}
public bool IsShowTabFlagSet(IUIItems tab, IUIItems parent = null)
{
//15985 I do not see a way to allow the User account to have visibility of system settings tile but not manage users
//if current view is named admin, he has visibility
//otherwise, if he has admin privileges, he has visibility
if (IsAdmin && IsADefaultUser) { return true; }
if (GetPermission(tab, parent) == UserPermissionLevels.Admin) { return true; }
if (_showTabs.ContainsKey(tab))
{
return _showTabs[tab];
}
var name = tab.GetName();
if (name.EndsWith("_Page"))
{
name = name.Substring(0, name.Length - 5);
}
var matches = from key in _showTabs.Keys where key.GetName() == name select key;
if (matches.Any())
{
return _showTabs[matches.First()];
}
if (null != parent)
{
return IsShowTabFlagSet(parent);
}
return tab.GetDefaultRoleVisibility(Role);
}
public void SetShowTabFlag(IUIItems tab, bool bFlag)
{
if (_showTabs.ContainsKey(tab)) { _showTabs[tab] = bFlag; }
else
{
_showTabs.Add(tab, bFlag);
OnPropertyChanged(Tags.Visibility.ToString());
}
}
public static string GetDefaultUserName(DefaultRoles role)
{
switch (role)
{
case DefaultRoles.Administrator: return DefaultAdminUsername;
case DefaultRoles.Guest: return DefaultGuestUsername;
case DefaultRoles.PowerUser: return DefaultPoweruserUsername;
case DefaultRoles.User: return DefaultUserUsername;
default: throw new NotSupportedException("Unknown role " + role); // TODO: handle exception properly
}
}
private static int GetDefaultUserId(DefaultRoles role)
{
return (int)role + 1;
}
public string GetVisibilitySerialized()
{
var sb = new StringBuilder();
var i2 = _showTabs.GetEnumerator();
while (i2.MoveNext())
{
if (sb.Length > 0) { sb.Append(","); }
sb.Append(i2.Current.Key.GetName());
sb.Append("=");
sb.Append(i2.Current.Value ? "1" : "0");
}
return sb.ToString();
}
protected void SetVisibilitiesFromCSV(string sVisibiles, Dictionary<string, List<IUIItems>> lookup)
{
var tokens = sVisibiles.Split(',');
foreach (var token in tokens)
{
var subtokens = token.Split('=');
if (2 != subtokens.Length) { continue; }
if (!lookup.ContainsKey(subtokens[0])) { continue; }
foreach (var item in lookup[subtokens[0]]) { _showTabs[item] = Convert.ToBoolean(Convert.ToInt32(subtokens[1])); }
}
}
protected void SetPermissionsFromCSV(string sPermissions, Dictionary<string, List<IUIItems>> lookup)
{
var tokens = sPermissions.Split(',');
foreach (var token in tokens)
{
var subtokens = token.Split('=');
if (2 != subtokens.Length) { continue; }
if (!lookup.ContainsKey(subtokens[0])) { continue; }
foreach (var item in lookup[subtokens[0]])
{
if (_tabPermissions != null)
{
lock (TAB_PERMISSIONS_LOCK)
{
_tabPermissions[item] = (UserPermissionLevels)Convert.ToInt32(subtokens[1]);
}
}
}
}
}
/// <summary>
/// True if more than one user with this name exists in the Users table
/// </summary>
/// <param name="role"></param>
/// <returns></returns>
public static bool DuplicateFound(DefaultRoles role)
{
var userName = role.ToString();
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = $"SELECT ID FROM [dbo].[Users] WHERE UserName = '{userName}'";
using (var ds = DbOperations.Connection.QueryDataSet(cmd))
{
if (ds.Tables.Count > 0)
{
return ds.Tables[0].Rows.Count > 1;
}
}
}
finally
{
cmd.Connection.Dispose();
}
}
return false;
}
public string[] GetLastUsedHardware()
{
var results = new List<string>();
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_LastUsedHardwareGet.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = Id });
#endregion
//cmd.ExecuteNonQuery();
using (var ds = DbOperations.Connection.QueryDataSet(cmd))
{
foreach (DataRow dr in ds.Tables[0].Rows)
{
var hardwareId = Convert.ToString(dr["HardwareID"]);
if (!results.Contains(hardwareId))
{
results.Add(hardwareId);
}
}
}
}
finally
{
cmd.Connection.Dispose();
}
}
return results.ToArray();
}
public void SetLastUsedHardware(List<string> hardware)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_LastUsedHardwareDelete.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = Id });
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
if (!hardware.Any()) return;
foreach (var h in hardware)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_LastUsedHardwareInsert.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = Id });
cmd.Parameters.Add(new SqlParameter("@HardwareID", SqlDbType.NVarChar, 50) { Value = h });
cmd.Parameters.Add(new SqlParameter("@SerialNumber", SqlDbType.NVarChar, 50) { Value = h }); //Not sure why this field is needed, but it was added by Alex
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
}
}
#endregion
#region XML serialization
public void WriteXML(ref XmlWriter writer)
{
writer.WriteStartElement("User");
var fields = Enum.GetValues(typeof(XmlFields)).Cast<XmlFields>().ToArray();
foreach (var field in fields)
{
writer.WriteStartElement(field.ToString());
switch (field)
{
case XmlFields.DisplayName: writer.WriteString(Name); break;
case XmlFields.IUIItemPermissions: writer.WriteString(GetPermissionSerialized()); break;
case XmlFields.IUIItemVisibility: writer.WriteString(GetVisibilitySerialized()); break;
case XmlFields.LastModified: writer.WriteString(LastModified.ToString(CultureInfo.InvariantCulture)); break;
case XmlFields.LastModifiedBy: writer.WriteString(LastModifiedBy); break;
case XmlFields.LocalOnly: writer.WriteString(LocalOnly.ToString(CultureInfo.InvariantCulture)); break;
case XmlFields.Password: writer.WriteString(_password); break;
case XmlFields.Role: writer.WriteString(Role.ToString()); break;
case XmlFields.UserName: writer.WriteString(UserName); break;
case XmlFields.UserTags: writer.WriteString(GetTagsAsCommaSeparatedString(DbOperations.TagsGet)); break;
case XmlFields.Version: writer.WriteString(Version.ToString(CultureInfo.InvariantCulture)); break;
default: throw new NotSupportedException(field.ToString()); // TODO: handle exception properly
}
writer.WriteEndElement();
}
writer.WriteEndElement();
}
public static User ReadXML(XmlElement root, IUIItems[] items)
{
var lookup = new Dictionary<string, List<IUIItems>>();
Parallel.ForEach(items, item =>
{
lock (lookup)
{
if (!lookup.ContainsKey(item.GetName())) { lookup.Add(item.GetName(), new List<IUIItems>()); }
if (!lookup[item.GetName()].Contains(item)) { lookup[item.GetName()].Add(item); }
}
});
var user = new User();
foreach (var node in root.ChildNodes)
{
if (node is XmlElement element)
{
ProcessXMLElement(element, ref user, lookup);
}
}
return user;
}
private static void ProcessXMLElement(XmlElement node, ref User user, Dictionary<string, List<IUIItems>> lookup)
{
XmlFields field;
if (Enum.TryParse(node.Name, out field))
{
switch (field)
{
case XmlFields.DisplayName: user.Name = node.InnerText; break;
case XmlFields.LastModified: user.LastModified = DateTime.Parse(node.InnerText, CultureInfo.InvariantCulture); break;
case XmlFields.LastModifiedBy: user.LastModifiedBy = node.InnerText; break;
case XmlFields.LocalOnly: user.LocalOnly = Boolean.Parse(node.InnerText); break;
case XmlFields.Password: user.SetPasswordHash(node.InnerText); break;
case XmlFields.Role: DefaultRoles role; if (Enum.TryParse(node.InnerText, out role)) { user.Role = role; } break;
case XmlFields.UserName: user.UserName = node.InnerText; break;
case XmlFields.UserTags:
user.SetTagsFromCommaSeparatedString(node.InnerText,
DbOperations.GetSQLCommand, DbOperations.TagsGet,
DbOperations.TagsGetId, DbOperations.TagsInsert); break;
case XmlFields.Version: int iTemp; if (int.TryParse(node.InnerText, NumberStyles.Any, CultureInfo.InvariantCulture, out iTemp)) { user.Version = iTemp; } break;
case XmlFields.IUIItemPermissions: user.SetPermissionsFromCSV(node.InnerText, lookup); break;
case XmlFields.IUIItemVisibility: user.SetVisibilitiesFromCSV(node.InnerText, lookup); break;
}
}
}
#endregion XML Serialization
}
}

View File

@@ -0,0 +1,28 @@
using System.ComponentModel;
using Users.UserSettings;
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users.UserSettings
{
/// <summary>
/// this class overloads the categoryattribute to provide a localized string using our string resources
/// we also overload it so that we can use an enum to set the attribute
/// to be translated the category should exist in the string resources, otherwise you'll get
/// ##ResourceNotFound## as your translated string
/// </summary>
public class CategoryAttributeEx : CategoryAttribute
{
private readonly PropertyEnums.PropertyCategories _category;
public PropertyEnums.PropertyCategories GetCategory() { return _category; }
protected override string GetLocalizedString(string value)
{
return StringResources.ResourceManager.GetString(value) ?? "##ResourceNotFound##" + value;
}
public CategoryAttributeEx(PropertyEnums.PropertyCategories category) : base(category.ToString())
{
_category = category;
}
}
}

BIN
DataPRO/Users/.svn/wc.db Normal file

Binary file not shown.

View File

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace DTS.Slice.Users
{
public partial class ChallengeDialog : Form
{
public ChallengeDialog()
{
InitializeComponent();
}
}
}

143
DataPRO/Users/ChallengeDialog.designer.cs generated Normal file
View File

@@ -0,0 +1,143 @@
namespace DTS.Slice.Users
{
partial class ChallengeDialog
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.tbPassword = new System.Windows.Forms.TextBox();
this.lblLoginFailedMessage = new System.Windows.Forms.Label();
this.btnCancel = new System.Windows.Forms.Button();
this.btnContinue = new System.Windows.Forms.Button();
this.label2 = new System.Windows.Forms.Label();
this.tableLayoutPanel1.SuspendLayout();
this.SuspendLayout();
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.ColumnCount = 2;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel1.Controls.Add(this.tbPassword, 0, 2);
this.tableLayoutPanel1.Controls.Add(this.lblLoginFailedMessage, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.btnCancel, 1, 3);
this.tableLayoutPanel1.Controls.Add(this.btnContinue, 0, 3);
this.tableLayoutPanel1.Controls.Add(this.label2, 0, 0);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(10);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 4;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.64378F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.Size = new System.Drawing.Size(632, 120);
this.tableLayoutPanel1.TabIndex = 0;
//
// tbPassword
//
this.tbPassword.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.tableLayoutPanel1.SetColumnSpan(this.tbPassword, 2);
this.tbPassword.Location = new System.Drawing.Point(3, 66);
this.tbPassword.Name = "tbPassword";
this.tbPassword.PasswordChar = '*';
this.tbPassword.Size = new System.Drawing.Size(626, 22);
this.tbPassword.TabIndex = 1;
this.tbPassword.UseSystemPasswordChar = true;
//
// lblLoginFailedMessage
//
this.lblLoginFailedMessage.AutoSize = true;
this.tableLayoutPanel1.SetColumnSpan(this.lblLoginFailedMessage, 2);
this.lblLoginFailedMessage.Dock = System.Windows.Forms.DockStyle.Fill;
this.lblLoginFailedMessage.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.lblLoginFailedMessage.ForeColor = System.Drawing.Color.DarkRed;
this.lblLoginFailedMessage.Location = new System.Drawing.Point(3, 45);
this.lblLoginFailedMessage.Name = "lblLoginFailedMessage";
this.lblLoginFailedMessage.Size = new System.Drawing.Size(626, 18);
this.lblLoginFailedMessage.TabIndex = 2;
this.lblLoginFailedMessage.Text = "Login failed";
this.lblLoginFailedMessage.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// btnCancel
//
this.btnCancel.Location = new System.Drawing.Point(319, 94);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 4;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
//
// btnContinue
//
this.btnContinue.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.btnContinue.Location = new System.Drawing.Point(238, 94);
this.btnContinue.Name = "btnContinue";
this.btnContinue.Size = new System.Drawing.Size(75, 23);
this.btnContinue.TabIndex = 5;
this.btnContinue.Text = "Continue";
this.btnContinue.UseVisualStyleBackColor = true;
//
// label2
//
this.label2.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.label2.AutoSize = true;
this.tableLayoutPanel1.SetColumnSpan(this.label2, 2);
this.label2.Location = new System.Drawing.Point(18, 0);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(595, 34);
this.label2.TabIndex = 6;
this.label2.Text = "Admin access needed to update Master User db. Please enter the Adminsitrator pas" +
"sword to continue or press cancel to skip updating the master.";
this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// ChallengeDialog
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(632, 120);
this.Controls.Add(this.tableLayoutPanel1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
this.Name = "ChallengeDialog";
this.Text = "Admin Access Needed";
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.TextBox tbPassword;
private System.Windows.Forms.Label lblLoginFailedMessage;
private System.Windows.Forms.Button btnCancel;
private System.Windows.Forms.Button btnContinue;
private System.Windows.Forms.Label label2;
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Class Name="DTS.Slice.Users.ChallengeDialog" Collapsed="true">
<Position X="4.75" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAACAAABGAAACAAAACAAAAAAAAAAAAAAAEACI=</HashCode>
<FileName>ChallengeDialog.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.TagAwareBase" Collapsed="true">
<Position X="0.5" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAEAAAAUBAAAAAgAAIAAAAACAAAQAQAAAAgABAAAAAA=</HashCode>
<FileName>ITagAware.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.Tags" Collapsed="true">
<Position X="4.75" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAIAAEACAAAAASMBAgEAAAAAAAAAgAAFAAAAAQBEAAE=</HashCode>
<FileName>Tags.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.UIItemHelper" Collapsed="true">
<Position X="8.25" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAEAAAAAAAAAAAAAAgQgAAAAAAAAAAAAA=</HashCode>
<FileName>UIItemHelper.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.User" Collapsed="true">
<Position X="0.5" Y="2" Width="1.5" />
<TypeIdentifier>
<HashCode>IAQSIKSwECCAKADkEoBAABQLiAgAAwEAAYMQgqwAAYA=</HashCode>
<FileName>User.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.UserCollection" Collapsed="true" BaseTypeListCollapsed="true">
<Position X="3" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAEAAAAAAAAAAIAAAAAAogEEAAAACEAAAQEEAAAA=</HashCode>
<FileName>UserCollection.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" Collapsed="true" />
</Class>
<Class Name="DTS.Slice.Users.UserSettings.CategoryAttributeEx" Collapsed="true">
<Position X="3" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAgABAAAAAAAAAAAAAAAgAAAAAAAAAAAAAA=</HashCode>
<FileName>UserSettings\CategoryAttributeEx.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.UserSettings.DescriptionAttributeEx" Collapsed="true">
<Position X="6.5" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAA=</HashCode>
<FileName>UserSettings\DescriptionAttributeEx.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.UserSettings.DisplayAttributeEx" Collapsed="true">
<Position X="8.25" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAA=</HashCode>
<FileName>UserSettings\DisplayAttributeEx.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.UserSettings.PropertyEnums" Collapsed="true">
<Position X="3" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>UserSettings\PropertyEnums.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.UserSettings.PropertyIdAttribute" Collapsed="true">
<Position X="4.75" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAQAAgAA=</HashCode>
<FileName>UserSettings\PropertyIdAttribute.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.UserSettings.TestSetupDefaults" Collapsed="true">
<Position X="6.5" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>DCCSAgkyKgDiIqqAGgkjYiGOgSEARAAovFkgICiXAVg=</HashCode>
<FileName>UserSettings\TestSetupDefaults.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.UserSettings.SubCategory1" Collapsed="true">
<Position X="8.25" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAQAAAAA=</HashCode>
<FileName>UserSettings\TestSetupDefaults.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.UserSettings.SubCategory2" Collapsed="true">
<Position X="3" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAQAAAAA=</HashCode>
<FileName>UserSettings\TestSetupDefaults.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Slice.Users.UserSettings.UserHistory" Collapsed="true">
<Position X="4.75" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAIAAAEAAAAAAAAAgAAAAAAAAAAAAAAIAAAAAAA=</HashCode>
<FileName>UserSettings\UserHistory.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="Users.UserSettings.StringResources" Collapsed="true">
<Position X="6.5" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>i9gDcyyAqknaWcIt528ZuBMcd7UxA2Uto2jXQsmxQ/E=</HashCode>
</TypeIdentifier>
</Class>
<Interface Name="DTS.Slice.Users.ITagAware" Collapsed="true">
<Position X="3" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAEAAAAEBAAAAAAAAIAAAAAAAAAQAAAAAAAAAAAAAAA=</HashCode>
<FileName>ITagAware.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="DTS.Slice.Users.IUIItems" Collapsed="true">
<Position X="4.75" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAIIAAAQAAIAAAAgAAAgAAAAAAAAAAAAAAAAAAABIA=</HashCode>
<FileName>IUIItems.cs</FileName>
</TypeIdentifier>
</Interface>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>

253
DataPRO/Users/ITagAware.cs Normal file
View File

@@ -0,0 +1,253 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using DTS.Common.Storage;
using DTS.Common.Utilities.Logging;
namespace DTS.Slice.Users
{
public abstract class TagAwareBase : Common.Base.BasePropertyChanged
{
public enum TagTypes
{
User,
Group,
Template,
TestSetup,
Sensors,
SensorModels
}
public abstract TagTypes TagType { get; }
#region Tags
public byte[] TagsBlobBytes
{
get
{
var result = new byte[TagIDs.Length * sizeof(int)];
Buffer.BlockCopy(TagIDs, 0, result, 0, result.Length);
return result;
}
set
{
if (value.Length < sizeof(int)) return;
var tagsBlob = new int[value.Length / sizeof(int)];
try
{
Buffer.BlockCopy(value, 0, tagsBlob, 0, value.Length);
TagIDs = tagsBlob;
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
}
private int[] _tagIDs = new int[0];
public int[] TagIDs
{
get => _tagIDs;
set => _tagIDs = value ?? new int[0];
}
public void SetTagsFromCommaSeparatedString(string tagText)
{
//if (string.IsNullOrEmpty(tagText)) { return; } // http://fogbugz/fogbugz/default.asp?7176
SetTags(tagText.Split(','));
}
public virtual void SetTags(string[] tagsText)
{
Tags.AddRange(tagsText);
TagIDs = Tags.GetIDsFromTagText(tagsText);
OnPropertyChanged("TagIDs");
}
public string GetTagsAsCommaSeparatedString()
{
var sb = new StringBuilder();
foreach (var s in GetTagsArray())
{
if (sb.Length > 0) { sb.Append(","); }
sb.Append(s);
}
return sb.ToString();
}
#region ITagAware
public virtual string[] GetTagsArray()
{
return Tags.GetTagTextFromIDs(TagIDs);
}
public virtual int[] GetTagIDs() { return TagIDs; }
public virtual void RemoveTags(string[] tagsText)
{
// remove tags!!!
//-;
}
public bool TagCompatible(string tags)
{
//Make sure there are Tags to check
if (string.IsNullOrWhiteSpace(tags)) return true;
var newTagsArray = tags.Split(',');
//Make sure all Tags are not empty strings
if (newTagsArray.All(string.IsNullOrWhiteSpace)) return true;
var comparisonArray = GetTagsArray();
foreach (var tag in newTagsArray)
{
//If a Tag is an empty string, ignore it
if (string.IsNullOrWhiteSpace(tag)) continue;
if (comparisonArray.Contains(tag.Trim()))
{
return true;
}
}
return false;
}
public virtual bool TagCompatible(int[] tags)
{
return !tags.Any() || HasIntersectingTag(tags);
}
public virtual bool HasIntersectingTag(int[] tags)
{
return tags.Intersect(TagIDs).Any();
}
#endregion
#endregion
public void InsertTagsFromCommaSeparatedString(int id, TagTypes tagType, string tags)
{
SetTagsFromCommaSeparatedString(tags);
Commit(id, tagType);
}
public void Commit(int id, TagTypes tagType)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_TagAssignmentsDelete.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@ObjectID", SqlDbType.Int) { Value = id });
cmd.Parameters.Add(new SqlParameter("@ObjectType", SqlDbType.SmallInt) { Value = tagType });
var errorNumberParam = new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam = new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
if (!TagIDs.Any()) return;
foreach (var tagId in TagIDs)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_TagAssignmentsInsert.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@ObjectID", SqlDbType.Int) { Value = id });
cmd.Parameters.Add(new SqlParameter("@ObjectType", SqlDbType.SmallInt) { Value = tagType });
cmd.Parameters.Add(new SqlParameter("@TagID", SqlDbType.Int) { Value = tagId });
var errorNumberParam = new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam = new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
}
}
public List<int> GetTagIdList(int objectId, TagTypes tagType)
{
var tagIdList = new List<int>();
try
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_TagAssignmentsGet.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@ObjectType", SqlDbType.Int) { Value = tagType });
#endregion params
//cmd.ExecuteNonQuery();
using (var ds = DbOperations.Connection.QueryDataSet(cmd))
{
foreach (DataRow dr in ds.Tables[0].Rows)
{
if (Convert.ToInt32(dr[DbOperations.Tags.TagAssignmentFields.ObjectID.ToString()]) != objectId) continue;
var tagId = Convert.ToInt32(dr[DbOperations.Tags.TagAssignmentFields.TagID.ToString()]);
if (!tagIdList.Contains(tagId))
{
tagIdList.Add(tagId);
}
}
}
}
finally
{
cmd.Connection.Dispose();
}
}
}
catch (Exception ex)
{
APILogger.Log("failed to retrieve object tags", ex);
}
return tagIdList;
}
}
}

14
DataPRO/Users/IUIItems.cs Normal file
View File

@@ -0,0 +1,14 @@
namespace DTS.Slice.Users
{
public interface IUIItems
{
User.UserPermissionLevels GetDefaultRolePermission(User.DefaultRoles role);
bool GetDefaultRoleVisibility(User.DefaultRoles role);
void SetVisible(bool bShow);
void SetEnabled(bool bEnabled);
User.UserPermissionLevels GetRequiredPermission();
string GetName();
long GetID();
void SetID(long id);
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Users")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Users")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("7baff2aa-d701-4d98-b20e-872f21431990")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

364
DataPRO/Users/Tags.cs Normal file
View File

@@ -0,0 +1,364 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using DTS.Common.Storage;
using DTS.Common.Utilities.Logging;
// ReSharper disable InconsistentNaming
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users
{
public class Tags
{
/// <summary>
/// represents a single tag, which is composed of an ID and a string of text
/// we don't currently let you obsolete, delete, or edit tags, just add
/// </summary>
public class Tag: ICloneable
{
public Tag(string tagText, int tagId)
{
ID = tagId;
Text = tagText;
IsObsolete = false;
}
public const int INVALID_ID = -1;
public int ID { get; set; }
public string Text { get; set; }
public bool IsObsolete { get; set; }
public Tag(Tag copy)
{
ID = copy.ID;
Text = copy.Text;
IsObsolete = copy.IsObsolete;
}
public Tag(IDataRecord reader)
{
try
{
ID = Convert.ToInt32(reader[DbOperations.Tags.TagFields.TagId.ToString()]);
IsObsolete = Convert.ToBoolean(reader[DbOperations.Tags.TagFields.Obsolete.ToString()]);
Text = Convert.ToString(reader[DbOperations.Tags.TagFields.TagText.ToString()]);
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
public Tag(DataRow dr)
{
try
{
IsObsolete = Convert.ToBoolean(dr[DbOperations.Tags.TagFields.Obsolete.ToString()]);
ID = Convert.ToInt32(dr[DbOperations.Tags.TagFields.TagId.ToString()]);
Text = Convert.ToString(dr[DbOperations.Tags.TagFields.TagText.ToString()]);
}
catch (Exception ex) { APILogger.Log(ex); }
}
public object Clone()
{
return new Tag(this);
}
}
private static Tags _tagsInstance;
public static Tags TagsInstance
{
get
{
if (null == _tagsInstance) { _tagsInstance = new Tags(); }
return _tagsInstance;
}
}
private static readonly object LOCK_OBJECT = new object();
public Tags()
{
_tagsLookup = new Dictionary<string, Tag>();
UpdateList();
}
/// <summary>
/// holds a cached collection of tags. This collection however is currently only populated on startup
/// and not updated except explicitly when a user adds a tag
/// </summary>
// ReSharper disable once RedundantDefaultMemberInitializer
private readonly Dictionary<string, Tag> _tagsLookup = null;
/// <summary>
/// Adds a tag if not present in memory cache to db
/// </summary>
/// <param name="tagText"></param>
/// <returns></returns>
public static bool AddTag(string tagText)
{
if (string.IsNullOrEmpty(tagText)) { return false; }
// is it already in the dictionary?
if (TagsInstance.ContainsTag(tagText)) return false;
TagsInstance.Commit(new Tag(tagText, Tag.INVALID_ID));
return true;
}
/// <summary>
/// Changes the ID of a tag during database migration
/// </summary>
/// <param name="tagText"></param>
/// <returns></returns>
public static bool MigrateTag(string tagText)
{
if (string.IsNullOrEmpty(tagText)) { return false; }
TagsInstance.Commit(new Tag(tagText, Tag.INVALID_ID));
return true;
}
/// <summary>
/// commits a tag to db if doesn't already exist in db
/// </summary>
/// <param name="tag"></param>
private void Commit(Tag tag)
{
try
{
if (-1 == GetIDFromTagText(tag.Text))
{
Insert(tag);
}
else { UpdateAll(tag); }
lock (LOCK_OBJECT)
{
_tagsLookup[tag.Text] = tag;
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
private void UpdateAll(Tag tag)
{
//nothing to do currently? (we don't let you rename or edit, or obsolete, or delete ...)
tag.ID = GetTagIdFromText(tag.Text);
}
/// <summary>
/// inserts a tag into the db
/// </summary>
/// <param name="tag"></param>
private void Insert(Tag tag)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_TagsInsert.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@TagText", SqlDbType.NVarChar, 255) {Value = tag.Text});
cmd.Parameters.Add(new SqlParameter("@Obsolete", SqlDbType.Bit) {Value = tag.IsObsolete});
var newIdParam = new SqlParameter("@new_id", SqlDbType.Int) {Direction = ParameterDirection.Output};
cmd.Parameters.Add(newIdParam);
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) {Direction = ParameterDirection.Output};
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
tag.ID = int.Parse(newIdParam.Value.ToString());
}
finally
{
cmd.Connection.Dispose();
}
}
}
/// <summary>
/// retrieves a string text associated with an ID FROM CACHED copies
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
private string GetTagTextFromId(int id)
{
lock (LOCK_OBJECT)
{
if (_tagsLookup == null) return null;
var e = _tagsLookup.GetEnumerator();
while (e.MoveNext())
{
if (e.Current.Value.ID != id) continue;
var returnText = e.Current.Value.Text;
e.Dispose();
return returnText;
}
}
return null;
}
/// <summary>
/// Gets an ID for a given tag text FROM DB
/// returns InvalidID if not found
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
private int GetTagIdFromText(string text)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_TagsGetId.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@TagText", SqlDbType.NVarChar, 255) {Value = text});
var tagIdParam = new SqlParameter("@TagId", SqlDbType.Int) {Direction = ParameterDirection.Output};
cmd.Parameters.Add(tagIdParam);
#endregion params
cmd.ExecuteNonQuery();
if (DBNull.Value.Equals(tagIdParam.Value))
{
return Tag.INVALID_ID;
}
var tagIdtemp = int.Parse(tagIdParam.Value.ToString());
return tagIdtemp == 0 ? Tag.INVALID_ID : tagIdtemp;
}
finally
{
cmd.Connection.Dispose();
}
}
}
/// <summary>
/// returns true if a given tag text is contained in cached in memory tags
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public bool ContainsTag(string text)
{
lock (LOCK_OBJECT)
{
return _tagsLookup.ContainsKey(text);
}
}
/// <summary>
/// adds multiple tags at once
/// note that tags will have their start trimmed before commiting
/// </summary>
/// <param name="tagText"></param>
/// <returns></returns>
public static bool[] AddRange(string[] tagText)
{
List<bool> rv = new List<bool>();
if (null == tagText || 0 == tagText.Length) { return null; }
foreach (string s in tagText)
{
var tag = s.TrimStart();
rv.Add(AddTag(tag));
}
return rv.ToArray();
}
/// <summary>
/// gets an ID for a given tag text FROM DB
/// </summary>
/// <param name="tagText"></param>
/// <returns></returns>
public static int GetIDFromTagText(string tagText)
{
return TagsInstance.GetTagIdFromText(tagText);
}
/// <summary>
/// gets an array of ids given an array of tag texts
/// </summary>
/// <param name="tagText"></param>
/// <returns></returns>
public static int[] GetIDsFromTagText(string[] tagText)
{
if (null == tagText || 0 == tagText.Length) { return null; }
return tagText.Select(s => s.TrimStart()).Select(text => GetIDFromTagText(text)).Where(id => id != Tag.INVALID_ID).ToArray();
}
/// <summary>
/// returns a string for a given id from memory cache
/// returns null if it doesn't exist or is an invalid id
/// </summary>
/// <param name="tagID"></param>
/// <returns></returns>
public static string GetTagTextFromID(int tagID)
{
if (0 > tagID || tagID == Tag.INVALID_ID)
{
// Not a valid ID
return null;
}
return TagsInstance.GetTagTextFromId(tagID);
}
/// <summary>
/// returns an array of tag text given an array of tag ids.
/// skips invalid tags or tag text
/// </summary>
/// <param name="tagId"></param>
/// <returns></returns>
public static string[] GetTagTextFromIDs(int[] tagId)
{
if (null == tagId || 0 == tagId.Length) { return new string [0]; }
return tagId.Where(i => i != Tag.INVALID_ID).Select(i => GetTagTextFromID(i)).Where(tag => !string.IsNullOrWhiteSpace(tag)).ToArray();
}
/// <summary>
/// retrieves all tags and updates the cached dictionary of tags
/// </summary>
public void UpdateList()
{
lock (LOCK_OBJECT)
{
_tagsLookup.Clear();
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_TagsGet.ToString();
cmd.Parameters.Add(new SqlParameter("@TagId", SqlDbType.Int) {Value = null});
var reader = cmd.ExecuteReader();
while (reader.Read())
{
var t = new Tag(reader);
if (t.ID == 0) continue;
_tagsLookup[t.Text] = t;
}
reader.Close();
}
finally
{
cmd.Connection.Dispose();
}
}
}
}
}
}

View File

@@ -0,0 +1,19 @@
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users
{
public class UIItemHelper
{
public long UIItemId { get; private set; }
public string UIItemName { get; private set; }
public bool IsVisible { get; private set; }
public short Permission { get; private set; }
public UIItemHelper(long uiItemId, short permission, bool visible, string uiItemName)
{
UIItemId = uiItemId;
Permission = permission;
IsVisible = visible;
UIItemName = uiItemName;
}
}
}

803
DataPRO/Users/User.cs Normal file
View File

@@ -0,0 +1,803 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Globalization;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using DTS.Common.Classes;
using DTS.Common.Interface.Tags;
using DTS.Common.Storage;
// ReSharper disable GenericEnumeratorNotDisposed
// ReSharper disable InconsistentNaming
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users
{
/// <summary>
/// this class encapsulates a single user
/// </summary>
public class User : TagAwareBase
{
public override TagTypes TagType => TagTypes.User;
#region constants and enums
public enum DefaultRoles
{
Administrator = 0,
PowerUser = 1,
User = 2,
Guest = 3
}
public enum UserPermissionLevels
{
Deny = 0,
Read = 1,
ReadAndExecute = 2,
Edit = 3,
Admin = 4
}
public enum Tags
{
User,
Role,
Version,
LastModified,
LastModifiedBy,
Name,
UserName,
Password,
LocalOnly,
Permissions,
Visibility,
Id
}
public enum XmlFields
{
UserName,
DisplayName,
Password,
// ReSharper disable once InconsistentNaming
IUIItemPermissions,
// ReSharper disable once InconsistentNaming
IUIItemVisibility,
Role,
LastModified,
LastModifiedBy,
Version,
LocalOnly,
UserTags
}
private const string DefaultLastModifiedBy = "---";
private const string DefaultAdminPwd = "DTSAdmin";
public const string DefaultPoweruserPwd = "PowerUser123";
private const string DefaultUserPwd = "UserNormal";
private const string DefaultAdminUsername = "Admin";
private const string DefaultGuestUsername = "Guest";
private const string DefaultPoweruserUsername = "PowerUser";
private const string DefaultUserUsername = "User";
private const int InvalidId = -1;
public const string DefaultAerouserPwd = "AeroUser123";
public const string DefaultCrashuserPwd = "CrashUser123";
public const string DefaultTSRAIRuserPwd = "TSRAIRUser123";
public const string DefaultAeroUsername = "AeroUser";
public const string DefaultCrashUsername = "CrashUser";
public const string DefaultTSRAIRUsername = "TSRAIRUser";
#endregion
#region properties
/// <summary>
/// a default user is a user with one of the default roles and names, like Admin or Guest
/// return true if is a default user
/// </summary>
public bool IsADefaultUser => UserName == GetDefaultUserName(Role);
/// <summary>
/// a default user id is 1, 2, 3, or 4 based on the default name
/// </summary>
public bool IsADefaultID => Id == GetDefaultUserId(Role);
/// <summary>
/// considered a duplicate if the same default name exists in the db
/// </summary>
public bool IsADuplicate => DuplicateFound(Role);
/// <summary>
/// hash of password is seeded and stored in xml
/// hash is seeded with computable information known about the user
/// hash is base64encoding for xml niceness
/// xml is encrypted prior to writing to file
/// </summary>
private string _password = "";
public void SetPassword(string s)
{
var b = Encoding.UTF8.GetBytes($"{s}_{UserName}");
var sha2 = SHA256.Create();
var hashed = sha2.ComputeHash(b);
s = Convert.ToBase64String(hashed);
_password = s;
OnPropertyChanged(Tags.Password.ToString());
}
/// <summary>
/// the user friendly name for a user, a display name
/// </summary>
private string _name;
public string Name
{
get => _name;
set => SetProperty(ref _name, value, Tags.Name.ToString());
}
/// <summary>
/// the user name for the user, a short unique name for the user
/// </summary>
private string _userName = string.Empty;
public string UserName
{
get => _userName;
set => SetProperty(ref _userName, value, Tags.UserName.ToString());
}
private int _id = InvalidId;
public int Id
{
get => _id;
set => SetProperty(ref _id, value, Tags.Id.ToString());
}
/// <summary>
/// the default role for the user, if a permission is not explicitly set for the user
/// it will use this default role to determine the effect permission
/// </summary>
private DefaultRoles _myRole = DefaultRoles.Guest;
public DefaultRoles Role
{
get => _myRole;
set
{
if (IsADefaultUser && _myRole != value) { throw new NotSupportedException(); }
SetProperty(ref _myRole, value, Tags.Role.ToString());
}
}
/// <summary>
/// right now the version field is updated whenever the user is updated, so it keeps
/// track of how many times it has been modified
/// </summary>
private int _version;
public int Version
{
get => _version;
set => SetProperty(ref _version, value, Tags.Version.ToString());
}
/// <summary>
/// the time the user was last modified or commited to the db
/// </summary>
private DateTime _lastModified = DateTime.MinValue;
public DateTime LastModified
{
get => _lastModified;
set => SetProperty(ref _lastModified, value, Tags.LastModified.ToString());
}
/// <summary>
/// the user that last modified the user
/// </summary>
private string _lastModifiedBy = DefaultLastModifiedBy;
public string LastModifiedBy
{
get => _lastModifiedBy;
set => SetProperty(ref _lastModifiedBy, value, Tags.LastModifiedBy.ToString());
}
/// <summary>
/// a remnant of the multiple database era, this was to mark a user as being local to this db and should never
/// be pushed to the central db
/// </summary>
private bool _bLocalOnly;
public bool LocalOnly
{
get => _bLocalOnly;
set => SetProperty(ref _bLocalOnly, value, Tags.LocalOnly.ToString());
}
/// <summary>
/// returns true if the user's role is Administrator
/// </summary>
public bool IsAdmin => Role == DefaultRoles.Administrator;
/// <summary>
/// returns true if the user's role is guest
/// </summary>
public bool IsGuest => Role == DefaultRoles.Guest;
/// <summary>
/// lookup of permissions by UI item
/// </summary>
private readonly Dictionary<IUIItems, UserPermissionLevels> _tabPermissions = new Dictionary<IUIItems, UserPermissionLevels>();
/// <summary>
/// lookup of visibility by UI item
/// </summary>
private readonly Dictionary<IUIItems, bool> _showTabs = new Dictionary<IUIItems, bool>();
/// <summary>
/// lock for accessing tab permissions or visibility
/// </summary>
private static readonly object TAB_PERMISSIONS_LOCK = new object();
#endregion properties
#region Constructors and Initializers
/// <summary>
/// used by Add user page to create a new user
/// </summary>
/// <param name="items"></param>
public User(IEnumerable<IUIItems> items)
{
Role = DefaultRoles.Guest;
foreach (var item in items)
{
SetPermission(item, item.GetDefaultRolePermission(Role));
SetShowTabFlag(item, item.GetDefaultRoleVisibility(Role));
}
}
/// <summary>
/// deep copy constructor
/// </summary>
/// <param name="user"></param>
public User(User user)
{
Name = user.Name;
UserName = user.UserName;
Version = user.Version;
_password = user._password;
Role = user.Role;
LastModified = user.LastModified;
LastModifiedBy = user.LastModifiedBy;
LocalOnly = user.LocalOnly;
var e = user._tabPermissions.GetEnumerator();
while (e.MoveNext()) { SetPermission(e.Current.Key, e.Current.Value); }
var e2 = user._showTabs.GetEnumerator();
while (e2.MoveNext()) { SetShowTabFlag(e2.Current.Key, e2.Current.Value); }
TagIDs = user.TagIDs;
}
/// <summary>
/// reserved for when creating a default user
/// </summary>
/// <param name="username"></param>
public User(string username)
{
_userName = username;
_name = username;
}
/// <summary>
/// creates a user given a role and a list of UI items
/// </summary>
/// <param name="role"></param>
/// <param name="uiItems"></param>
/// <returns></returns>
public static User CreateDefault(DefaultRoles role, IUIItems[] uiItems)
{
var uName = GetDefaultUserName(role);
var user = new User(uName)
{
_version = 1,
_myRole = role
};
switch (role)
{
case DefaultRoles.Administrator:
user.SetPassword(DefaultAdminPwd);
break;
case DefaultRoles.Guest:
user.SetPassword("");
break;
case DefaultRoles.PowerUser:
user.SetPassword(DefaultPoweruserPwd);
break;
case DefaultRoles.User:
user.SetPassword(DefaultUserPwd);
break;
default:
throw new NotSupportedException("Unknown role " + role);// TODO: handle exception properly
}
user._lastModified = DateTime.Now;
bool bShow;
UserPermissionLevels permission;
Parallel.ForEach(uiItems, uiItem =>
{
permission = uiItem.GetDefaultRolePermission(role);
bShow = uiItem.GetDefaultRoleVisibility(role);
lock (user)
{
user.SetShowTabFlag(uiItem, bShow);
user.SetPermission(uiItem, permission);
}
});
return user;
}
public static User CreateNonDefaultPowerUser(string username, IUIItems[] uiItems)
{
var user = new User(username)
{
_version = 1,
_myRole = DefaultRoles.PowerUser
};
switch (username)
{
case DefaultAeroUsername:
user.SetPassword(DefaultAerouserPwd);
break;
case DefaultCrashUsername:
user.SetPassword(DefaultCrashuserPwd);
break;
case DefaultTSRAIRUsername:
user.SetPassword(DefaultTSRAIRuserPwd);
break;
}
user._lastModified = DateTime.Now;
bool bShow;
UserPermissionLevels permission;
Parallel.ForEach(uiItems, uiItem =>
{
permission = uiItem.GetDefaultRolePermission(user.Role);
bShow = uiItem.GetDefaultRoleVisibility(user.Role);
lock (user)
{
user.SetShowTabFlag(uiItem, bShow);
user.SetPermission(uiItem, permission);
}
});
return user;
}
/// <summary>
/// constructor using db row
/// </summary>
/// <param name="row"></param>
/// <param name="items"></param>
/// <param name="permissionLookup"></param>
/// <param name="tagLookup"></param>
public User(DataRow row, IEnumerable<IUIItems> items, IReadOnlyDictionary<int, Dictionary<long, UIItemHelper>> permissionLookup, IReadOnlyDictionary<int, List<int>> tagLookup)
{
var nameToUiItem = new Dictionary<string, IUIItems>();
foreach (var item in items)
{
nameToUiItem[item.GetName()] = item;
}
var fields = Enum.GetValues(typeof(DbOperations.Users.UserFields)).Cast<DbOperations.Users.UserFields>().ToArray();
foreach (var field in fields)
{
if (DBNull.Value.Equals(row[field.ToString()])) { continue; }
switch (field)
{
case DbOperations.Users.UserFields.ID: Id = Convert.ToInt32(row[field.ToString()]); break;
case DbOperations.Users.UserFields.UserName: UserName = (string)row[field.ToString()]; break;
case DbOperations.Users.UserFields.Role: _myRole = (DefaultRoles)Convert.ToInt32(row[field.ToString()]); break;
case DbOperations.Users.UserFields.Password: _password = (string)row[field.ToString()]; break;
case DbOperations.Users.UserFields.LocalOnly: LocalOnly = Convert.ToBoolean(row[field.ToString()]); break;
case DbOperations.Users.UserFields.LastModifiedBy: LastModifiedBy = (string)row[field.ToString()]; break;
case DbOperations.Users.UserFields.LastModified: LastModified = (DateTime)row[field.ToString()]; break;
case DbOperations.Users.UserFields.DisplayName: Name = (string)row[field.ToString()]; break;
default: throw new NotSupportedException("unknown field: " + field);// TODO: handle exception properly
}
}
if (permissionLookup.ContainsKey(Id))
{
var e = permissionLookup[Id].GetEnumerator();
while (e.MoveNext())
{
if (!nameToUiItem.ContainsKey(e.Current.Value.UIItemName)) continue;
SetPermission(nameToUiItem[e.Current.Value.UIItemName], (UserPermissionLevels)e.Current.Value.Permission);
SetShowTabFlag(nameToUiItem[e.Current.Value.UIItemName], e.Current.Value.IsVisible);
}
}
if (tagLookup.ContainsKey(Id))
{
TagIDs = tagLookup[Id].ToArray();
}
}
private User() { }
#endregion
#region Methods
public void MarkChanged()
{
OnPropertyChanged(Tags.User.ToString());
}
public string GetPasswordHash() { return _password; }
public void SetPasswordHash(string value)
{
_password = value;
OnPropertyChanged(Tags.Password.ToString());
}
public bool CheckPasswordHash(string hash)
{
if (null == _password && string.IsNullOrEmpty(hash)) { return true; }
if (null == _password) { return false; }
return _password == hash;
}
public bool CheckPassword(string password)
{
try
{
if (null == _password && string.IsNullOrEmpty(password)) { return true; }
if (null == _password) { return false; }
var b = Encoding.UTF8.GetBytes(string.Format("{0}_{1}", password, UserName));
var sha2 = SHA256.Create();
var hashed = sha2.ComputeHash(b);
password = Convert.ToBase64String(hashed);
return _password == password;
}
catch (Exception) { return false; }// TODO: handle exception properly
}
public UserPermissionLevels GetPermission(IUIItems tab, IUIItems parent = null)
{
if (IsAdmin) { return UserPermissionLevels.Admin; }
lock (TAB_PERMISSIONS_LOCK)
{
if (!_tabPermissions.ContainsKey(tab))
{
return null != parent ? GetPermission(parent) : tab.GetDefaultRolePermission(Role);
}
return _tabPermissions[tab];
}
}
public string GetPermissionSerialized()
{
var sb = new StringBuilder();
lock (TAB_PERMISSIONS_LOCK)
{
var i = _tabPermissions.GetEnumerator();
while (i.MoveNext())
{
if (sb.Length > 0) { sb.Append(","); }
sb.Append(i.Current.Key.GetName());
sb.Append("=");
sb.Append(((int)i.Current.Value).ToString());
}
}
return sb.ToString();
}
public void SetPermission(IUIItems tab, UserPermissionLevels permission)
{
lock (TAB_PERMISSIONS_LOCK)
{
if (!_tabPermissions.ContainsKey(tab)) { _tabPermissions.Add(tab, permission); }
else { _tabPermissions[tab] = permission; }
OnPropertyChanged(Tags.Permissions.ToString());
}
}
public bool IsShowTabFlagSet(IUIItems tab, IUIItems parent = null)
{
//15985 I do not see a way to allow the User account to have visibility of system settings tile but not manage users
//if current view is named admin, he has visibility
//otherwise, if he has admin privileges, he has visibility
if (IsAdmin && IsADefaultUser) { return true; }
if (GetPermission(tab, parent) == UserPermissionLevels.Admin) { return true; }
if (_showTabs.ContainsKey(tab))
{
return _showTabs[tab];
}
var name = tab.GetName();
if (name.EndsWith("_Page"))
{
name = name.Substring(0, name.Length - 5);
}
var matches = from key in _showTabs.Keys where key.GetName() == name select key;
if (matches.Any())
{
return _showTabs[matches.First()];
}
if (null != parent)
{
return IsShowTabFlagSet(parent);
}
return tab.GetDefaultRoleVisibility(Role);
}
public void SetShowTabFlag(IUIItems tab, bool bFlag)
{
if (_showTabs.ContainsKey(tab)) { _showTabs[tab] = bFlag; }
else
{
_showTabs.Add(tab, bFlag);
OnPropertyChanged(Tags.Visibility.ToString());
}
}
public static string GetDefaultUserName(DefaultRoles role)
{
switch (role)
{
case DefaultRoles.Administrator: return DefaultAdminUsername;
case DefaultRoles.Guest: return DefaultGuestUsername;
case DefaultRoles.PowerUser: return DefaultPoweruserUsername;
case DefaultRoles.User: return DefaultUserUsername;
default: throw new NotSupportedException("Unknown role " + role); // TODO: handle exception properly
}
}
private static int GetDefaultUserId(DefaultRoles role)
{
return (int)role + 1;
}
public string GetVisibilitySerialized()
{
var sb = new StringBuilder();
var i2 = _showTabs.GetEnumerator();
while (i2.MoveNext())
{
if (sb.Length > 0) { sb.Append(","); }
sb.Append(i2.Current.Key.GetName());
sb.Append("=");
sb.Append(i2.Current.Value ? "1" : "0");
}
return sb.ToString();
}
protected void SetVisibilitiesFromCSV(string sVisibiles, Dictionary<string, List<IUIItems>> lookup)
{
var tokens = sVisibiles.Split(',');
foreach (var token in tokens)
{
var subtokens = token.Split('=');
if (2 != subtokens.Length) { continue; }
if (!lookup.ContainsKey(subtokens[0])) { continue; }
foreach (var item in lookup[subtokens[0]]) { _showTabs[item] = Convert.ToBoolean(Convert.ToInt32(subtokens[1])); }
}
}
protected void SetPermissionsFromCSV(string sPermissions, Dictionary<string, List<IUIItems>> lookup)
{
var tokens = sPermissions.Split(',');
foreach (var token in tokens)
{
var subtokens = token.Split('=');
if (2 != subtokens.Length) { continue; }
if (!lookup.ContainsKey(subtokens[0])) { continue; }
foreach (var item in lookup[subtokens[0]])
{
if (_tabPermissions != null)
{
lock (TAB_PERMISSIONS_LOCK)
{
_tabPermissions[item] = (UserPermissionLevels)Convert.ToInt32(subtokens[1]);
}
}
}
}
}
/// <summary>
/// True if more than one user with this name exists in the Users table
/// </summary>
/// <param name="role"></param>
/// <returns></returns>
public static bool DuplicateFound(DefaultRoles role)
{
var userName = role.ToString();
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = $"SELECT ID FROM [dbo].[Users] WHERE UserName = '{userName}'";
using (var ds = DbOperations.Connection.QueryDataSet(cmd))
{
if (ds.Tables.Count > 0)
{
return ds.Tables[0].Rows.Count > 1;
}
}
}
finally
{
cmd.Connection.Dispose();
}
}
return false;
}
public string[] GetLastUsedHardware()
{
var results = new List<string>();
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_LastUsedHardwareGet.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = Id });
#endregion
//cmd.ExecuteNonQuery();
using (var ds = DbOperations.Connection.QueryDataSet(cmd))
{
foreach (DataRow dr in ds.Tables[0].Rows)
{
var hardwareId = Convert.ToString(dr["HardwareID"]);
if (!results.Contains(hardwareId))
{
results.Add(hardwareId);
}
}
}
}
finally
{
cmd.Connection.Dispose();
}
}
return results.ToArray();
}
public void SetLastUsedHardware(List<string> hardware)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_LastUsedHardwareDelete.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = Id });
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
if (!hardware.Any()) return;
foreach (var h in hardware)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_LastUsedHardwareInsert.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = Id });
cmd.Parameters.Add(new SqlParameter("@HardwareID", SqlDbType.NVarChar, 50) { Value = h });
cmd.Parameters.Add(new SqlParameter("@SerialNumber", SqlDbType.NVarChar, 50) { Value = h }); //Not sure why this field is needed, but it was added by Alex
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
}
}
#endregion
#region XML serialization
public void WriteXML(ref XmlWriter writer)
{
writer.WriteStartElement("User");
var fields = Enum.GetValues(typeof(XmlFields)).Cast<XmlFields>().ToArray();
foreach (var field in fields)
{
writer.WriteStartElement(field.ToString());
switch (field)
{
case XmlFields.DisplayName: writer.WriteString(Name); break;
case XmlFields.IUIItemPermissions: writer.WriteString(GetPermissionSerialized()); break;
case XmlFields.IUIItemVisibility: writer.WriteString(GetVisibilitySerialized()); break;
case XmlFields.LastModified: writer.WriteString(LastModified.ToString(CultureInfo.InvariantCulture)); break;
case XmlFields.LastModifiedBy: writer.WriteString(LastModifiedBy); break;
case XmlFields.LocalOnly: writer.WriteString(LocalOnly.ToString(CultureInfo.InvariantCulture)); break;
case XmlFields.Password: writer.WriteString(_password); break;
case XmlFields.Role: writer.WriteString(Role.ToString()); break;
case XmlFields.UserName: writer.WriteString(UserName); break;
case XmlFields.UserTags: writer.WriteString(GetTagsAsCommaSeparatedString(DbOperations.TagsGet)); break;
case XmlFields.Version: writer.WriteString(Version.ToString(CultureInfo.InvariantCulture)); break;
default: throw new NotSupportedException(field.ToString()); // TODO: handle exception properly
}
writer.WriteEndElement();
}
writer.WriteEndElement();
}
public static User ReadXML(XmlElement root, IUIItems[] items)
{
var lookup = new Dictionary<string, List<IUIItems>>();
Parallel.ForEach(items, item =>
{
lock (lookup)
{
if (!lookup.ContainsKey(item.GetName())) { lookup.Add(item.GetName(), new List<IUIItems>()); }
if (!lookup[item.GetName()].Contains(item)) { lookup[item.GetName()].Add(item); }
}
});
var user = new User();
foreach (var node in root.ChildNodes)
{
if (node is XmlElement element)
{
ProcessXMLElement(element, ref user, lookup);
}
}
return user;
}
private static void ProcessXMLElement(XmlElement node, ref User user, Dictionary<string, List<IUIItems>> lookup)
{
XmlFields field;
if (Enum.TryParse(node.Name, out field))
{
switch (field)
{
case XmlFields.DisplayName: user.Name = node.InnerText; break;
case XmlFields.LastModified: user.LastModified = DateTime.Parse(node.InnerText, CultureInfo.InvariantCulture); break;
case XmlFields.LastModifiedBy: user.LastModifiedBy = node.InnerText; break;
case XmlFields.LocalOnly: user.LocalOnly = Boolean.Parse(node.InnerText); break;
case XmlFields.Password: user.SetPasswordHash(node.InnerText); break;
case XmlFields.Role: DefaultRoles role; if (Enum.TryParse(node.InnerText, out role)) { user.Role = role; } break;
case XmlFields.UserName: user.UserName = node.InnerText; break;
case XmlFields.UserTags:
user.SetTagsFromCommaSeparatedString(node.InnerText,
DbOperations.GetSQLCommand, DbOperations.TagsGet,
DbOperations.TagsGetId, DbOperations.TagsInsert); break;
case XmlFields.Version: int iTemp; if (int.TryParse(node.InnerText, NumberStyles.Any, CultureInfo.InvariantCulture, out iTemp)) { user.Version = iTemp; } break;
case XmlFields.IUIItemPermissions: user.SetPermissionsFromCSV(node.InnerText, lookup); break;
case XmlFields.IUIItemVisibility: user.SetVisibilitiesFromCSV(node.InnerText, lookup); break;
}
}
}
#endregion XML Serialization
}
}

View File

@@ -0,0 +1,570 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using DTS.Common.Classes;
using DTS.Common.Interface.Tags;
using DTS.Common.Storage;
using DTS.Common.Utilities.Logging;
using DTS.Slice.Users.UserSettings;
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users
{
public class UserCollection : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T storage, T value, string propertyName = null)
{
if (Equals(storage, value)) return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged(string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private static readonly object MyLock = new object();
private static UserCollection _userList;
public static UserCollection UsersList
{
get
{
lock (MyLock)
{
return _userList ?? (_userList = new UserCollection());
}
}
}
private UserCollection() { }
public static Dictionary<int, List<int>> GetUserToTagIdLookup()
{
var lookup = new Dictionary<int, List<int>>();
var hr = DbOperations.TagAssignmentsGet(TagTypes.User, out var records);
if (0 == hr && null != records && records.Any())
{
foreach (var record in records)
{
if (!lookup.ContainsKey(record.ObjectID))
{
lookup.Add(record.ObjectID, new List<int>());
}
lookup[record.ObjectID].Add(record.TagID);
}
}
return lookup;
}
public static User[] GetAllUsers(IUIItems[] allItems, int? uid = null)
{
lock (MyLock)
{
//keyed by user and then uiitem id
var permissionLookup = new Dictionary<int, Dictionary<long, UIItemHelper>>();
var tagsLookup = GetUserToTagIdLookup();
try
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UserUIItemSettingsGet.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = uid });
#endregion params
using (var ds = DbOperations.Connection.QueryDataSet(cmd))
{
if (ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
foreach (DataRow dr in ds.Tables[0].Rows)
{
var userId = Convert.ToInt32(dr["UserID"]);
var uiItemId = Convert.ToInt64(dr["UIItemID"]);
var permission = Convert.ToInt16(dr["Permission"]);
var visible = Convert.ToBoolean(dr["Visible"]);
var uiItemName = Convert.ToString(dr["NAME"]);
var helper = new UIItemHelper(uiItemId, permission, visible, uiItemName);
if (!permissionLookup.ContainsKey(userId))
{
permissionLookup.Add(userId, new Dictionary<long, UIItemHelper>());
}
permissionLookup[userId][uiItemId] = helper;
}
}
}
}
finally
{
cmd.Connection.Dispose();
}
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
var users = new List<User>();
try
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UsersGet.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = uid });
#endregion params
using (var ds = DbOperations.Connection.QueryDataSet(cmd))
{
if (ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
foreach (DataRow dr in ds.Tables[0].Rows)
{
try
{
users.Add(new User(dr, allItems, permissionLookup, tagsLookup));
}
catch (Exception ex)
{
APILogger.Log("Failed to read user", ex);
}
}
}
}
}
finally
{
cmd.Connection.Dispose();
}
}
}
catch (Exception ex)
{
APILogger.Log("problem getting user", ex);
}
// uid is null when we are requesting all users. This function is dual purpose and can be used to request
// a single user by passing a uid
if (null != uid) return users.ToArray();
var roles = Enum.GetValues(typeof(User.DefaultRoles)).Cast<User.DefaultRoles>().ToArray();
foreach (var role in roles)
{
var user = User.CreateDefault(role, allItems);
var bFound = users.Exists(u => u.UserName == user.UserName);
if (!bFound)
{
UsersList.Commit(user, user.UserName, allItems);
}
}
//Now add the users that are not the default for a role
var nonDefaultUser = User.CreateNonDefaultPowerUser(User.DefaultAeroUsername, allItems);
var nonDefaultUserFound = users.Exists(u => u.UserName == nonDefaultUser.UserName);
if (!nonDefaultUserFound)
{
UsersList.Commit(nonDefaultUser, nonDefaultUser.UserName, allItems);
}
nonDefaultUser = User.CreateNonDefaultPowerUser(User.DefaultCrashUsername, allItems);
nonDefaultUserFound = users.Exists(u => u.UserName == nonDefaultUser.UserName);
if (!nonDefaultUserFound)
{
UsersList.Commit(nonDefaultUser, nonDefaultUser.UserName, allItems);
}
nonDefaultUser = User.CreateNonDefaultPowerUser(User.DefaultTSRAIRUsername, allItems);
nonDefaultUserFound = users.Exists(u => u.UserName == nonDefaultUser.UserName);
if (!nonDefaultUserFound)
{
UsersList.Commit(nonDefaultUser, nonDefaultUser.UserName, allItems);
}
return users.ToArray();
}
}
public static User GetUser(int uid, IUIItems[] items)
{
var users = GetAllUsers(items, uid);
var enumerable = users ?? users.ToArray();
return !enumerable.Any() ? null : enumerable[0];
}
public static User GetUser(string username, IUIItems[] items)
{
try
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UsersGetId.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@UserName", SqlDbType.NVarChar, 50) { Value = username });
var newIdParam =
new SqlParameter("@UserId", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(newIdParam);
#endregion params
cmd.ExecuteNonQuery();
if (DBNull.Value.Equals(newIdParam.Value))
{
return null;
}
var id = int.Parse(newIdParam.Value.ToString());
return id != 0 ? GetUser(id, items) : null;
}
finally
{
cmd.Connection.Dispose();
}
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
return null;
}
public void Commit(User user, string username, IUIItems[] items)
{
try
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UsersUpdateInsert.ToString();
#region params
//cmd.Parameters.Add(new SqlParameter("@Id", SqlDbType.NVarChar, 50) { Value = user.Id });
cmd.Parameters.Add(
new SqlParameter("@UserName", SqlDbType.NVarChar, 50) { Value = user.UserName });
cmd.Parameters.Add(
new SqlParameter("@DisplayName", SqlDbType.NVarChar, 50) { Value = user.Name });
cmd.Parameters.Add(
new SqlParameter("@Password", SqlDbType.NVarChar, 2048) { Value = user.GetPasswordHash() });
cmd.Parameters.Add(new SqlParameter("@Role", SqlDbType.SmallInt) { Value = user.Role });
cmd.Parameters.Add(
new SqlParameter("@LastModified", SqlDbType.DateTime) { Value = DateTime.Now });
cmd.Parameters.Add(
new SqlParameter("@LastModifiedBy", SqlDbType.NVarChar, 50) { Value = username });
cmd.Parameters.Add(new SqlParameter("@LocalOnly", SqlDbType.Bit) { Value = user.LocalOnly });
var newIdParam =
new SqlParameter("@new_id", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(newIdParam);
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
var id = int.Parse(newIdParam.Value.ToString());
user.Id = id == 0 ? user.Id : id;
}
finally
{
cmd.Connection.Dispose();
}
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
var settings = TestSetupDefaults.GetUserSettings(user.Id);
var properties = settings.GetType().GetProperties();
Defaults.CreateOrUpdateUserSettingProperties(user.Id, properties);
InsertPermissionsAndVisibility(user, items);
InsertTags(user);
OnPropertyChanged("AllUsers");
}
/// <summary>
/// associates tags to a user
/// </summary>
/// <param name="user"></param>
private static void InsertTags(User user)
{
_ = DbOperations.TagAssignmentsDelete(user.TagType, user.Id);
if (!user.TagIDs.Any()) return;
foreach (var tag in user.TagIDs)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_TagAssignmentsInsert.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@ObjectID", SqlDbType.Int) { Value = user.Id });
cmd.Parameters.Add(new SqlParameter("@ObjectType", SqlDbType.SmallInt) { Value = user.TagType });
cmd.Parameters.Add(new SqlParameter("@TagID", SqlDbType.Int) { Value = tag });
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
}
}
public void Delete(User user)
{
lock (MyLock)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UsersDelete.ToString();
#region params
if (user.IsADefaultUser)
{
cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = user.Id });
}
cmd.Parameters.Add(
new SqlParameter("@UserName", SqlDbType.NVarChar, 50) { Value = user.UserName });
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
OnPropertyChanged("AllUsers");
}
}
public void Delete(User[] users)
{
foreach (var user in users)
{
Delete(user);
}
}
private static void InsertPermissionsAndVisibility(User user, IReadOnlyList<IUIItems> items)
{
try
{
//all our UIItems should already be in the db, so we just have to associate them now...
//but first, I guess just remove any existing associations.
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UserUIItemSettingsDelete.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@UserID", SqlDbType.NVarChar, 50) { Value = user.Id });
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
//now to insert them ... there could be a lot so we have to put them into a bunches
foreach (var item in items)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UserUIItemSettingsInsert.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@UserID", SqlDbType.Int) { Value = user.Id });
var uiItemId = item.GetID();
var userPermission = user.GetPermission(item);
var isShow = user.IsShowTabFlagSet(item);
cmd.Parameters.Add(new SqlParameter("@UIItemID", SqlDbType.Int) { Value = uiItemId });
cmd.Parameters.Add(
new SqlParameter("@Permission", SqlDbType.SmallInt) { Value = userPermission });
cmd.Parameters.Add(new SqlParameter("@Visible", SqlDbType.SmallInt) { Value = isShow });
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
}
}
catch (Exception ex)
{
APILogger.Log(ex);
}
}
//private static void UpdateAll(User user, string username)
//{
// try
// {
// using (var cmd = DbOperations.GetSQLCommand(true))
// {
// try
// {
// cmd.CommandType = CommandType.StoredProcedure;
// cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UserUpdate.ToString();
// #region params
// cmd.Parameters.Add(new SqlParameter("@UserName", SqlDbType.NVarChar, 50) {Value = user.Name});
// cmd.Parameters.Add(
// new SqlParameter("@DisplayName", SqlDbType.NVarChar, 50) {Value = user.Name});
// cmd.Parameters.Add(
// new SqlParameter("@Password", SqlDbType.NVarChar, 2048) {Value = user.GetPasswordHash()});
// cmd.Parameters.Add(new SqlParameter("@Role", SqlDbType.SmallInt) {Value = user.Role});
// cmd.Parameters.Add(
// new SqlParameter("@LastModified", SqlDbType.DateTime) {Value = DateTime.Now});
// cmd.Parameters.Add(
// new SqlParameter("@LastModifiedBy", SqlDbType.NVarChar, 50) {Value = username});
// cmd.Parameters.Add(new SqlParameter("@LocalOnly", SqlDbType.Bit) {Value = user.LocalOnly});
// var errorNumberParam =
// new SqlParameter("@errorNumber", SqlDbType.Int) {Direction = ParameterDirection.Output};
// cmd.Parameters.Add(errorNumberParam);
// var errorMessageParam =
// new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
// {
// Direction = ParameterDirection.Output
// };
// cmd.Parameters.Add(errorMessageParam);
// #endregion params
// cmd.ExecuteNonQuery();
// if (int.Parse(errorNumberParam.Value.ToString()) != 0)
// {
// //errorMessageParam.Value
// }
// }
// finally
// {
// cmd.Connection.Dispose();
// }
// }
// }
// catch (Exception ex)
// {
// APILogger.Log("Failed to update user", user.UserName, ex);
// throw;// TODO: handle exception properly
// }
//}
}
}

View File

@@ -0,0 +1,28 @@
using System.ComponentModel;
using Users.UserSettings;
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users.UserSettings
{
/// <summary>
/// this class overloads the categoryattribute to provide a localized string using our string resources
/// we also overload it so that we can use an enum to set the attribute
/// to be translated the category should exist in the string resources, otherwise you'll get
/// ##ResourceNotFound## as your translated string
/// </summary>
public class CategoryAttributeEx : CategoryAttribute
{
private readonly PropertyEnums.PropertyCategories _category;
public PropertyEnums.PropertyCategories GetCategory() { return _category; }
protected override string GetLocalizedString(string value)
{
return StringResources.ResourceManager.GetString(value) ?? "##ResourceNotFound##" + value;
}
public CategoryAttributeEx(PropertyEnums.PropertyCategories category) : base(category.ToString())
{
_category = category;
}
}
}

View File

@@ -0,0 +1,736 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Globalization;
using System.IO.Ports;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using DTS.Common;
using DTS.Common.Enums;
using DTS.Common.Enums.Sensors;
using DTS.Common.Storage;
using DTS.Common.Utilities.Logging;
namespace DTS.Slice.Users.UserSettings
{
public abstract class Defaults
{
#region Static Methods
/// <summary>
/// this function is designed to create any missing property settings if needed
/// this might happen if the database table was just created for instance
/// it will create defaults for all the settings in the db, and also settings for all users
/// currently it's used by DataPRO.App
/// </summary>
internal static void CreateAnyMissingUserSettingPropertyDefaults(Defaults userSetting)
{
//get a list of all known properties
var properties = userSetting.GetType().GetProperties();
var needToBeAdded = new Dictionary<int, PropertyInfo>();
foreach (var property in properties)
{
var id = PropertyIdAttribute.GetPropertyId(property);
needToBeAdded[id] = property;
}
//find if the property already exists in the db, if so, no need to add...
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
sql.CommandType = CommandType.Text;
sql.CommandText = "SELECT [PropertyId] from [DefaultProperties]";
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
var id = Convert.ToInt32(row["PropertyId"]);
if (needToBeAdded.ContainsKey(id))
{
needToBeAdded.Remove(id);
}
}
}
}
finally
{
sql.Connection.Dispose();
}
}
//if we have nothing to add, we are all done
if (needToBeAdded.Values.Count <= 0) return;
//otherwise add the defaults
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
var sb = new StringBuilder();
sb.Append(DbOperations.BEGIN_STATEMENT);
using (var needToBeAddedEnumerator = needToBeAdded.GetEnumerator())
{
var iIndex = 0;
while (needToBeAddedEnumerator.MoveNext())
{
var currentProperty = needToBeAddedEnumerator.Current.Value;
sb.AppendFormat(
"INSERT INTO [DefaultProperties] ([PropertyId],[PropertyName],[DefaultValue]) VALUES (@1_{0}, @2_{0}, @3_{0});",
iIndex);
DbOperations.CreateParam(sql, $"@1_{iIndex}", SqlDbType.Int,
PropertyIdAttribute.GetPropertyId(currentProperty));
DbOperations.CreateParam(sql, $"@2_{iIndex}", SqlDbType.NVarChar,
PropertyIdAttribute.GetPropertyIdEnum(currentProperty).ToString());
DbOperations.CreateParam(sql, $"@3_{iIndex}", SqlDbType.NVarChar,
GetDefaultValueAsString(currentProperty));
iIndex++;
}
}
sb.Append(DbOperations.COMMIT_STATEMENT);
sql.CommandText = sb.ToString();
DbOperations.Connection.ExecuteCommand(sql);
}
finally
{
sql.Connection.Dispose();
}
}
//finally add settings for any users we have currently
CreateMissingUserSettingProperties(needToBeAdded.Values.ToArray());
}
/// <summary>
/// creates missing user settings (for all users)
/// </summary>
/// <param name="needToBeAdded"></param>
internal static void CreateMissingUserSettingProperties(PropertyInfo[] needToBeAdded)
{
var userIds = new List<int>();
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
sql.CommandText = "SELECT ID FROM [Users]";
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
var id = Convert.ToInt32(row["ID"]);
if (!userIds.Contains(id))
{
userIds.Add(id);
}
}
}
}
finally
{
sql.Connection.Dispose();
}
}
foreach (var id in userIds)
{
CreateMissingUserSettingProperties(id, needToBeAdded);
}
}
/// <summary>
/// Inserts missing properties, and updates existing ones for given user
/// </summary>
/// <param name="id"></param>
/// <param name="allProperties"></param>
internal static void CreateOrUpdateUserSettingProperties(int id, PropertyInfo[] allProperties)
{
var existing = new HashSet<int>();
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
sql.CommandType = CommandType.Text;
sql.CommandText = "SELECT PropertyId FROM [UserProperties] WHERE UserId=@1";
DbOperations.CreateParam(sql, "@1", SqlDbType.Int, id);
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
var propertyId = Convert.ToInt32(row[0]);
existing.Add(propertyId);
}
}
}
finally
{
sql.Connection.Dispose();
}
}
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
sql.CommandType = CommandType.Text;
var index = 0;
var sb = new StringBuilder();
sb.Append(DbOperations.BEGIN_STATEMENT);
foreach (var property in allProperties)
{
var propId = PropertyIdAttribute.GetPropertyId(property);
if (existing.Contains(propId))
{
continue;
}
sb.AppendFormat(
"INSERT INTO [UserProperties] ([UserId],[PropertyId], [PropertyValue]) VALUES (@1_{0},@2_{0},@3_{0});",
index);
DbOperations.CreateParam(sql, $"@1_{index}", SqlDbType.Int, id);
DbOperations.CreateParam(sql, $"@2_{index}", SqlDbType.Int, propId);
DbOperations.CreateParam(sql, $"@3_{index}", SqlDbType.NVarChar,
GetDefaultValueAsString(property));
index++;
}
sb.Append(DbOperations.COMMIT_STATEMENT);
sql.CommandText = sb.ToString();
DbOperations.Connection.ExecuteCommand(sql);
}
finally
{
sql.Connection.Dispose();
}
}
if (existing.Any())
{
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
var index = 0;
var sb = new StringBuilder();
sb.Append(DbOperations.BEGIN_STATEMENT);
foreach (var property in allProperties)
{
var propId = PropertyIdAttribute.GetPropertyId(property);
if (!existing.Contains(propId))
{
continue;
}
sb.AppendFormat(
"UPDATE [UserProperties] SET PropertyValue=@1_{0} WHERE UserId=@2_{0} AND PropertyId=@3_{0};",
index);
DbOperations.CreateParam(sql, $"@1_{index}", SqlDbType.NVarChar,
GetUserSettingValue(id, (PropertyEnums.PropertyIds)propId, true) ?? string.Empty);
DbOperations.CreateParam(sql, $"@2_{index}", SqlDbType.Int, id);
DbOperations.CreateParam(sql, $"@3_{index}", SqlDbType.Int, propId);
index++;
}
sb.Append(DbOperations.COMMIT_STATEMENT);
sql.CommandText = sb.ToString();
sql.CommandType = CommandType.Text;
DbOperations.Connection.ExecuteCommand(sql);
}
finally { sql.Connection.Dispose(); }
}
}
}
/// <summary>
/// this funtion creates a list of settings for a specific user
/// this may happen with a new database, it's called by the
/// CreateAnyMissingUserSettingPropertyDefaults function above
/// </summary>
/// <param name="id"></param>
/// <param name="needToBeAdded"></param>
internal static void CreateMissingUserSettingProperties(int id, PropertyInfo[] needToBeAdded)
{
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
sql.CommandType = CommandType.Text;
var index = 0;
var sb = new StringBuilder();
sb.Append(DbOperations.BEGIN_STATEMENT);
foreach (var property in needToBeAdded)
{
sb.AppendFormat(
"INSERT INTO [UserProperties] ([UserId],[PropertyId], [PropertyValue]) VALUES (@1_{0},@2_{0},@3_{0});",
index);
DbOperations.CreateParam(sql, $"@1_{index}", SqlDbType.Int, id);
DbOperations.CreateParam(sql, $"@2_{index}", SqlDbType.Int,
PropertyIdAttribute.GetPropertyId(property));
DbOperations.CreateParam(sql, $"@3_{index}", SqlDbType.NVarChar,
GetDefaultValueAsString(property));
index++;
}
sb.Append(DbOperations.COMMIT_STATEMENT);
sql.CommandText = sb.ToString();
DbOperations.Connection.ExecuteCommand(sql);
}
finally
{
sql.Connection.Dispose();
}
}
}
/// <summary>
/// get an invariant version of the value for db storage
/// this is used when we create or insert a new default into the db
/// </summary>
/// <param name="property"></param>
/// <returns></returns>
internal static string GetDefaultValueAsString(PropertyInfo property)
{
if (property == null) return "";
var attr = (DefaultValueAttribute)property.GetCustomAttribute(typeof(DefaultValueAttribute));
if (attr.Value is double d)
{
return d.ToString(CultureInfo.InvariantCulture);
}
if (attr.Value is float f)
{
return f.ToString(CultureInfo.InvariantCulture);
}
return attr.Value?.ToString() ?? string.Empty;
}
/// <summary>
/// gets a collection of all settings for a given user
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
protected static Defaults GetUserSettings(int userId, Defaults settings)
{
var properties = settings.GetType().GetProperties();
//first get all properties as filled out by code
foreach (var property in properties)
{
var d = property.GetCustomAttribute<DefaultValueAttribute>();
if (d != null)
{
property.SetValue(settings, d.Value);
}
}
//next make sure we get all the defaults from the db
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_DefaultPropertiesGet.ToString();
cmd.Parameters.Add(new SqlParameter("@PropertyId", SqlDbType.Int) { Value = null });
using (var ds = DbOperations.Connection.QueryDataSet(cmd))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
var id = Convert.ToInt32(row["PropertyId"]);
var dv = Convert.ToString(row["DefaultValue"]);
settings.SetValue(id, dv);
}
}
}
catch (Exception ex) { APILogger.Log("Failed to get Default Property", ex); }
finally { cmd.Connection.Dispose(); }
}
//finally get the user specific values
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UserPropertiesGet.ToString();
cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = userId });
cmd.Parameters.Add(new SqlParameter("@PropertyId", SqlDbType.Int) { Value = null });
using (var ds = DbOperations.Connection.QueryDataSet(cmd))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
var id = Convert.ToInt32(row["PropertyId"]);
var value = Convert.ToString(row["PropertyValue"]);
settings.SetValue(id, value);
}
}
}
catch (Exception ex) { APILogger.Log("Failed to get User Property", ex); }
finally
{
cmd.Connection.Dispose();
}
}
//if a user setting for a defaults type wasn't found, handle it in the inherited class
return settings;
}
protected static Defaults _allUserSettings = null;
/// <summary>
/// sets a specific user setting in the db
/// function should handle the invariant nature of values
/// </summary>
/// <param name="userId"></param>
/// <param name="id"></param>
/// <param name="value"></param>
public static void SetUserSetting(int userId, PropertyEnums.PropertyIds id, object value)
{
var sValue = value.ToString();
if (value is double d)
{
sValue = d.ToString(CultureInfo.InvariantCulture);
}
else if (value is float f)
{
sValue = f.ToString(CultureInfo.InvariantCulture);
}
try
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UserPropertiesUpdateInsert.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = userId });
cmd.Parameters.Add(new SqlParameter("@PropertyId", SqlDbType.Int) { Value = (int)id });
cmd.Parameters.Add(new SqlParameter("@PropertyValue", SqlDbType.NVarChar) { Value = sValue });
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
catch (Exception ex) { APILogger.Log("Failed to set User Property", ex); }
finally
{
cmd.Connection.Dispose();
}
}
}
catch (Exception ex) { APILogger.LogException(ex); }
}
/// <summary>
/// inserts a default setting into the db
/// written for 18028 Remember test id suffix drop down state
/// this is in place of a migration script and updating the db when there's a new user
/// setting, instead if a setting is absent we can insert one
/// </summary>
public static void InsertUserSetting(PropertyEnums.PropertyIds property, string value)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandText =
"INSERT INTO [DefaultProperties] ([PropertyId],[PropertyName],[DefaultValue]) VALUES (@1,@2,@3)";
cmd.Parameters.Add(new SqlParameter("@1", SqlDbType.Int) { Value = (int)property });
cmd.Parameters.Add(new SqlParameter("@2", SqlDbType.NVarChar, 255) { Value = property.ToString() });
cmd.Parameters.Add(new SqlParameter("@3", SqlDbType.NVarChar, 255) { Value = value });
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
APILogger.Log(ex);
}
finally
{
cmd.Connection.Dispose();
}
}
}
/// <summary>
/// gets a specific user setting as a bool
/// </summary>
/// <param name="userId"></param>
/// <param name="property"></param>
/// <param name="defaultValue">optional parameter allowing inserting a setting if absent</param>
/// <returns></returns>
public static bool GetUserSettingValueBool(int userId, PropertyEnums.PropertyIds property, bool? defaultValue = false)
{
var defaultV = false;
var val = GetUserSettingValue(userId, property);
if (null != defaultValue && null == val)
{
//if we get here the user supplied a default value for the property
//and the property is not in the db, so insert it
InsertUserSetting(property, ((bool)defaultValue).ToString());
return (bool)defaultValue;
}
//if the string is empty or null, it won't convert, so just return the default
//otherwise return the converted value
return string.IsNullOrWhiteSpace(val) ? defaultV : Convert.ToBoolean(val);
}
/// <summary>
/// gets a specific user setting as a double
/// </summary>
/// <param name="userId"></param>
/// <param name="property"></param>
/// <returns></returns>
public static double GetUserSettingValueDouble(int userId, PropertyEnums.PropertyIds property)
{
return Convert.ToDouble(GetUserSettingValue(userId, property) ?? "0", CultureInfo.InvariantCulture);
}
/// <summary>
/// gets a specific user setting as an integer
/// </summary>
/// <param name="userId"></param>
/// <param name="property"></param>
/// <returns></returns>
public static int GetUserSettingValueInt(int userId, PropertyEnums.PropertyIds property)
{
return Convert.ToInt32(GetUserSettingValue(userId, property) ?? "0", CultureInfo.InvariantCulture);
}
/// <summary>
/// Gets a specific user setting as a string
/// </summary>
/// <param name="userid"></param>
/// <param name="property"></param>
/// <param name="defaultValue">optional parameter, if specified and the property is missing will insert the property</param>
/// <returns></returns>
public static string GetUserSettingValueString(int userid, PropertyEnums.PropertyIds property, string defaultValue = null)
{
return GetUserSettingValue(userid, property, true, defaultValue) ?? string.Empty;
}
/// <summary>
/// gets a user setting out of the db, this is an internal function used by all the public
/// single setting accessors.
/// setting is determined by user settings table, default values table
/// </summary>
/// <param name="userId"></param>
/// <param name="propertyId">numeric id if the property</param>
/// <param name="dontUseCache">whether to use cache when retrieving property value</param>
/// <param name="defaultValue">optional parameter, if setting is missing will insert property with this default value</param>
/// <returns></returns>
private static string GetUserSettingValue(int userId,
PropertyEnums.PropertyIds propertyId,
bool dontUseCache = true,
string defaultValue = null)
{
if (_allUserSettings != null && !dontUseCache)
{
var properties = _allUserSettings.GetType().GetProperties();
foreach (var prop in properties)
{
var id = PropertyIdAttribute.GetPropertyId(prop);
if (id == (int)propertyId) { return GetDefaultValueAsString(prop); }
}
}
//if the user has a specific value set for this property, just return it directly
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UserPropertiesGet.ToString();
cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = userId });
cmd.Parameters.Add(new SqlParameter("@PropertyId", SqlDbType.Int) { Value = propertyId });
using (var ds = DbOperations.Connection.QueryDataSet(cmd))
{
if (ds.Tables[0].Rows.Count > 0)
{
return Convert.ToString(ds.Tables[0].Rows[0]["PropertyValue"]);
}
}
}
catch (Exception ex) { APILogger.Log("failed to retrieve user setting, ", ex); }
finally
{
cmd.Connection.Dispose();
}
}
//if there exists a specific default value set for this property, return that
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_DefaultPropertiesGet.ToString();
cmd.Parameters.Add(new SqlParameter("@PropertyId", SqlDbType.Int) { Value = propertyId });
using (var ds = DbOperations.Connection.QueryDataSet(cmd))
{
if (ds.Tables[0].Rows.Count > 0)
{
return Convert.ToString(ds.Tables[0].Rows[0]["DefaultValue"]);
}
//there's no value, no default value, setting is unknown
//if we have a default value go ahead and insert a setting
else if (null != defaultValue)
{
InsertUserSetting(propertyId, defaultValue);
}
}
}
catch (Exception ex) { APILogger.Log("failed to retrieve default setting, ", ex); }
finally { cmd.Connection.Dispose(); }
}
//FB16165: we can get here if the db connection drops. It's been noted in the logs, so don't crash
return null;
}
#endregion
#region methods
/// <summary>
/// sets a specific value given a property id
/// this is used when deserializing values out of the db
///
/// </summary>
/// <param name="id"></param>
/// <param name="dv"></param>
protected abstract void SetValue(int id, string dv);
/// <summary>
/// resets all the settings for a user in the db, using the default settings in the db
/// </summary>
/// <param name="userId"></param>
public void ResetUserSettings(int userId)
{
//TODO: move to stored procedure
//you can do this with one command with SQL, ie like
//http://stackoverflow.com/questions/224732/sql-update-from-one-table-to-another-based-on-a-id-match
//but since we haven't ditched SQlite yet, lets include support for both by separating it into two statements
var properties = new List<Tuple<int, string>>();
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_DefaultPropertiesGet.ToString();
cmd.Parameters.Add(new SqlParameter("@PropertyId", SqlDbType.Int) { Value = null });
using (var ds = DbOperations.Connection.QueryDataSet(cmd))
{
properties.AddRange(from DataRow row in ds.Tables[0].Rows
let id = Convert.ToInt32(row["PropertyId"])
let value = Convert.ToString(row["DefaultValue"])
select new Tuple<int, string>(id, value));
}
}
finally
{
cmd.Connection.Dispose();
}
}
foreach (var property in properties)
{
using (var cmd = DbOperations.GetSQLCommand(true))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = DbOperationsEnum.StoredProcedure.sp_UserPropertiesUpdateInsert.ToString();
#region params
cmd.Parameters.Add(new SqlParameter("@UserId", SqlDbType.Int) { Value = userId });
cmd.Parameters.Add(
new SqlParameter("@PropertyId", SqlDbType.Int) { Value = property.Item1 });
cmd.Parameters.Add(
new SqlParameter("@PropertyValue", SqlDbType.NVarChar) { Value = property.Item2 });
var errorNumberParam =
new SqlParameter("@errorNumber", SqlDbType.Int) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(errorNumberParam);
var errorMessageParam =
new SqlParameter("@errorMessage", SqlDbType.NVarChar, 250)
{
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(errorMessageParam);
#endregion params
cmd.ExecuteNonQuery();
if (int.Parse(errorNumberParam.Value.ToString()) != 0)
{
//errorMessageParam.Value
}
}
finally
{
cmd.Connection.Dispose();
}
}
}
}
#endregion
}
/// <summary>
/// Subcategory example
/// </summary>
[TypeConverter(typeof(ExpandableObjectConverter))]
public class SubCategory1
{
public string Property1 { get; set; }
public string Property2 { get; set; }
public override string ToString()
{
return string.Empty;
}
}
[TypeConverter(typeof(ExpandableObjectConverter))]
public class SubCategory2
{
public string Property3 { get; set; }
public override string ToString()
{
return string.Empty;
}
}
}

View File

@@ -0,0 +1,37 @@
using System.ComponentModel;
using Users.UserSettings;
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users.UserSettings
{
/// <summary>
/// this class overloads the description attribute to allow us to use an enum
/// to set the description and to lookup the description in the string resources
/// to be translated the property should have a string resource in the form of PropertyName_Description
/// otherwise ##DescriptionNotFound## will be returned as the translated string
/// </summary>
public class DescriptionAttributeEx : DescriptionAttribute
{
private readonly PropertyEnums.PropertyIds _propertyId;
private readonly string _propertyIdString = null;
public DescriptionAttributeEx(PropertyEnums.PropertyIds propertyId)
{
_propertyId = propertyId;
}
public DescriptionAttributeEx(string propertyId)
{
_propertyIdString = propertyId;
}
public override string Description
{
get
{
if (!string.IsNullOrEmpty(_propertyIdString))
{
return StringResources.ResourceManager.GetString(_propertyIdString + "_Description") ?? @"##DescriptionNotFound##" + _propertyIdString;
}
return StringResources.ResourceManager.GetString(_propertyId + "_Description") ?? @"##DescriptionNotFound##" + _propertyId;
}
}
}
}

View File

@@ -0,0 +1,38 @@
using System.ComponentModel;
using Users.UserSettings;
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users.UserSettings
{
/// <summary>
/// this class overrides the DisplayNameAttribute to provide a translated string name, and also
/// to allow us to use an enum to create the attribute
/// to be translated a string resource should exist in the form of PropertyName_DisplayName
/// otherwise ##DisplayNameNotFound## will be returned
/// </summary>
public class DisplayAttributeEx : DisplayNameAttribute
{
private readonly PropertyEnums.PropertyIds _propertyId;
private readonly string _propertyIdString = null;
public DisplayAttributeEx(PropertyEnums.PropertyIds propertyId)
{
_propertyId = propertyId;
}
public DisplayAttributeEx(string propertyId)
{
_propertyIdString = propertyId;
}
public override string DisplayName
{
get
{
if (!string.IsNullOrWhiteSpace(_propertyIdString))
{
return StringResources.ResourceManager.GetString(_propertyIdString + "_DisplayName") ?? @"##DisplayNameNotFound##" + _propertyIdString;
}
return StringResources.ResourceManager.GetString(_propertyId + "_DisplayName") ?? @"##DisplayNameNotFound##" + _propertyId;
}
}
}
}

View File

@@ -0,0 +1,34 @@
using DTS.Common.Enums.Hardware;
using DTS.Common.Utilities.Xml;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Users.UserSettings
{
public class OptimizationSettings
{
public List<Setting> Settings { get; set; }
public OptimizationSettings()
{
}
public OptimizationSettings(string xmlOptimizationSettings)
{
Settings = XmlToObject<OptimizationSettings>.FromXml(xmlOptimizationSettings).Settings;
}
public class Setting
{
public HardwareTypes HardwareType { get; set; }
public List<TransferSpeedSampleRate> TransferSpeedSampleRateSettings { get; set; }
}
public class TransferSpeedSampleRate
{
public float MaxTransferSpeed { get; set; }
public float MinTransferSpeed { get; set; }
public double SampleRate { get; set; }
}
}
}

View File

@@ -0,0 +1,386 @@
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users.UserSettings
{
/// <summary>
/// this class holds enums used for user properties/settings
/// </summary>
public abstract class PropertyEnums
{
/// <summary>
/// here are all the categories that user settings can come in currently
/// this is used to group properties in a propertygrid
/// </summary>
public enum PropertyCategories
{
TestInfo,
TestDetails,
DiagnosticOptions,
RealtimeOptions,
ArmChecklist,
ExportOptions,
UploadOptions,
UserHistory,
ClockSyncOptions,
UARTOptions,
EmbeddedSensorSampleRateOptions,
WakeMethodOptions,
EmbeddedSensorTriggerOptions,
TestHistoryOptions
}
/// <summary>
/// used to order the properties within a category
///
/// </summary>
public enum PropertyOrders
{
//test info
AutoExpandInfoSections,
AllowAdvanceRecordingModes,
AllowTSRAIRRecordingModes,
AllowUARTRecordingModes,
AllowActiveRamRecordingModes,
UseAdvancedStreamingProfiles,
DefaultRecordingMode,
DefaultNumberOfEvents,
DefaultSampleRate,
DefaultPreTriggerSeconds,
DefaultPostTriggerSeconds,
AllowStreamingModes,
DefaultStreaming,
DefaultAutoArm,
DefaultAutoArmRepeatEnable,
DefaultAutoArmPreserveDiagnostics,
DefaultDownloadROI,
DefaultROIStart,
DefaultROIEnd,
DefaultViewROI,
DefaultDownloadAll,
DefaultViewAll,
DefaultWarnMissingTrigger,
DefaultTestSetupTag,
//test details
DefaultCheckoutMode,
AlignUDPToPPS,
DefaultSuppressMissingSensorsWarning,
DefaultSensorCalibrationBehavior,
SupressQuitTestWarning,
SuppressViewAllRealtime,
SupressViewAllViewer,
DefaultCommonStatusLine,
DefaultTriggerCheckStep,
DefaultMeasureSquibResistancesStep,
DefaultAutomaticMode,
DefaultTestSetupAutomaticProgressDelaySeconds,
DefaultWarnOnFailedBattery,
DefaultIgnoreShortedStart,
DefaultIgnoreShortedTrigger,
//diagnostic options
DefaultRequireAllUnitsPassDiagnostics,
DefaultRequireUserConfirmationOnErrors,
DefaultAllowMissingSensors,
DefaultRequireSensorIdFound,
DefaultTestExcitationWarmupSeconds,
DefaultTestExcitationTOMWarmupDelayMS,
DefaultTestExcitationIEPEWarmupDelayMS,
DefaultRunPostTestDiagnostics,
DefaultTreeModeDiagnostics,
ArmTriggerDiagnosticsRunOnNextStep,
//RealtimeOptions
DefaultViewRealtime,
DefaultRealtimeGraphCount,
RealtimeChartWidthInSeconds,
DefaultUDPStreamProfile,
DefaultUDPStreamAddress,
DefaultUDPStreamTimeChannelId,
DefaultUDPStreamDataChannelId,
DefaultUDPStreamTmNSConfig,
DefaultIRIGTimeDataPacketIntervalMs,
DefaultUDPStreamMaskEUMetaData,
//15959 Realtime Sample Rate needs to be per seat instead of site wide
RealtimeSampleRateEthernetSLICE,
RealtimeSampleRateSLICE6,
RealtimeSampleRateUSBSLICE,
RealtimeSampleRateTDAS,
RealtimeSampleRateTDASSIM,
//armchecklist
DefaultArmCheckListStep,
DefaultCheckListBatteryVoltageCheck,
DefaultCheckListInputVoltageCheck,
ArmChecklistRequiredIfTOM,
DefaultCheckListSquibResistanceCheck,
DefaultCheckListSensorIdCheck,
DefaultCheckListTriggerStartCheck,
DefaultCheckListTiltSensorCheck,
DefaultCheckListTemperatureCheck,
DefaultCheckListClockSyncCheck,
DefaultCheckListMustPass,
//ExportOptions
DefaultExport,
ExportCSVUnfiltered,
ExportCSVFiltered,
ExportCSVMV,
ExportCSVADC,
ExportDiademADC,
ExportISOUnFiltered,
ExportISOFiltered,
ExportTDASADC,
ExportToyotaUnfiltered,
ExportToyotaFiltered,
ExportTSVUnfiltered,
ExportTSVFiltered,
ExportRDFADC,
ExportTDMSADC,
ExportChryslerDDAS,
ExportHDFUnfiltered,
ExportHDFFiltered,
ExportHDFMV,
ExportHDFADC,
ExportXLSXUnfiltered,
ExportXLSXFiltered,
ExportSomatUnfiltered,
ExportSomatFiltered,
ExportASC,
//UploadOptions
UploadData,
DefaultUploadFolder,
DefaultUploadExportsOnly,
//clock sync
DefaultClockSyncProfileMaster,
DefaultClockSyncProfileSlave,
DefaultPTPDomainID,
//uart
DefaultUARTBaudRate,
DefaultUARTDataBits,
DefaultUARTStopBits,
DefaultUARTParity,
DefaultUARTFlowControl,
DefaultUARTDataFormat,
//embedded sensors
DefaultEmbeddedLowGLinearAccelerometerSampleRate,
DefaultEmbeddedHighGLinearAccelerometerSampleRate,
DefaultEmbeddedAngularAccelerometerSampleRate,
DefaultEmbeddedAngularAccelerometerAndRateSensorSampleRate,
DefaultEmbeddedAtmosphericSensorSampleRate,
//power management
//wake up
DefaultMotionDetectDelayMs,
DefaultMotionQualificationPeriodMs,
DefaultMotionDetectInactivityS,
DefaultTimeSessionDuration,
//embedded sensor triggers
DefaultEmbeddedHighGLinearAccelerometerTrigger,
DefaultEmbeddedHighGLinearAccelerometerTriggerAboveAndBelow,
DefaultTimedIntervalTrigger,
DefaultIntervalBetweenEventStartsMinutes,
DefaultTimedIntervalUnit,
DefaultTimedIntervalEventDurationMs,
DefaultTimedIntervalNumberOfEvents,
DefaultRTCScheduleTrigger,
DefaultRTCScheduleStartTime,
DefaultRTCScheduleDuration,
DefaultStoreTestHistoryInDb,
DefaultStoreSensorTestHistoryInDb,
DefaultStoreTestSetupXmlInDb
}
/// <summary>
/// this is used to define the id for all known properties, which is used
/// in serializing/deserializing to the db
/// it's also used to handle displayname and description translations
/// </summary>
public enum PropertyIds
{
DefaultUploadEnabled = 102,
DefaultTestSampleRate = 103,
DefaultPostTriggerSeconds = 104,
DefaultPreTriggerSeconds = 105,
DefaultTriggerCheckStep = 106,
DefaultRealtimeGraphCount = 107,
DefaultROIStart = 108,
DefaultROIEnd = 109,
DefaultDownloadROI = 110,
DefaultViewROI = 111,
DefaultDownloadAll = 112,
DefaultViewAll = 113,
DefaultRequireAllUnitsPassDiagnostics = 115,
DefaultRequireUserConfirmationOnErrors = 116,
DefaultAllowMissingSensors = 117,
DefaultRunPostTestDiagnostics = 124,
DefaultArmCheckListStep = 126,
DefaultCheckListInputVoltageCheck = 127,
DefaultCheckListBatteryVoltageCheck = 128,
DefaultCheckListSquibResistanceCheck = 129,
DefaultCheckListSensorIdCheck = 130,
DefaultCheckListTriggerStartCheck = 131,
DefaultRequireSensorIdFound = 132,
DefaultCheckListMustPass = 133,
DefaultViewRealtime = 134,
DefaultExport = 135,
DefaultExportFormat = 137,
DefaultCheckListTiltSensorCheck = 138,
ExportCSVUnfiltered = 139,
ExportCSVFiltered = 140,
ExportISOUnFiltered = 141,
ExportISOFiltered = 142,
ExportSomatUnfiltered = 143,
ExportSomatFiltered = 144,
ExportTDMSADC = 145,
ExportToyotaUnfiltered = 146,
ExportToyotaFiltered = 147,
ExportTSVUnfiltered = 148,
ExportTSVFiltered = 149,
ExportTDASADC = 150,
ExportRDFADC = 151,
ExportChryslerDDAS = 152,
ExportHDFUnfiltered = 153,
ExportHDFFiltered = 154,
ExportHDFMV = 155,
ExportHDFADC = 156,
ExportXLSXUnfiltered = 157,
ExportXLSXFiltered = 158,
DefaultCheckoutMode = 159,
SupressQuitTestWarning = 160,
SuppressViewAllRealtime = 161,
SupressViewAllViewer = 162,
DefaultCommonStatusLine = 163,
DefaultAutomaticMode = 164,
DefaultTestSetupAutomaticProgressDelaySeconds = 165,
DefaultWarnOnFailedBattery = 166,
DefaultUploadFolder = 167,
DefaultAutoArm = 168,
AllowAdvancedRecordingModes = 169,
DefaultRecordingMode = 170,
ExportDiademADC = 171,
DefaultTestExcitationWarmupSeconds = 172,
DefaultCheckListTemperatureCheck = 173,
DefaultUploadExportsOnly = 174,
ExportCSVMV = 175,
ExportCSVADC = 176,
DefaultTestExcitationTOMWarmupDelayMS = 177,
DefaultTestExcitationIEPEWarmupDelayMS = 178,
RealtimeChartWidthInSeconds = 301,
DefaultTreeModeDiagnostics = 302,
ArmChecklistRequiredIfTOM = 303,
DefaultSuppressMissingSensorsWarning = 304,
ArmTriggerDiagnosticsRunOnNextStep = 305,
DefaultSensorCalibrationBehavior = 306,
RealtimeSampleRateEthernetSLICE = 307,
RealtimeSampleRateSLICE6 = 308,
RealtimeSampleRateUSBSLICE = 309,
RealtimeSampleRateTDAS = 310,
RealtimeSampleRateTDASSIM = 311,
UsersCurrentTestSetup = 401,
LastRunTestSetup = 402,
LastUsedSampleRate = 403,
ApplySensorDataToBlankChannels = 404,
ShowOptionsWhenApplyingSensorToBlankChannel = 405,
DefaultStreaming = 406,
DefaultCheckListClockSyncCheck = 407,
DefaultClockSyncProfileMaster = 408,
DefaultClockSyncProfileSlave = 409,
AllowUARTRecordingModes = 410,
DefaultUARTBaudRate = 411,
DefaultUARTDataBits = 412,
DefaultUARTStopBits = 413,
DefaultUARTParity = 414,
DefaultUARTFlowControl = 415,
DefaultUDPStreamProfile = 416,
DefaultUDPStreamTimeChannelId = 417,
DefaultUDPStreamDataChannelId = 418,
DefaultUDPStreamTmNSConfig = 419,
DefaultIRIGTimeDataPacketIntervalMs = 420,
DefaultAutoArmRepeatEnable = 421,
DefaultAutoArmPreserveDiagnostics = 422,
DefaultMeasureSquibResistancesStep = 423,
DefaultNumberOfEvents = 424,
//17566 Config option to "Auto expand" test info sections.
AutoExpandInfoSections = 425,
ExpandMainInfo = 426,
ExpandTestInfo = 427,
ExpandTestDiag = 428,
ExpandTestRealtime = 429,
ExpandTestClockSync = 430,
ExpandTestArmChecklist = 431,
ExpandTestUpload = 432,
ExpandTestExport = 433,
ApplyHardwareAssignmentInHardwareDisco = 434,
DefaultEmbeddedLowGLinearAccelerometerSampleRate = 435,
DefaultEmbeddedHighGLinearAccelerometerSampleRate = 436,
DefaultEmbeddedAngularAccelerometerSampleRate = 437,
DefaultEmbeddedAngularAccelerometerAndRateSensorSampleRate = 438,
DefaultEmbeddedAtmosphericSensorSampleRate = 439,
DefaultWakeMethod = 441,
DefaultMotionDetectDelayMs = 442,
DefaultMotionQualificationPeriodMs = 443,
DefaultMotionDetectInactivityS = 444,
DefaultTimeSessionDuration = 447,
DefaultEmbeddedHighGLinearAccelerometerTrigger = 453,
DefaultEmbeddedHighGLinearAccelerometerTriggerAboveAndBelow = 454,
DefaultTimedIntervalTrigger = 468,
DefaultIntervalBetweenEventStartsMinutes = 469,
DefaultTimedIntervalUnit = 470,
DefaultTimedIntervalEventDurationMs = 471,
DefaultTimedIntervalNumberOfEvents = 472,
DefaultRTCScheduleTrigger = 473,
DefaultRTCScheduleStartTime = 474,
DefaultRTCScheduleDuration = 475,
DefaultStoreTestHistoryInDb = 476,
DefaultStoreSensorTestHistoryInDb = 477,
DefaultStoreTestSetupXmlInDb = 478,
DefaultWarnMissingTrigger = 479,
AllowStreamingModes = 480,
//whether to remember test id prefix/suffix
//18028 Remember test id suffix drop down state
StoreTestIdAffixes = 481,
TestIdPrefix = 482,
TestIdSuffix = 483,
//18361
DefaultUARTDataFormat = 484,
//18362
DefaultUDPStreamAddress = 485,
DefaultUDPStreamMaskEUMetaData = 486,
DefaultTestSetupTag = 487,
AllowTSRAIRRecordingModes = 488,
ExportASC = 489,
//29835
DefaultIgnoreShortedStart = 490,
DefaultIgnoreShortedTrigger = 491,
//31840
DefaultUseAdvancedUDPStreamProfiles = 492,
//30513
DefaultPTPDomainID = 493,
//31841
AllowActiveRamRecordingModes = 494,
//39470
AlignUDPToPPS = 495,
//44881
DefaultCANIsFD = 497,
DefaultCANArbBaseBitrate = 498,
DefaultCANArbBaseSJW = 499,
DefaultCANDataBitrate = 500,
DefaultCANDataSJW = 501,
DefaultCANFileType = 502,
}
}
}

View File

@@ -0,0 +1,53 @@
using System;
using System.Linq;
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users.UserSettings
{
/// <summary>
/// this PropertyId attribute is a little more complex than some of the other attributes
/// it can be associated with an enum or an integer, in the db obviously properties are keyed by
/// property id as an integer, but for convenience in code we use the enum form
/// this attribute lets you store the property id for a property and get either the id or enum value
/// </summary>
public class PropertyIdAttribute : Attribute
{
private readonly PropertyEnums.PropertyIds _propertyId;
/// <summary>
/// returns the property id from a property
/// </summary>
/// <param name="o"></param>
/// <returns></returns>
public static int GetPropertyId(System.Reflection.PropertyInfo o)
{
if (o == null) throw new NullReferenceException("GetPropertyId called on a null reference");
var attr = o.GetCustomAttributes(typeof(PropertyIdAttribute), false);
if (null == attr || 0 == attr.Length)
{
throw new NullReferenceException("GetPropertyId called on an object with no PropertyIdAttribute, object: " + o);
}
return (int)((PropertyIdAttribute)attr.First())._propertyId;
}
/// <summary>
/// returns the propertyid (as an enum) from a property
/// </summary>
/// <param name="o"></param>
/// <returns></returns>
public static PropertyEnums.PropertyIds GetPropertyIdEnum(System.Reflection.PropertyInfo o)
{
if (o == null) throw new NullReferenceException();
var attr = o.GetCustomAttributes(typeof(PropertyIdAttribute), false);
if (null == attr || 0 == attr.Length)
{
throw new NullReferenceException();
}
return ((PropertyIdAttribute)attr.First())._propertyId;
}
public PropertyIdAttribute(PropertyEnums.PropertyIds propertyId)
{
_propertyId = propertyId;
}
}
}

View File

@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Globalization;
using DTS.Common.Settings;
namespace DTS.Slice.Users.UserSettings
{
public class SampleRateConverter : DoubleConverter
{
List<double> _validSampleRateList = new List<double>();
private const int SampleRateIndiceCountDefault = 24;
private const int SPSINDICE_COUNT = 56;
private const string SAMPLERATE_INDEX = "SPSINDEX_";
public static int[] AvailableSampleRatesDefault = new int[]
{
5,
50,
100,
200,
250, //TDC rates start here, everything from here to next comment is in default TDC.ini
500,
1000,
2000,
2500,
5000,
8000,
10000,
12500,
20000,
25000,
40000,
50000,
60000,
75000,
100000,
150000,
300000, //TDC rates end here
400000,
500000,
1000000
};
public SampleRateConverter()
{
}
//public SampleRateConverter(List<double> validSampleRateList)
//{
// _validSampleRateList = validSampleRateList;
//}
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
var SampleRateIndiceCount = SettingsDB.GetGlobalValueInt(SPSINDICE_COUNT.ToString(), SampleRateIndiceCountDefault);
_validSampleRateList.Clear();
for (var i = 0; i < SampleRateIndiceCount; i++)
{
var defaultValue = -1;
if (i < AvailableSampleRatesDefault.Length) { defaultValue = AvailableSampleRatesDefault[i]; }
var value = SettingsDB.GetGlobalValueInt(SAMPLERATE_INDEX + i.ToString(CultureInfo.InvariantCulture), defaultValue);
if (_validSampleRateList.Contains(value)) continue;
if (value > 0) { _validSampleRateList.Add(Convert.ToDouble(value)); }
}
return new StandardValuesCollection(_validSampleRateList.ToArray());
}
public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
{
return true;
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
return base.ConvertTo(context, culture, value, destinationType);
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type t)
{
return base.CanConvertTo(context, t);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,588 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="DefaultPostTriggerSeconds_Description" xml:space="preserve">
<value>ポストトリガー 記録時間(サーキュラーバッファーモード)または記録時間(レコーダーモード)の設定です。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultPostTriggerSeconds_DisplayName" xml:space="preserve">
<value>ポストトリガー 記録時間 / 記録時間 の既定値(秒)</value>
</data>
<data name="DefaultTestSampleRate_Description" xml:space="preserve">
<value>サンプルレート(sps)の設定。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultTestSampleRate_DisplayName" xml:space="preserve">
<value>サンプルレートの既定値(sps)</value>
</data>
<data name="DefaultTestSettings" xml:space="preserve">
<value>Test settings</value>
</data>
<data name="DefaultUploadEnabled" xml:space="preserve">
<value>Upload</value>
</data>
<data name="test" xml:space="preserve">
<value>試験</value>
</data>
<data name="ArmChecklistRequiredIfTOM_Description" xml:space="preserve">
<value>この項目をチェックすると、TOMが存在する場合には「アーム直前診断を使う」のオンオフにかかわらずARM直前診断を実行します。</value>
</data>
<data name="ArmChecklistRequiredIfTOM_DisplayName" xml:space="preserve">
<value>TOMが存在する場合はARM直前診断を実行する (推奨)</value>
</data>
<data name="ArmTriggerDiagnosticsRunOnNextStep_Description" xml:space="preserve">
<value>ダイアグのステップが選択されたらすぐにユーザの入力を待たずに全チャンネルのダイアグを開始します</value>
</data>
<data name="ArmTriggerDiagnosticsRunOnNextStep_DisplayName" xml:space="preserve">
<value>ダイアグのステップが選択されたらすぐに全チャンネルのダイアグを開始する</value>
</data>
<data name="DefaultAllowMissingSensors_Description" xml:space="preserve">
<value>すべてのセンサがみつからない場合に試験を続行できるかの設定。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultAllowMissingSensors_DisplayName" xml:space="preserve">
<value>センサーが見つからない状態を許可</value>
</data>
<data name="DefaultRequireSensorIdFound_Description" xml:space="preserve">
<value>この項目がチェックされていると、センサID照合の時にセンサーIDの登録されているセンサのマニュアルアサインは不可能になります。</value>
</data>
<data name="DefaultRequireSensorIdFound_DisplayName" xml:space="preserve">
<value>センサーIDが登録されている場合はIDを認識しないと進めない</value>
</data>
<data name="DefaultArmCheckListStep_Description" xml:space="preserve">
<value>アーム直前診断を実行するかどうか。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultArmCheckListStep_DisplayName" xml:space="preserve">
<value>アーム直前診断を使う</value>
</data>
<data name="DefaultCheckListBatteryVoltageCheck_Description" xml:space="preserve">
<value>アーム直前診断でバッテリー電圧の診断をするかどうか。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultCheckListBatteryVoltageCheck_DisplayName" xml:space="preserve">
<value>バッテリー電圧診断</value>
</data>
<data name="DefaultCheckListInputVoltageCheck_Description" xml:space="preserve">
<value>アーム直前診断で外部電源電圧の診断をするかどうか。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultCheckListInputVoltageCheck_DisplayName" xml:space="preserve">
<value>外部電源電圧診断</value>
</data>
<data name="DefaultCheckListMustPass_Description" xml:space="preserve">
<value>この項目がチェックされていると、アーム直前診断ですべてがパスしないとARMができません。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultCheckListMustPass_DisplayName" xml:space="preserve">
<value>全ユニットがアーム直前診断をパスすることを要求</value>
</data>
<data name="DefaultCheckListSensorIdCheck_Description" xml:space="preserve">
<value>アーム直前診断でセンサIDの照合をするかどうか。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultCheckListSensorIdCheck_DisplayName" xml:space="preserve">
<value>センサーID照合</value>
</data>
<data name="DefaultCheckListSquibResistanceCheck_Description" xml:space="preserve">
<value>アーム直前診断でスクイブ抵抗値のチェックをするかどうか。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultCheckListSquibResistanceCheck_DisplayName" xml:space="preserve">
<value>スクイブ抵抗診断(推奨)</value>
</data>
<data name="DefaultCheckListTriggerStartCheck_Description" xml:space="preserve">
<value>この項目サポートされていませんのではチェックをしないでください</value>
</data>
<data name="DefaultCheckListTriggerStartCheck_DisplayName" xml:space="preserve">
<value>(この項目はチェックしないでください)</value>
</data>
<data name="DefaultDownloadAll_Description" xml:space="preserve">
<value>全記録時間のダウンロードを実行する場合にチェックします。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultDownloadAll_DisplayName" xml:space="preserve">
<value>全記録時間をダウンロードする</value>
</data>
<data name="DefaultDownloadROI_Description" xml:space="preserve">
<value>指定時間(ROI)のダウンロードを実行する場合にチェックします。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultDownloadROI_DisplayName" xml:space="preserve">
<value>指定時間(ROI)をダウンロードする</value>
</data>
<data name="DefaultExport_Description" xml:space="preserve">
<value>データのエクスポートを実行する場合にチェックします。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultExport_DisplayName" xml:space="preserve">
<value>データのエクスポートをする</value>
</data>
<data name="DefaultPreTriggerSeconds_Description" xml:space="preserve">
<value>プリトリガー 記録時間の設定です。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultPreTriggerSeconds_DisplayName" xml:space="preserve">
<value>プリトリガー 記録時間の既定値(秒)</value>
</data>
<data name="DefaultRealtimeGraphCount_Description" xml:space="preserve">
<value>リアルタイム表示の同時表示チャンネル数の設定です。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultRealtimeGraphCount_DisplayName" xml:space="preserve">
<value> グラフの数</value>
</data>
<data name="DefaultRequireAllUnitsPassDiagnostics_Description" xml:space="preserve">
<value>全てのダイアグ項目がパスにならなかった場合、試験を続けられるかの設定。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultRequireAllUnitsPassDiagnostics_DisplayName" xml:space="preserve">
<value>全ユニットがダイアグをパスすることを要求</value>
</data>
<data name="DefaultRequireUserConfirmationOnErrors_Description" xml:space="preserve">
<value>ダイアグまたは試験実施においてエラーは発生した場合、ユーザーに確認を要求するかどうか。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultRequireUserConfirmationOnErrors_DisplayName" xml:space="preserve">
<value>エラーの確認をユーザーに要求する</value>
</data>
<data name="DefaultROIEnd_Description" xml:space="preserve">
<value>指定時間の終了時刻の設定です。トリガ前はマイナス、トリガ後はプラスの値になります。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultROIEnd_DisplayName" xml:space="preserve">
<value>指定時間 終了(秒)</value>
</data>
<data name="DefaultROIStart_Description" xml:space="preserve">
<value>指定時間の開始時刻の設定です。トリガ前はマイナス、トリガ後はプラスの値になります。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultROIStart_DisplayName" xml:space="preserve">
<value>指定時間 開始(秒)</value>
</data>
<data name="DefaultRunPostTestDiagnostics_Description" xml:space="preserve">
<value>試験後ダイアグを実行するかどうかの設定。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultRunPostTestDiagnostics_DisplayName" xml:space="preserve">
<value>試験後ダイアグの実行</value>
</data>
<data name="DefaultSuppressMissingSensorsWarning_Description" xml:space="preserve">
<value>すべてのセンサが接続されていない時の警告の有無を設定します</value>
</data>
<data name="DefaultSuppressMissingSensorsWarning_DisplayName" xml:space="preserve">
<value>すべてのセンサが接続されていない時の警告を表示しない</value>
</data>
<data name="DefaultTreeModeDiagnostics_Description" xml:space="preserve">
<value>ダイアグ結果のデフォルト表示方法。チェックするとツリービュー、チェックしないとテーブル ビューになります。</value>
</data>
<data name="DefaultTreeModeDiagnostics_DisplayName" xml:space="preserve">
<value>ダイアグでツリー ビューを使用する (チェックしないとテーブル ビュー)</value>
</data>
<data name="DefaultTriggerCheckStep_Description" xml:space="preserve">
<value>トリガーチェックを実行するかどうか、新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultTriggerCheckStep_DisplayName" xml:space="preserve">
<value>トリガーチェックを実行する</value>
</data>
<data name="DefaultUploadEnabled_Description" xml:space="preserve">
<value>データのアップロードをするかどうかの設定。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultUploadEnabled_DisplayName" xml:space="preserve">
<value>データのアップロードをする</value>
</data>
<data name="DefaultViewAll_Description" xml:space="preserve">
<value>全記録時間の表示を行うかどうかの設定。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultViewAll_DisplayName" xml:space="preserve">
<value>全記録時間の表示</value>
</data>
<data name="DefaultViewRealtime_Description" xml:space="preserve">
<value>リアルタイム表示を行うかどうかの設定。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultViewRealtime_DisplayName" xml:space="preserve">
<value>リアルタイム表示をする</value>
</data>
<data name="DefaultViewROI_Description" xml:space="preserve">
<value>指定時間の表示/非表示設定。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultViewROI_DisplayName" xml:space="preserve">
<value>指定時間の表示</value>
</data>
<data name="LastRunTestSetup_Description" xml:space="preserve">
<value>The last run test setup</value>
</data>
<data name="LastRunTestSetup_DisplayName" xml:space="preserve">
<value>Last run test setup</value>
</data>
<data name="LastUsedSampleRate_Description" xml:space="preserve">
<value>The last used sample rate (per second)</value>
</data>
<data name="LastUsedSampleRate_DisplayName" xml:space="preserve">
<value>Last used sample rate</value>
</data>
<data name="RealtimeChartWidthInSeconds_Description" xml:space="preserve">
<value> 横軸に表示する時間(秒)の設定。</value>
</data>
<data name="RealtimeChartWidthInSeconds_DisplayName" xml:space="preserve">
<value> 横軸に表示する時間(秒)</value>
</data>
<data name="RealtimeSettings" xml:space="preserve">
<value>Realtime settings</value>
</data>
<data name="TestOptions" xml:space="preserve">
<value>Test options</value>
</data>
<data name="UserHistory" xml:space="preserve">
<value>User history</value>
</data>
<data name="UsersCurrentTestSetup_Description" xml:space="preserve">
<value>The active test setup</value>
</data>
<data name="UsersCurrentTestSetup_DisplayName" xml:space="preserve">
<value>Current test setup</value>
</data>
<data name="DefaultCheckListTiltSensorCheck_Description" xml:space="preserve">
<value>アーム直前診断でチルトセンサーのチェックをするかどうか。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultCheckListTiltSensorCheck_DisplayName" xml:space="preserve">
<value>チルトセンサーのチェック</value>
</data>
<data name="AllowAdvancedRecordingModes_Description" xml:space="preserve">
<value>サーキュラーバッファモード、レコーダーモード以外の記録モードを選択可能にします</value>
</data>
<data name="AllowAdvancedRecordingModes_DisplayName" xml:space="preserve">
<value>アドバンス記録モードを使用可能にする</value>
</data>
<data name="ArmChecklist" xml:space="preserve">
<value>(4) アーム直前診断</value>
</data>
<data name="DefaultAutoArm_Description" xml:space="preserve">
<value>DASをオートアームモードに設定するにはこの項目をチェックしてください。</value>
</data>
<data name="DefaultAutoArm_DisplayName" xml:space="preserve">
<value>DASをオートアームモードに設定する</value>
</data>
<data name="DefaultAutomaticMode_Description" xml:space="preserve">
<value>自動モードを使用するかどうか 新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultAutomaticMode_DisplayName" xml:space="preserve">
<value>自動モードを使用する</value>
</data>
<data name="DefaultCheckoutMode_Description" xml:space="preserve">
<value>新規にテストセトアップを作成する時、チェックアウトモードをオンにします。</value>
</data>
<data name="DefaultCheckoutMode_DisplayName" xml:space="preserve">
<value>チェックアウトモード ==スクイブ出力をしない== (通常OFF)</value>
</data>
<data name="DefaultCommonStatusLine_Description" xml:space="preserve">
<value>ステータス信号の相互監視機能の有無、新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultCommonStatusLine_DisplayName" xml:space="preserve">
<value>ステータス信号の相互監視(通常ON)</value>
</data>
<data name="DefaultRecordingMode_Description" xml:space="preserve">
<value>記録モードの設定です。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultRecordingMode_DisplayName" xml:space="preserve">
<value>記録モード</value>
</data>
<data name="DefaultTestSetupAutomaticProgressDelaySeconds_Description" xml:space="preserve">
<value>自動モードで次のステップに進むまでの待機時間(秒)。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultTestSetupAutomaticProgressDelaySeconds_DisplayName" xml:space="preserve">
<value>自動モードで次のステップに進むまでの待機時間(秒)</value>
</data>
<data name="DefaultUploadFolder_Description" xml:space="preserve">
<value>新規テストセトアップにおけるデフォルトアップロードフォルダを設定します。</value>
</data>
<data name="DefaultUploadFolder_DisplayName" xml:space="preserve">
<value>アップロード先フォルダ</value>
</data>
<data name="DefaultWarnOnFailedBattery_Description" xml:space="preserve">
<value>バッテリー異常、バッテリーなしを警告するかどうかの設定。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultWarnOnFailedBattery_DisplayName" xml:space="preserve">
<value>バッテリー異常、バッテリーなしを警告する</value>
</data>
<data name="DiagnosticOptions" xml:space="preserve">
<value>(2) ダイアグオプション</value>
</data>
<data name="DownloadAndViewOptions" xml:space="preserve">
<value>(6) ダウンロード/表示 オプション</value>
</data>
<data name="ExportChryslerDDAS_Description" xml:space="preserve">
<value>Controls whether export DDAS unfiltered EU data is enabled by default for new test setups</value>
</data>
<data name="ExportChryslerDDAS_DisplayName" xml:space="preserve">
<value>DDAS EU フィルタ有り </value>
</data>
<data name="ExportCSVFiltered_Description" xml:space="preserve">
<value>CSV EU フィルタ有り のエクスポートを有効にします。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="ExportCSVFiltered_DisplayName" xml:space="preserve">
<value>CSV EU フィルタ有り</value>
</data>
<data name="ExportCSVUnfiltered_Description" xml:space="preserve">
<value>CSV EU フィルタ無し のエクスポートを有効にします。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="ExportCSVUnfiltered_DisplayName" xml:space="preserve">
<value>CSV EU フィルタ無し</value>
</data>
<data name="ExportHDFADC_Description" xml:space="preserve">
<value>Controls whether export HDF ADC data is enabled by default for new test setups</value>
</data>
<data name="ExportHDFADC_DisplayName" xml:space="preserve">
<value>HDF ADC</value>
</data>
<data name="ExportHDFFiltered_Description" xml:space="preserve">
<value>Controls whether export HDF filtered EU </value>
</data>
<data name="ExportHDFFiltered_DisplayName" xml:space="preserve">
<value>HDF EU フィルタ有り </value>
</data>
<data name="ExportHDFMV_Description" xml:space="preserve">
<value>Controls whether export HDF mV data is enabled by default for new test setups</value>
</data>
<data name="ExportHDFMV_DisplayName" xml:space="preserve">
<value>HDF mV</value>
</data>
<data name="ExportHDFUnfiltered_Description" xml:space="preserve">
<value>Controls whether export HDF unfiltered EU data is enabled by default for new test setups</value>
</data>
<data name="ExportHDFUnfiltered_DisplayName" xml:space="preserve">
<value>HDF EU フィルタ無し</value>
</data>
<data name="ExportISOFiltered_Description" xml:space="preserve">
<value>ISO形式 EU フィルタ有り のエクスポートを有効にします。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="ExportISOFiltered_DisplayName" xml:space="preserve">
<value>ISO EU フィルタ有り</value>
</data>
<data name="ExportISOUnFiltered_Description" xml:space="preserve">
<value>ISO形式 EU フィルタ無し のエクスポートを有効にします。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="ExportISOUnFiltered_DisplayName" xml:space="preserve">
<value>ISO EU フィルタ無し</value>
</data>
<data name="ExportOptions" xml:space="preserve">
<value>(7) エクスポートの設定</value>
</data>
<data name="ExportRDFADC_Description" xml:space="preserve">
<value>Controls whether export RDF ADC data is enabled by default for new test setups</value>
</data>
<data name="ExportRDFADC_DisplayName" xml:space="preserve">
<value>RDF ADC</value>
</data>
<data name="ExportSomatFiltered_Description" xml:space="preserve">
<value>Controls whether export Somat filtered data is enabled by default for new test setups</value>
</data>
<data name="ExportSomatFiltered_DisplayName" xml:space="preserve">
<value>Somat filtered EU</value>
</data>
<data name="ExportSomatUnfiltered_Description" xml:space="preserve">
<value>Controls whether export Somat unfiltered data is enabled by default for new test setups</value>
</data>
<data name="ExportSomatUnfiltered_DisplayName" xml:space="preserve">
<value>Somat EU フィルタ無し</value>
</data>
<data name="ExportTDASADC_Description" xml:space="preserve">
<value>Controls whether export TDAS ADCdata is enabled by default for new test setups</value>
</data>
<data name="ExportTDASADC_DisplayName" xml:space="preserve">
<value>TDAS ADC</value>
</data>
<data name="ExportTDMSADC_Description" xml:space="preserve">
<value>Controls whether export TDMS ADC data is enabled by default for new test setups</value>
</data>
<data name="ExportTDMSADC_DisplayName" xml:space="preserve">
<value>TDMS ADC</value>
</data>
<data name="ExportToyotaFiltered_Description" xml:space="preserve">
<value>Controls whether export TTS EU filtered EU data is enabled by default for new test setups</value>
</data>
<data name="ExportToyotaFiltered_DisplayName" xml:space="preserve">
<value>TTS EU フィルタ無し</value>
</data>
<data name="ExportToyotaUnfiltered_Description" xml:space="preserve">
<value>Controls whether export TTS unfiltered EU data is enabled by default for new test setups</value>
</data>
<data name="ExportToyotaUnfiltered_DisplayName" xml:space="preserve">
<value>(この項目は使用しません)</value>
</data>
<data name="ExportTSVFiltered_Description" xml:space="preserve">
<value>Controls whether export TSV filtered EU data is enabled by default for new test setups</value>
</data>
<data name="ExportTSVFiltered_DisplayName" xml:space="preserve">
<value>TSV EU フィルタ有り</value>
</data>
<data name="ExportTSVUnfiltered_Description" xml:space="preserve">
<value>Controls whether export TSV unfiltered EU data is enabled by default for new test setups</value>
</data>
<data name="ExportTSVUnfiltered_DisplayName" xml:space="preserve">
<value>TSV EU フィルタ無し</value>
</data>
<data name="ExportXLSXFiltered_Description" xml:space="preserve">
<value>Microsoft Excel (XLSX) EU フィルタ有り のエクスポートを有効にします。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="ExportXLSXFiltered_DisplayName" xml:space="preserve">
<value>XLSX EU フィルタ有り</value>
</data>
<data name="ExportXLSXUnfiltered_Description" xml:space="preserve">
<value>Microsoft Excel (XLSX) EU フィルタ無し のエクスポートを有効にします。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="ExportXLSXUnfiltered_DisplayName" xml:space="preserve">
<value>XLSX EU フィルタ無し</value>
</data>
<data name="RealtimeOptions" xml:space="preserve">
<value>(3) リアルタイム設定</value>
</data>
<data name="RecordingOptions" xml:space="preserve">
<value>(5) 記録設定</value>
</data>
<data name="SuppressViewAllRealtime_Description" xml:space="preserve">
<value>リアルタイムモードを終了する時の警告の有無、新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="SuppressViewAllRealtime_DisplayName" xml:space="preserve">
<value>リアルタイムモードを終了する時に警告を表示しない</value>
</data>
<data name="SupressQuitTestWarning_Description" xml:space="preserve">
<value>試験を中断する時の警告の有無、新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="SupressQuitTestWarning_DisplayName" xml:space="preserve">
<value>試験を中断する時に警告を表示しない</value>
</data>
<data name="SupressViewAllViewer_Description" xml:space="preserve">
<value>データ表示を終了する時の警告の有無、新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="SupressViewAllViewer_DisplayName" xml:space="preserve">
<value>データ表示を終了する時に警告を表示しない</value>
</data>
<data name="TestInfo" xml:space="preserve">
<value>(1) 試験情報</value>
</data>
<data name="UploadOptions" xml:space="preserve">
<value>(8) アップロードの設定</value>
</data>
<data name="ExportDiademADC_Description" xml:space="preserve">
<value>Controls whether export ADC is enabled by default for new test setups</value>
</data>
<data name="ExportDiademADC_DisplayName" xml:space="preserve">
<value>DIAdem ADC</value>
</data>
<data name="DefaultTestExcitationWarmupSeconds_Description" xml:space="preserve">
<value>センサウォームアップ時間の設定。新規テストセトアップにおけるデフォルト値を設定します。</value>
</data>
<data name="DefaultTestExcitationWarmupSeconds_DisplayName" xml:space="preserve">
<value>センサーウォーム アップ(秒) &lt; suggested</value>
</data>
<data name="DefaultCheckListTemperatureCheck_Description" xml:space="preserve">
<value>アーム直前診断で温度のチェックをするかどうか。新規テストセトアップにおけるデフォルト値を設定します</value>
</data>
<data name="DefaultCheckListTemperatureCheck_DisplayName" xml:space="preserve">
<value>温度のチェック</value>
</data>
<data name="DefaultUploadExportsOnly_Description" xml:space="preserve">
<value>アップロードの時、すべてのテストファイルをアップロードするかエクスポートされたファイルのみアップロードするかを設定します。</value>
</data>
<data name="DefaultUploadExportsOnly_DisplayName" xml:space="preserve">
<value>エクスポートファイルのみアップロードする</value>
</data>
</root>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,182 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using DTS.Common.Storage;
// ReSharper disable RedundantEmptyDefaultSwitchBranch
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users.UserSettings
{
/// <summary>
/// user specific properties, stored in db
///
/// these are all the user specific settings we are storing in the db currently as generic settings
/// we have a few user specific settings like last used hardware that are stored in other places, that maybe
/// should be stored here as well
///
/// it's possible to retrieve all the settings at once (more efficient, only one db query), or retrieve settings individually
/// one by one using the static accessors
/// each setting has a default specified both in code and in the db.
/// when retrieving a setting we fall back to the default if a user specific value is not found
/// if the default setting in the db is not found, we can further fall back to the default specified in code
///
/// in the db we have a table that lists all the settings with their fall back default value
/// we have a separate table that stores the user specific values for any of those settings, which may or may not match the fall
/// back default value
///
/// the data should always be stored in invariant form in the db
/// DisplayName, Description attributes translate so the properties can be displayed in a property grid
/// </summary>
public class UserHistory
{
#region properties
[CategoryAttributeEx(PropertyEnums.PropertyCategories.UserHistory)]
[PropertyId(PropertyEnums.PropertyIds.UsersCurrentTestSetup)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.UsersCurrentTestSetup)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.UsersCurrentTestSetup)]
[DefaultValue("")]
[ReadOnly(true)]
public string UsersCurrentTestSetup { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.UserHistory)]
[PropertyId(PropertyEnums.PropertyIds.LastRunTestSetup)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.LastRunTestSetup)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.LastRunTestSetup)]
[DefaultValue("")]
[ReadOnly(true)]
public string LastRunTestSetup { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.UserHistory)]
[PropertyId(PropertyEnums.PropertyIds.LastUsedSampleRate)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.LastUsedSampleRate)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.LastUsedSampleRate)]
[DefaultValue(20000D)]
[ReadOnly(true)]
public double LastUsedSampleRate { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.UserHistory)]
[PropertyId(PropertyEnums.PropertyIds.ApplySensorDataToBlankChannels)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.ApplySensorDataToBlankChannels)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.ApplySensorDataToBlankChannels)]
[DefaultValue(true)]
[ReadOnly(true)]
public bool ApplySensorDataToBlankChannels { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.UserHistory)]
[PropertyId(PropertyEnums.PropertyIds.ApplyHardwareAssignmentInHardwareDisco)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.ApplyHardwareAssignmentInHardwareDisco)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.ApplyHardwareAssignmentInHardwareDisco)]
[DefaultValue(true)]
[ReadOnly(true)]
[Browsable(false)]
public bool ApplyHardwareAssignmentInHardwareDisco { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.UserHistory)]
[PropertyId(PropertyEnums.PropertyIds.ShowOptionsWhenApplyingSensorToBlankChannel)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.ShowOptionsWhenApplyingSensorToBlankChannel)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.ShowOptionsWhenApplyingSensorToBlankChannel)]
[DefaultValue(true)]
[ReadOnly(true)]
public bool ShowOptionsWhenApplyingSensorToBlankChannel { get; set; }
#endregion properties
#region Static Methods
/// <summary>
/// this function is designed to create any missing property settings if needed
/// this might happen if the database table was just created for instance
/// it will create defaults for all the settings in the db, and also settings for all users
/// currently it's used by DataPRO.App
/// </summary>
public static void CreateAnyMissingUserHistory()
{
//get a list of all known properties
var userHistory = new UserHistory();
var properties = userHistory.GetType().GetProperties();
var needToBeAdded = new Dictionary<int, PropertyInfo>();
foreach (var property in properties)
{
var id = PropertyIdAttribute.GetPropertyId(property);
needToBeAdded[id] = property;
}
//find if the property already exists in the db, if so, no need to add...
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
sql.CommandText = "SELECT [PropertyId] from [DefaultProperties]";
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
var id = Convert.ToInt32(row["PropertyId"]);
if (needToBeAdded.ContainsKey(id))
{
needToBeAdded.Remove(id);
}
}
}
}
finally
{
sql.Connection.Dispose();
}
}
//if we have nothing to add, we are all done
if (needToBeAdded.Values.Count <= 0) return;
//otherwise add the defaults
using (var sql = DbOperations.GetSQLCommand(true))
{
try
{
var sb = new StringBuilder();
sb.Append(DbOperations.BEGIN_STATEMENT);
using (var needToBeAddedEnumerator = needToBeAdded.GetEnumerator())
{
var iIndex = 0;
while (needToBeAddedEnumerator.MoveNext())
{
var currentProperty = needToBeAddedEnumerator.Current.Value;
sb.AppendFormat(
"INSERT INTO [DefaultProperties] ([PropertyId],[PropertyName],[DefaultValue]) VALUES (@1_{0}, @2_{0}, @3_{0});",
iIndex);
DbOperations.CreateParam(sql, string.Format("@1_{0}", iIndex), SqlDbType.Int,
PropertyIdAttribute.GetPropertyId(currentProperty));
DbOperations.CreateParam(sql, string.Format("@2_{0}", iIndex), SqlDbType.NVarChar,
PropertyIdAttribute.GetPropertyIdEnum(currentProperty).ToString());
DbOperations.CreateParam(sql, string.Format("@3_{0}", iIndex), SqlDbType.NVarChar,
TestSetupDefaults.GetDefaultValueAsString(currentProperty));
iIndex++;
}
}
sb.Append(DbOperations.COMMIT_STATEMENT);
sql.CommandText = sb.ToString();
DbOperations.Connection.ExecuteCommand(sql);
}
finally
{
sql.Connection.Dispose();
}
}
//finally add settings for any users we have currently
TestSetupDefaults.CreateMissingUserSettingProperties(needToBeAdded.Values.ToArray());
}
#endregion
#region methods
#endregion
}
}

View File

@@ -0,0 +1,741 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using DTS.Storage;
// ReSharper disable RedundantEmptyDefaultSwitchBranch
// ReSharper disable once CheckNamespace
namespace DTS.Slice.Users.UserSettings
{
/// <summary>
/// user specific properties, stored in db
///
/// these are all the user specific settings we are storing in the db currently as generic settings
/// we have a few user specific settings like last used hardware that are stored in other places, that maybe
/// should be stored here as well
///
/// it's possible to retrieve all the settings at once (more efficient, only one db query), or retrieve settings individually
/// one by one using the static accessors
/// each setting has a default specified both in code and in the db.
/// when retrieving a setting we fall back to the default if a user specific value is not found
/// if the default setting in the db is not found, we can further fall back to the default specified in code
///
/// in the db we have a table that lists all the settings with their fall back default value
/// we have a separate table that stores the user specific values for any of those settings, which may or may not match the fall
/// back default value
///
/// the data should always be stored in invariant form in the db
/// DisplayName, Description attributes translate so the properties can be displayed in a property grid
/// </summary>
public class UserSettings
{
#region properties
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultUploadEnabled)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultUploadEnabled)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultUploadEnabled)]
[DefaultValue(false)]
public bool UploadDefault { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultTestSampleRate)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultTestSampleRate)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultTestSampleRate)]
[DefaultValue(10000D)]
public double DefaultSampleRate { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultPostTriggerSeconds)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultPostTriggerSeconds)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultPostTriggerSeconds)]
[DefaultValue(1D)]
public double DefaultPostTriggerSeconds { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultPreTriggerSeconds)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultPreTriggerSeconds)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultPreTriggerSeconds)]
[DefaultValue(1D)]
public double DefaultPreTriggerSeconds { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultTriggerCheckStep)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultTriggerCheckStep)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultTriggerCheckStep)]
[DefaultValue(true)]
public bool DefaultTriggerCheckStep { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultRealtimeGraphCount)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultRealtimeGraphCount)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultRealtimeGraphCount)]
[DefaultValue(6)]
public int DefaultRealtimeGraphCount { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultROIStart)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultROIStart)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultROIStart)]
[DefaultValue(-1D)]
public double DefaultROIStart { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultROIEnd)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultROIEnd)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultROIEnd)]
[DefaultValue(1D)]
public double DefaultROIEnd { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultDownloadROI)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultDownloadROI)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultDownloadROI)]
[DefaultValue(true)]
public bool DefaultDownloadROI { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultViewROI)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultViewROI)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultViewROI)]
[DefaultValue(true)]
public bool DefaultViewROI { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultDownloadAll)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultDownloadAll)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultDownloadAll)]
[DefaultValue(true)]
public bool DefaultDownloadAll { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultViewAll)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultViewAll)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultViewAll)]
[DefaultValue(false)]
public bool DefaultViewAll { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultRequireAllUnitsPassDiagnostics)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultRequireAllUnitsPassDiagnostics)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultRequireAllUnitsPassDiagnostics)]
[DefaultValue(true)]
public bool DefaultRequireAllUnitsPassDiagnostics { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultRequireUserConfirmationOnErrors)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultRequireUserConfirmationOnErrors)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultRequireUserConfirmationOnErrors)]
[DefaultValue(true)]
public bool DefaultRequireUserConfirmationOnErrors { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultAllowMissingSensors)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultAllowMissingSensors)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultAllowMissingSensors)]
[DefaultValue(false)]
public bool DefaultAllowMissingSensors { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultRunPostTestDiagnostics)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultRunPostTestDiagnostics)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultRunPostTestDiagnostics)]
[DefaultValue(false)]
public bool DefaultRunPostTestDiagnostics { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultArmCheckListStep)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultArmCheckListStep)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultArmCheckListStep)]
[DefaultValue(false)]
public bool DefaultArmCheckListStep { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultCheckListInputVoltageCheck)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListInputVoltageCheck)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListInputVoltageCheck)]
[DefaultValue(true)]
public bool DefaultCheckListInputVoltageCheck { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultCheckListBatteryVoltageCheck)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListBatteryVoltageCheck)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListBatteryVoltageCheck)]
[DefaultValue(true)]
public bool DefaultCheckListBatteryVoltageCheck { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultCheckListSquibResistanceCheck)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListSquibResistanceCheck)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListSquibResistanceCheck)]
[DefaultValue(true)]
public bool DefaultCheckListSquibResistanceCheck { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultCheckListSensorIdCheck)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListSensorIdCheck)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListSensorIdCheck)]
[DefaultValue(true)]
public bool DefaultCheckListSensorIdCheck { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultCheckListTriggerStartCheck)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListTriggerStartCheck)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListTriggerStartCheck)]
[DefaultValue(true)]
public bool DefaultCheckListTriggerStartCheck { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultCheckListTiltSensorCheck)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListTiltSensorCheck)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListTiltSensorCheck)]
[DefaultValue(true)]
public bool DefaultCheckListTiltSensorCheck { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultAllowSensorIdToBlankChannel)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultAllowSensorIdToBlankChannel)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultAllowSensorIdToBlankChannel)]
[DefaultValue(true)]
public bool DefaultAllowSensorIdToBlankChannel { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultCheckListMustPass)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListMustPass)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultCheckListMustPass)]
[DefaultValue(false)]
public bool DefaultChecklistMustPass { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[PropertyId(PropertyEnums.PropertyIds.DefaultViewRealtime)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultViewRealtime)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultViewRealtime)]
[DefaultValue(true)]
public bool DefaultViewRealtime { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultExport)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultExport)]
[PropertyId(PropertyEnums.PropertyIds.DefaultExport)]
[DefaultValue(false)]
public bool DefaultExport { get; set; }
[DefaultValue(0)]
[CategoryAttributeEx(PropertyEnums.PropertyCategories.DefaultTestSettings)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultExportFormat)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultExportFormat)]
[PropertyId(PropertyEnums.PropertyIds.DefaultExportFormat)]
public int DefaultExportFormat { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.RealtimeSettings)]
[PropertyId(PropertyEnums.PropertyIds.RealtimeChartWidthInSeconds)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.RealtimeChartWidthInSeconds)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.RealtimeChartWidthInSeconds)]
[DefaultValue(2)]
public double RealtimeChartWidthInSeconds { get; set; }
[DefaultValue(true)]
[CategoryAttributeEx(PropertyEnums.PropertyCategories.TestOptions)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultTreeModeDiagnostics)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultTreeModeDiagnostics)]
[PropertyId(PropertyEnums.PropertyIds.DefaultTreeModeDiagnostics)]
public bool DefaultTreeModeDiagnostics { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.TestOptions)]
[PropertyId(PropertyEnums.PropertyIds.ArmChecklistRequiredIfTOM)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.ArmChecklistRequiredIfTOM)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.ArmChecklistRequiredIfTOM)]
[DefaultValue(true)]
public bool ArmChecklistRequiredIfTOM { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.TestOptions)]
[PropertyId(PropertyEnums.PropertyIds.DefaultSuppressMissingSensorsWarning)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.DefaultSuppressMissingSensorsWarning)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.DefaultSuppressMissingSensorsWarning)]
[DefaultValue(true)]
public bool DefaultSuppressMissingSensorsWarning { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.TestOptions)]
[PropertyId(PropertyEnums.PropertyIds.ArmTriggerDiagnosticsRunOnNextStep)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.ArmTriggerDiagnosticsRunOnNextStep)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.ArmTriggerDiagnosticsRunOnNextStep)]
[DefaultValue(false)]
public bool ArmTriggerDiagnosticsRunOnNextStep { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.UserHistory)]
[PropertyId(PropertyEnums.PropertyIds.UsersCurrentTestSetup)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.UsersCurrentTestSetup)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.UsersCurrentTestSetup)]
[DefaultValue("")]
[ReadOnly(true)]
public string UsersCurrentTestSetup { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.UserHistory)]
[PropertyId(PropertyEnums.PropertyIds.LastRunTestSetup)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.LastRunTestSetup)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.LastRunTestSetup)]
[DefaultValue("")]
[ReadOnly(true)]
public string LastRunTestSetup { get; set; }
[CategoryAttributeEx(PropertyEnums.PropertyCategories.UserHistory)]
[PropertyId(PropertyEnums.PropertyIds.LastUsedSampleRate)]
[DescriptionAttributeEx(PropertyEnums.PropertyIds.LastUsedSampleRate)]
[DisplayAttributeEx(PropertyEnums.PropertyIds.LastUsedSampleRate)]
[DefaultValue(20000D)]
[ReadOnly(true)]
public double LastUsedSampleRate { get; set; }
/*
* Subcategory example
*/
//[Category("Category1")]
//public SubCategory1 Subcategory1 { get; set; }
//[Category("Category1")]
//public SubCategory2 Subcategory2 { get; set; }
#endregion properties
#region Static Methods
/// <summary>
/// this function is designed to create any missing property settings if needed
/// this might happen if the database table was just created for instance
/// it will create defaults for all the settings in the db, and also settings for all users
/// currently it's used by DataPRO.App
/// </summary>
public static void CreateAnyMissingUserSettingPropertyDefaults()
{
//get a list of all known properties
var userSetting = new UserSettings();
var properties = userSetting.GetType().GetProperties();
var needToBeAdded = new Dictionary<int, PropertyInfo>();
foreach (var property in properties)
{
var id = PropertyIdAttribute.GetPropertyId(property);
needToBeAdded[id] = property;
}
//find if the property already exists in the db, if so, no need to add...
using (var sql = DbOperations.GetCommand())
{
sql.CommandText = "SELECT [PropertyId] from [DefaultProperties]";
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
var id = Convert.ToInt32(row["PropertyId"]);
if (needToBeAdded.ContainsKey(id))
{
needToBeAdded.Remove(id);
}
}
}
}
//if we have nothing to add, we are all done
if (needToBeAdded.Values.Count <= 0) return;
//otherwise add the defaults
using (var sql = DbOperations.GetCommand())
{
var sb = new StringBuilder();
sb.Append(DbOperations.BEGIN_STATEMENT);
var needToBeAddedEnumerator = needToBeAdded.GetEnumerator();
int iIndex = 0;
while (needToBeAddedEnumerator.MoveNext())
{
var currentProperty = needToBeAddedEnumerator.Current.Value;
sb.AppendFormat("INSERT INTO [DefaultProperties] ([PropertyId],[PropertyName],[DefaultValue]) VALUES (@1_{0}, @2_{0}, @3_{0});", iIndex);
DbOperations.CreateParam(sql, string.Format("@1_{0}", iIndex), SqlDbType.Int, PropertyIdAttribute.GetPropertyId(currentProperty));
DbOperations.CreateParam(sql, string.Format("@2_{0}", iIndex), SqlDbType.NVarChar, PropertyIdAttribute.GetPropertyIdEnum(currentProperty).ToString());
DbOperations.CreateParam(sql, string.Format("@3_{0}", iIndex), SqlDbType.NVarChar, GetDefaultValueAsString(currentProperty));
iIndex++;
}
sb.Append(DbOperations.COMMIT_STATEMENT);
sql.CommandText = sb.ToString();
DbOperations.Connection.ExecuteCommand(sql);
}
//finally add settings for any users we have currently
CreateMissingUserSettingProperties(needToBeAdded.Values.ToArray());
}
/// <summary>
/// creates missing user settings (for all users)
/// </summary>
/// <param name="needToBeAdded"></param>
private static void CreateMissingUserSettingProperties(PropertyInfo[] needToBeAdded)
{
var userIds = new List<int>();
using (var sql = DbOperations.GetCommand())
{
sql.CommandText = "SELECT ID FROM [DataPROUsers]";
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
var id = Convert.ToInt32(row["ID"]);
if (!userIds.Contains(id))
{
userIds.Add(id);
}
}
}
}
foreach (var id in userIds)
{
CreateMissingUserSettingProperties(id, needToBeAdded);
}
}
/// <summary>
/// this funtion creates a list of settings for a specific user
/// this may happen with a new database, it's called by the
/// CreateAnyMissingUserSettingPropertyDefaults function above
/// </summary>
/// <param name="id"></param>
/// <param name="needToBeAdded"></param>
internal static void CreateMissingUserSettingProperties(int id, PropertyInfo[] needToBeAdded)
{
using (var sql = DbOperations.GetCommand())
{
var index = 0;
var sb = new StringBuilder();
sb.Append(DbOperations.BEGIN_STATEMENT);
foreach (var property in needToBeAdded)
{
sb.AppendFormat(
"INSERT INTO [UserProperties] ([UserId],[PropertyId], [PropertyValue]) VALUES (@1_{0},@2_{0},@3_{0});",
index);
DbOperations.CreateParam(sql, string.Format("@1_{0}", index), SqlDbType.Int, id);
DbOperations.CreateParam(sql, string.Format("@2_{0}", index), SqlDbType.Int,
PropertyIdAttribute.GetPropertyId(property));
DbOperations.CreateParam(sql, string.Format("@3_{0}", index), SqlDbType.NVarChar,
GetDefaultValueAsString(property));
index++;
}
sb.Append(DbOperations.COMMIT_STATEMENT);
sql.CommandText = sb.ToString();
DbOperations.Connection.ExecuteCommand(sql);
}
}
/// <summary>
/// get an invariant version of the value for db storage
/// this is used when we create or insert a new default into the db
/// </summary>
/// <param name="property"></param>
/// <returns></returns>
private static string GetDefaultValueAsString(PropertyInfo property)
{
if (property == null) return "";
var attr = (DefaultValueAttribute)property.GetCustomAttribute(typeof(DefaultValueAttribute));
if (attr.Value is double)
{
return ((double) attr.Value).ToString(CultureInfo.InvariantCulture);
}
if (attr.Value is float)
{
return ((float) attr.Value).ToString(CultureInfo.InvariantCulture);
}
return attr.Value.ToString();
}
/// <summary>
/// gets a collection of all settings for a given user
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public static UserSettings GetUserSettings(int userId)
{
var settings = new UserSettings();
var properties = settings.GetType().GetProperties();
//first get all properties as filled out by code
foreach (var property in properties)
{
var d = property.GetCustomAttribute<DefaultValueAttribute>();
if (d != null)
{
property.SetValue(settings, d.Value);
}
}
//next make sure we get all the defaults from the db
using (var sql = DbOperations.GetCommand())
{
sql.CommandText = "SELECT [PropertyId], [DefaultValue] from [DefaultProperties]";
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
var id = Convert.ToInt32(row["PropertyId"]);
var dv = Convert.ToString(row["DefaultValue"]);
settings.SetValue(id, dv);
}
}
}
//finally get the user specific values
using (var sql = DbOperations.GetCommand())
{
sql.CommandText = "SELECT [PropertyId], [PropertyValue] FROM [UserProperties] WHERE [UserId]=@1";
DbOperations.CreateParam(sql, "@1", SqlDbType.Int, userId);
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
foreach (DataRow row in ds.Tables[0].Rows)
{
var id = Convert.ToInt32(row["PropertyId"]);
var value = Convert.ToString(row["PropertyValue"]);
settings.SetValue(id, value);
}
}
}
return settings;
}
/// <summary>
/// sets a specific user setting in the db
/// function should handle the invariant nature of values
/// </summary>
/// <param name="userId"></param>
/// <param name="id"></param>
/// <param name="value"></param>
public static void SetUserSetting(int userId, PropertyEnums.PropertyIds id, object value)
{
var sValue = value.ToString();
if (value is double)
{
sValue = ((double)value).ToString(CultureInfo.InvariantCulture);
}
else if (value is float)
{
sValue = ((float)value).ToString(CultureInfo.InvariantCulture);
}
using (var sql = DbOperations.GetCommand())
{
sql.CommandText = "UPDATE [UserProperties] SET [PropertyValue]=@1 WHERE [UserId]=@2 AND [PropertyId]=@3";
DbOperations.CreateParam(sql, "@1", SqlDbType.NVarChar, sValue);
DbOperations.CreateParam(sql, "@2", SqlDbType.Int, userId);
DbOperations.CreateParam(sql, "@3", SqlDbType.Int, (int)id);
DbOperations.Connection.ExecuteCommand(sql);
}
}
/// <summary>
/// gets a specific user setting as a bool
/// </summary>
/// <param name="userId"></param>
/// <param name="property"></param>
/// <returns></returns>
public static bool GetUserSettingValueBool(int userId, PropertyEnums.PropertyIds property)
{
return Convert.ToBoolean(GetUserSettingValue(userId, property));
}
/// <summary>
/// gets a specific user setting as a double
/// </summary>
/// <param name="userId"></param>
/// <param name="property"></param>
/// <returns></returns>
public static double GetUserSettingValueDouble(int userId, PropertyEnums.PropertyIds property)
{
return Convert.ToDouble(GetUserSettingValue(userId, property), CultureInfo.InvariantCulture);
}
/// <summary>
/// gets a specific user setting as an integer
/// </summary>
/// <param name="userId"></param>
/// <param name="property"></param>
/// <returns></returns>
public static int GetUserSettingValueInt(int userId, PropertyEnums.PropertyIds property)
{
return Convert.ToInt32(GetUserSettingValue(userId, property), CultureInfo.InvariantCulture);
}
/// <summary>
/// Gets a specific user setting as a string
/// </summary>
/// <param name="userid"></param>
/// <param name="property"></param>
/// <returns></returns>
public static string GetUserSettingValueString(int userid, PropertyEnums.PropertyIds property)
{
return GetUserSettingValue(userid, property);
}
/// <summary>
/// gets a user setting out of the db, this is an internal function used by all the public
/// single setting accessors.
/// setting is determined by user settings table, default values table
/// </summary>
/// <param name="userid"></param>
/// <param name="property"></param>
/// <returns></returns>
private static string GetUserSettingValue(int userid, PropertyEnums.PropertyIds property)
{
//if the user has a specific value set for this property, just return it directly
using (var sql = DbOperations.GetCommand())
{
sql.CommandText = "SELECT [PropertyValue] FROM [UserProperties] WHERE [UserId]=@1 AND [PropertyId]=@2";
DbOperations.CreateParam(sql, "@1", SqlDbType.Int, userid);
DbOperations.CreateParam(sql, "@2", SqlDbType.Int, (int)property);
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
if (ds.Tables[0].Rows.Count > 0)
{
return Convert.ToString(ds.Tables[0].Rows[0]["PropertyValue"]);
}
}
}
//if there exists a specific default value set for this property, return that
using (var sql = DbOperations.GetCommand())
{
sql.CommandText = "SELECT [DefaultValue] FROM [DefaultProperties] WHERE [PropertyId] =@1";
DbOperations.CreateParam(sql, "@1", SqlDbType.Int, (int)property);
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
if (ds.Tables[0].Rows.Count > 0)
{
return Convert.ToString(ds.Tables[0].Rows[0]["DefaultValue"]);
}
}
}
//we could return the default value in code here, but we don't expect to get here, so
//we can treat this as an exception for now
throw new NullReferenceException(property.ToString());
}
#endregion
#region methods
/// <summary>
/// sets a specific value given a property id
/// this is used when deserializing values out of the db
///
/// </summary>
/// <param name="id"></param>
/// <param name="dv"></param>
protected void SetValue(int id, string dv)
{
var property = (PropertyEnums.PropertyIds)id;
switch (property)
{
case PropertyEnums.PropertyIds.ArmChecklistRequiredIfTOM: ArmChecklistRequiredIfTOM = Convert.ToBoolean(dv); break;
case PropertyEnums.PropertyIds.ArmTriggerDiagnosticsRunOnNextStep: ArmTriggerDiagnosticsRunOnNextStep = Convert.ToBoolean(dv); break;
case PropertyEnums.PropertyIds.DefaultAllowMissingSensors: DefaultAllowMissingSensors = Convert.ToBoolean(dv); break;
case PropertyEnums.PropertyIds.DefaultAllowSensorIdToBlankChannel: DefaultAllowSensorIdToBlankChannel = Convert.ToBoolean(dv); break;
case PropertyEnums.PropertyIds.DefaultArmCheckListStep: DefaultArmCheckListStep = Convert.ToBoolean(dv); break;
case PropertyEnums.PropertyIds.DefaultCheckListBatteryVoltageCheck: DefaultCheckListBatteryVoltageCheck = Convert.ToBoolean(dv); break;
case PropertyEnums.PropertyIds.DefaultUploadEnabled: UploadDefault = Convert.ToBoolean(dv); break;
case PropertyEnums.PropertyIds.DefaultTestSampleRate: DefaultSampleRate = Convert.ToDouble(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultPostTriggerSeconds: DefaultPostTriggerSeconds = Convert.ToDouble(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultPreTriggerSeconds: DefaultPreTriggerSeconds = Convert.ToDouble(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultTriggerCheckStep: DefaultTriggerCheckStep = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultRealtimeGraphCount: DefaultRealtimeGraphCount = Convert.ToInt32(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultROIStart: DefaultROIStart = Convert.ToDouble(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultROIEnd: DefaultROIEnd = Convert.ToDouble(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultDownloadROI: DefaultDownloadROI = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultViewROI: DefaultViewROI = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultDownloadAll: DefaultDownloadAll = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultViewAll: DefaultViewAll = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultRequireAllUnitsPassDiagnostics: DefaultRequireAllUnitsPassDiagnostics = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultRequireUserConfirmationOnErrors: DefaultRequireUserConfirmationOnErrors = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultRunPostTestDiagnostics: DefaultRunPostTestDiagnostics = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultCheckListInputVoltageCheck: DefaultCheckListInputVoltageCheck = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultCheckListSquibResistanceCheck: DefaultCheckListSquibResistanceCheck = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultCheckListSensorIdCheck: DefaultCheckListSensorIdCheck = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultCheckListTriggerStartCheck: DefaultCheckListTriggerStartCheck = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultCheckListTiltSensorCheck: DefaultCheckListTiltSensorCheck = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultCheckListMustPass: DefaultChecklistMustPass = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultViewRealtime: DefaultViewRealtime = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultExport: DefaultExport = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultExportFormat: DefaultExportFormat = Convert.ToInt32(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.RealtimeChartWidthInSeconds: RealtimeChartWidthInSeconds = Convert.ToDouble(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultTreeModeDiagnostics: DefaultTreeModeDiagnostics = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.DefaultSuppressMissingSensorsWarning: DefaultSuppressMissingSensorsWarning = Convert.ToBoolean(dv, CultureInfo.InvariantCulture); break;
case PropertyEnums.PropertyIds.UsersCurrentTestSetup: UsersCurrentTestSetup = dv; break;
case PropertyEnums.PropertyIds.LastRunTestSetup: LastRunTestSetup = dv; break;
case PropertyEnums.PropertyIds.LastUsedSampleRate: LastUsedSampleRate = Convert.ToDouble(dv, CultureInfo.InvariantCulture); break;
default:
break;//ignore unknown property, just just ignore it
}
}
/// <summary>
/// resets all the settings for a user in the db, using the default settings in the db
/// </summary>
/// <param name="userId"></param>
public void ResetUserSettings(int userId)
{
//you can do this with one command with SQL, ie like
//http://stackoverflow.com/questions/224732/sql-update-from-one-table-to-another-based-on-a-id-match
//but since we haven't ditched SQlite yet, lets include support for both by separating it into two statements
var properties = new List<Tuple<int, string>>();
using (var sql = DbOperations.GetCommand())
{
sql.CommandText = "SELECT [PropertyId],[DefaultValue] from [DefaultProperties]";
using (var ds = DbOperations.Connection.QueryDataSet(sql))
{
properties.AddRange(from DataRow row in ds.Tables[0].Rows let id = Convert.ToInt32(row["PropertyId"]) let value = Convert.ToString(row["DefaultValue"]) select new Tuple<int, string>(id, value));
}
}
using (var sql = DbOperations.GetCommand())
{
var sb = new StringBuilder();
sb.Append(DbOperations.BEGIN_STATEMENT);
for (var i = 0; i < properties.Count; i ++)
{
sb.AppendFormat("UPDATE [UserProperties] SET [PropertyValue]=@1_{0} WHERE [PropertyId]=@2_{0} AND [UserId]=@3_{0};",i);
DbOperations.CreateParam(sql, string.Format("@1_{0}", i), SqlDbType.NVarChar, properties[i].Item2);
DbOperations.CreateParam(sql, string.Format("@2_{0}", i), SqlDbType.Int, properties[i].Item1);
DbOperations.CreateParam(sql, string.Format("@3_{0}",i), SqlDbType.Int, userId);
}
sb.Append(DbOperations.COMMIT_STATEMENT);
sql.CommandText = sb.ToString();
DbOperations.Connection.ExecuteCommand(sql);
}
}
#endregion
}
/// <summary>
/// Subcategory example
/// http://stackoverflow.com/questions/9379353/category-hierarchy-in-winforms-propertygrid
/// </summary>
[TypeConverter(typeof(ExpandableObjectConverter))]
public class SubCategory1
{
public String Property1 { get; set; }
public String Property2 { get; set; }
public override string ToString()
{
return String.Empty;
}
}
[TypeConverter(typeof(ExpandableObjectConverter))]
public class SubCategory2
{
public String Property3 { get; set; }
public override string ToString()
{
return String.Empty;
}
}
}

157
DataPRO/Users/Users.csproj Normal file
View File

@@ -0,0 +1,157 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{BE8D217D-6DA9-4BCA-B62A-A82325B33979}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Users</RootNamespace>
<AssemblyName>Users</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>3.5</OldToolsVersion>
<TargetFrameworkProfile />
<SccProjectName>
</SccProjectName>
<SccLocalPath>
</SccLocalPath>
<SccAuxPath>
</SccAuxPath>
<SccProvider>
</SccProvider>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Xceed.Wpf.Toolkit, Version=3.8.19076.18510, Culture=neutral, PublicKeyToken=ba83ff368b7563c6, processorArchitecture=MSIL">
<HintPath>..\..\Common\DTS.Common\lib\Xceed.Wpf.Toolkit\Xceed.Wpf.Toolkit.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ChallengeDialog.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ChallengeDialog.designer.cs">
<DependentUpon>ChallengeDialog.cs</DependentUpon>
</Compile>
<Compile Include="IUIItems.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UIItemHelper.cs" />
<Compile Include="User.cs" />
<Compile Include="UserCollection.cs" />
<Compile Include="UserSettings\Defaults.cs" />
<Compile Include="UserSettings\OptimizationSettings.cs" />
<Compile Include="UserSettings\PropertyIdAttribute.cs" />
<Compile Include="UserSettings\DescriptionAttributeEx.cs" />
<Compile Include="UserSettings\DisplayAttributeEx.cs" />
<Compile Include="UserSettings\CategoryAttributeEx.cs" />
<Compile Include="UserSettings\PropertyEnums.cs" />
<Compile Include="UserSettings\SampleRateConverter.cs" />
<Compile Include="UserSettings\StringResources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>StringResources.resx</DependentUpon>
</Compile>
<Compile Include="UserSettings\UserHistory.cs" />
<Compile Include="UserSettings\TestSetupDefaults.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="ChallengeDialog.resx">
<DependentUpon>ChallengeDialog.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="UserSettings\StringResources.ja.resx" />
<EmbeddedResource Include="UserSettings\StringResources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>StringResources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Common\DTS.Common.SettingsDB\DTS.Common.Settings.csproj">
<Project>{61017104-D8EE-41D1-B9CA-DAD863FF78B2}</Project>
<Name>DTS.Common.Settings</Name>
</ProjectReference>
<ProjectReference Include="..\..\Common\DTS.Common.Storage\DTS.Common.Storage.csproj">
<Project>{e3be457c-0ac7-4a9c-bc81-eafeb3217878}</Project>
<Name>DTS.Common.Storage</Name>
</ProjectReference>
<ProjectReference Include="..\..\Common\DTS.Common.Utilities\DTS.Common.Utilities.csproj">
<Project>{d6da1b74-c711-43c2-91b1-1908a8d04dbf}</Project>
<Name>DTS.Common.Utilities</Name>
</ProjectReference>
<ProjectReference Include="..\..\Common\DTS.Common\DTS.Common.csproj">
<Project>{f7a0804f-61a4-40ae-83d0-f1137622b592}</Project>
<Name>DTS.Common</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="Design\UsersClassDiagram.cd" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = "")]

View File

@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]