Compare commits
	
		
			3 Commits
		
	
	
		
			7b2a843664
			...
			red-hat
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 85fe0a7823 | |||
| 811f45a7df | |||
| 127634f5ab | 
| @ -105,7 +105,7 @@ dotnet_diagnostic.CS8936.severity = error # Feature 'collection expressions' is | |||||||
| dotnet_diagnostic.IDE0001.severity = warning # IDE0001: Simplify name | dotnet_diagnostic.IDE0001.severity = warning # IDE0001: Simplify name | ||||||
| dotnet_diagnostic.IDE0002.severity = warning # Simplify (member access) - System.Version.Equals("1", "2"); Version.Equals("1", "2"); | dotnet_diagnostic.IDE0002.severity = warning # Simplify (member access) - System.Version.Equals("1", "2"); Version.Equals("1", "2"); | ||||||
| dotnet_diagnostic.IDE0004.severity = warning # IDE0004: Cast is redundant. | dotnet_diagnostic.IDE0004.severity = warning # IDE0004: Cast is redundant. | ||||||
| dotnet_diagnostic.IDE0005.severity = none # Using directive is unnecessary | dotnet_diagnostic.IDE0005.severity = warning # Using directive is unnecessary | ||||||
| dotnet_diagnostic.IDE0028.severity = none # IDE0028: Collection initialization can be simplified | dotnet_diagnostic.IDE0028.severity = none # IDE0028: Collection initialization can be simplified | ||||||
| dotnet_diagnostic.IDE0031.severity = warning # Use null propagation (IDE0031) | dotnet_diagnostic.IDE0031.severity = warning # Use null propagation (IDE0031) | ||||||
| dotnet_diagnostic.IDE0047.severity = warning # IDE0047: Parentheses can be removed | dotnet_diagnostic.IDE0047.severity = warning # IDE0047: Parentheses can be removed | ||||||
| @ -115,7 +115,6 @@ dotnet_diagnostic.IDE0290.severity = none # Use primary constructor [Distance]cs | |||||||
| dotnet_diagnostic.IDE0300.severity = none # IDE0300: Collection initialization can be simplified | dotnet_diagnostic.IDE0300.severity = none # IDE0300: Collection initialization can be simplified | ||||||
| dotnet_diagnostic.IDE0301.severity = none #IDE0301: Collection initialization can be simplified | dotnet_diagnostic.IDE0301.severity = none #IDE0301: Collection initialization can be simplified | ||||||
| dotnet_diagnostic.IDE0305.severity = none # IDE0305: Collection initialization can be simplified | dotnet_diagnostic.IDE0305.severity = none # IDE0305: Collection initialization can be simplified | ||||||
| dotnet_diagnostic.MSTEST0015.severity = none # MSTEST0015: Test method {method} should not be ignored |  | ||||||
| dotnet_naming_rule.abstract_method_should_be_pascal_case.severity = warning | dotnet_naming_rule.abstract_method_should_be_pascal_case.severity = warning | ||||||
| dotnet_naming_rule.abstract_method_should_be_pascal_case.style = pascal_case | dotnet_naming_rule.abstract_method_should_be_pascal_case.style = pascal_case | ||||||
| dotnet_naming_rule.abstract_method_should_be_pascal_case.symbols = abstract_method | dotnet_naming_rule.abstract_method_should_be_pascal_case.symbols = abstract_method | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -343,6 +343,4 @@ ASALocalRun/ | |||||||
| /wwwroot/lib/* | /wwwroot/lib/* | ||||||
|  |  | ||||||
| .kanbn | .kanbn | ||||||
| Tests/.kanbn | Tests/.kanbn | ||||||
|  |  | ||||||
| secrets.json |  | ||||||
							
								
								
									
										6
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -8,7 +8,7 @@ | |||||||
|             "name": ".NET Core Launch (web) - Server", |             "name": ".NET Core Launch (web) - Server", | ||||||
|             "type": "coreclr", |             "type": "coreclr", | ||||||
|             "request": "launch", |             "request": "launch", | ||||||
|             "preLaunchTask": "Build Server", |             "preLaunchTask": "buildServer", | ||||||
|             // If you have changed target frameworks, make sure to update the program path. |             // If you have changed target frameworks, make sure to update the program path. | ||||||
|             "program": "${workspaceFolder}/Server/bin/Debug/net8.0/win-x64/OI.Metrology.Server.dll", |             "program": "${workspaceFolder}/Server/bin/Debug/net8.0/win-x64/OI.Metrology.Server.dll", | ||||||
|             "args": [], |             "args": [], | ||||||
| @ -31,7 +31,7 @@ | |||||||
|             "name": ".NET Core Attach - Server", |             "name": ".NET Core Attach - Server", | ||||||
|             "type": "coreclr", |             "type": "coreclr", | ||||||
|             "request": "attach", |             "request": "attach", | ||||||
|             "preLaunchTask": "Watch Server", |             "preLaunchTask": "watchServer", | ||||||
|             "processName": "OI.Metrology.Server.exe" |             "processName": "OI.Metrology.Server.exe" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
| @ -41,7 +41,7 @@ | |||||||
|             "name": ".NET Core Launch (web) - ClientHub", |             "name": ".NET Core Launch (web) - ClientHub", | ||||||
|             "type": "coreclr", |             "type": "coreclr", | ||||||
|             "request": "launch", |             "request": "launch", | ||||||
|             "preLaunchTask": "Build Client Hub", |             "preLaunchTask": "buildClientHub", | ||||||
|             // If you have changed target frameworks, make sure to update the program path. |             // If you have changed target frameworks, make sure to update the program path. | ||||||
|             "program": "${workspaceFolder}/ClientHub/bin/Debug/net7.0/win-x64/OI.Metrology.ClientHub.dll", |             "program": "${workspaceFolder}/ClientHub/bin/Debug/net7.0/win-x64/OI.Metrology.ClientHub.dll", | ||||||
|             "args": [], |             "args": [], | ||||||
|  | |||||||
							
								
								
									
										72
									
								
								.vscode/tasks.json
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -28,60 +28,72 @@ | |||||||
|             "problemMatcher": "$msCompile" |             "problemMatcher": "$msCompile" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "label": "Build Server", |             "label": "buildServer", | ||||||
|             "command": "dotnet", |             "command": "dotnet", | ||||||
|             "type": "process", |             "type": "process", | ||||||
|             "args": [ |             "args": [ | ||||||
|                 "build", |                 "build", | ||||||
|                 "${workspaceFolder}/Server/OI.Metrology.Server.csproj" |                 "${workspaceFolder}/Server/OI.Metrology.Server.csproj", | ||||||
|  |                 "/property:GenerateFullPaths=true", | ||||||
|  |                 "/consoleloggerparameters:NoSummary" | ||||||
|             ], |             ], | ||||||
|             "problemMatcher": "$msCompile" |             "problemMatcher": "$msCompile" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "label": "Build Tests", |             "label": "buildTests", | ||||||
|             "command": "dotnet", |             "command": "dotnet", | ||||||
|             "type": "process", |             "type": "process", | ||||||
|             "args": [ |             "args": [ | ||||||
|                 "build", |                 "build", | ||||||
|                 "${workspaceFolder}/Tests/OI.Metrology.Tests.csproj" |                 "${workspaceFolder}/Tests/OI.Metrology.Tests.csproj", | ||||||
|  |                 "/property:GenerateFullPaths=true", | ||||||
|  |                 "/consoleloggerparameters:NoSummary" | ||||||
|             ], |             ], | ||||||
|             "problemMatcher": "$msCompile" |             "problemMatcher": "$msCompile" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "label": "Build Shared", |             "label": "buildShared", | ||||||
|             "command": "dotnet", |             "command": "dotnet", | ||||||
|             "type": "process", |             "type": "process", | ||||||
|             "args": [ |             "args": [ | ||||||
|                 "build", |                 "build", | ||||||
|                 "${workspaceFolder}/Shared/OI.Metrology.Shared.csproj" |                 "${workspaceFolder}/Shared/OI.Metrology.Shared.csproj", | ||||||
|  |                 "/property:GenerateFullPaths=true", | ||||||
|  |                 "/consoleloggerparameters:NoSummary" | ||||||
|             ], |             ], | ||||||
|             "problemMatcher": "$msCompile" |             "problemMatcher": "$msCompile" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "label": "Publish Server", |             "label": "publishServer", | ||||||
|             "command": "dotnet", |             "command": "dotnet", | ||||||
|             "type": "process", |             "type": "process", | ||||||
|             "args": [ |             "args": [ | ||||||
|                 "publish", |                 "publish", | ||||||
|                 "${workspaceFolder}/Server/OI.Metrology.Server.csproj" |                 "${workspaceFolder}/Server/OI.Metrology.Server.csproj", | ||||||
|  |                 "/property:GenerateFullPaths=true", | ||||||
|  |                 "/consoleloggerparameters:NoSummary" | ||||||
|             ], |             ], | ||||||
|             "problemMatcher": "$msCompile" |             "problemMatcher": "$msCompile" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "label": "Test Debug", |             "label": "testDebug", | ||||||
|             "command": "dotnet", |  | ||||||
|             "type": "process", |  | ||||||
|             "args": [ |  | ||||||
|                 "test" |  | ||||||
|             ], |  | ||||||
|             "problemMatcher": "$msCompile" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "label": "Test Release", |  | ||||||
|             "command": "dotnet", |             "command": "dotnet", | ||||||
|             "type": "process", |             "type": "process", | ||||||
|             "args": [ |             "args": [ | ||||||
|                 "test", |                 "test", | ||||||
|  |                 "/property:GenerateFullPaths=true", | ||||||
|  |                 "/consoleloggerparameters:NoSummary" | ||||||
|  |             ], | ||||||
|  |             "problemMatcher": "$msCompile" | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "label": "testRelease", | ||||||
|  |             "command": "dotnet", | ||||||
|  |             "type": "process", | ||||||
|  |             "args": [ | ||||||
|  |                 "test", | ||||||
|  |                 "/property:GenerateFullPaths=true", | ||||||
|  |                 "/consoleloggerparameters:NoSummary", | ||||||
|                 "-c", |                 "-c", | ||||||
|                 "Release" |                 "Release" | ||||||
|             ], |             ], | ||||||
| @ -103,7 +115,7 @@ | |||||||
|             "problemMatcher": "$msCompile" |             "problemMatcher": "$msCompile" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "label": "Old Watch", |             "label": "old-watch", | ||||||
|             "command": "dotnet", |             "command": "dotnet", | ||||||
|             "type": "process", |             "type": "process", | ||||||
|             "args": [ |             "args": [ | ||||||
| @ -115,7 +127,7 @@ | |||||||
|             "problemMatcher": "$msCompile" |             "problemMatcher": "$msCompile" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "label": "Watch Server", |             "label": "watchServer", | ||||||
|             "command": "dotnet", |             "command": "dotnet", | ||||||
|             "type": "process", |             "type": "process", | ||||||
|             "args": [ |             "args": [ | ||||||
| @ -149,27 +161,31 @@ | |||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "label": "Build Client Hub", |             "label": "buildClientHub", | ||||||
|             "command": "dotnet", |             "command": "dotnet", | ||||||
|             "type": "process", |             "type": "process", | ||||||
|             "args": [ |             "args": [ | ||||||
|                 "build", |                 "build", | ||||||
|                 "${workspaceFolder}/ClientHub/OI.Metrology.ClientHub.csproj" |                 "${workspaceFolder}/ClientHub/OI.Metrology.ClientHub.csproj", | ||||||
|  |                 "/property:GenerateFullPaths=true", | ||||||
|  |                 "/consoleloggerparameters:NoSummary" | ||||||
|             ], |             ], | ||||||
|             "problemMatcher": "$msCompile" |             "problemMatcher": "$msCompile" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "label": "Publish Client Hub", |             "label": "publishClientHub", | ||||||
|             "command": "dotnet", |             "command": "dotnet", | ||||||
|             "type": "process", |             "type": "process", | ||||||
|             "args": [ |             "args": [ | ||||||
|                 "publish", |                 "publish", | ||||||
|                 "${workspaceFolder}/ClientHub/OI.Metrology.ClientHub.csproj" |                 "${workspaceFolder}/ClientHub/OI.Metrology.ClientHub.csproj", | ||||||
|  |                 "/property:GenerateFullPaths=true", | ||||||
|  |                 "/consoleloggerparameters:NoSummary" | ||||||
|             ], |             ], | ||||||
|             "problemMatcher": "$msCompile" |             "problemMatcher": "$msCompile" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "label": "Watch Client Hub", |             "label": "watchClientHub", | ||||||
|             "command": "dotnet", |             "command": "dotnet", | ||||||
|             "type": "process", |             "type": "process", | ||||||
|             "args": [ |             "args": [ | ||||||
| @ -201,6 +217,12 @@ | |||||||
|                     "endsPattern": "^.*Application started.*" |                     "endsPattern": "^.*Application started.*" | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "label": "File-Folder-Helper AOT s M Self .Kanbn Tasks", | ||||||
|  |             "type": "shell", | ||||||
|  |             "command": "& L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net7.0/win-x64/publish/File-Folder-Helper.exe s M '.kanbn/tasks'", | ||||||
|  |             "problemMatcher": [] | ||||||
|         } |         } | ||||||
|     ] |     ] | ||||||
| } | } | ||||||
							
								
								
									
										8
									
								
								Archive/.vscode/tasks.json
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -7,7 +7,9 @@ | |||||||
|             "type": "process", |             "type": "process", | ||||||
|             "args": [ |             "args": [ | ||||||
|                 "build", |                 "build", | ||||||
|                 "${workspaceFolder}/Archive.csproj" |                 "${workspaceFolder}/Archive.csproj", | ||||||
|  |                 "/property:GenerateFullPaths=true", | ||||||
|  |                 "/consoleloggerparameters:NoSummary" | ||||||
|             ], |             ], | ||||||
|             "problemMatcher": "$msCompile" |             "problemMatcher": "$msCompile" | ||||||
|         }, |         }, | ||||||
| @ -17,7 +19,9 @@ | |||||||
|             "type": "process", |             "type": "process", | ||||||
|             "args": [ |             "args": [ | ||||||
|                 "publish", |                 "publish", | ||||||
|                 "${workspaceFolder}/Archive.csproj" |                 "${workspaceFolder}/Archive.csproj", | ||||||
|  |                 "/property:GenerateFullPaths=true", | ||||||
|  |                 "/consoleloggerparameters:NoSummary" | ||||||
|             ], |             ], | ||||||
|             "problemMatcher": "$msCompile" |             "problemMatcher": "$msCompile" | ||||||
|         }, |         }, | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								Server/.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -8,7 +8,7 @@ | |||||||
|             "name": ".NET Core Launch (web)", |             "name": ".NET Core Launch (web)", | ||||||
|             "type": "coreclr", |             "type": "coreclr", | ||||||
|             "request": "launch", |             "request": "launch", | ||||||
|             "preLaunchTask": "Build", |             "preLaunchTask": "build", | ||||||
|             // If you have changed target frameworks, make sure to update the program path. |             // If you have changed target frameworks, make sure to update the program path. | ||||||
|             "program": "${workspaceFolder}/bin/Debug/net8.0/OI.Metrology.Server.dll", |             "program": "${workspaceFolder}/bin/Debug/net8.0/OI.Metrology.Server.dll", | ||||||
|             "args": [], |             "args": [], | ||||||
|  | |||||||
							
								
								
									
										5
									
								
								Server/.vscode/mklink.md
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -1,5 +0,0 @@ | |||||||
| # mklink |  | ||||||
|  |  | ||||||
| ```bash Thu Aug 29 2024 09:47:22 GMT-0700 (Mountain Standard Time) |  | ||||||
| mklink /J "L:\DevOps\OpenInsight-Metrology-Viewer\OI-Metrology\Server\.vscode\.UserSecrets" "C:\Users\phares\AppData\Roaming\Microsoft\UserSecrets\b0a3891c-b775-422c-80ee-63a2f385045d" |  | ||||||
| ``` |  | ||||||
							
								
								
									
										478
									
								
								Server/.vscode/tasks.json
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -1,164 +1,22 @@ | |||||||
| { | { | ||||||
|     "inputs": [ |     "version": "2.0.0", | ||||||
|         { |  | ||||||
|             "default": "Development", |  | ||||||
|             "description": "Which ASP Net Core Environment?", |  | ||||||
|             "id": "ASPNETCORE_ENVIRONMENT", |  | ||||||
|             "options": [ |  | ||||||
|                 "Development", |  | ||||||
|                 "Production" |  | ||||||
|             ], |  | ||||||
|             "type": "pickString" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "default": "{AssemblyTitle}", |  | ||||||
|             "description": "What Assembly Title?", |  | ||||||
|             "id": "AssemblyTitle", |  | ||||||
|             "type": "promptString" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "default": "{Build.BuildId}", |  | ||||||
|             "description": "Which Build BuildId?", |  | ||||||
|             "id": "Build.BuildId", |  | ||||||
|             "type": "promptString" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "default": "{Build.Reason}", |  | ||||||
|             "description": "Which Build Reason?", |  | ||||||
|             "id": "Build.Reason", |  | ||||||
|             "type": "promptString" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "default": "{Build.Repository.Id}", |  | ||||||
|             "description": "Which Build Repository Id?", |  | ||||||
|             "id": "Build.Repository.Id", |  | ||||||
|             "type": "promptString" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "default": "{Build.Repository.Name}", |  | ||||||
|             "description": "Which Build Repository Name?", |  | ||||||
|             "id": "Build.Repository.Name", |  | ||||||
|             "type": "promptString" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "default": "{Build.SourceVersion}", |  | ||||||
|             "description": "Which Build Source Version?", |  | ||||||
|             "id": "Build.SourceVersion", |  | ||||||
|             "type": "promptString" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "default": "Debug", |  | ||||||
|             "description": "Which Configuration?", |  | ||||||
|             "id": "Configuration", |  | ||||||
|             "options": [ |  | ||||||
|                 "Debug", |  | ||||||
|                 "Release" |  | ||||||
|             ], |  | ||||||
|             "type": "pickString" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "default": "net8.0", |  | ||||||
|             "description": "Which Core Version?", |  | ||||||
|             "id": "CoreVersion", |  | ||||||
|             "options": [ |  | ||||||
|                 "net8.0" |  | ||||||
|             ], |  | ||||||
|             "type": "pickString" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "default": "C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/MSBuild/Current/Bin/MSBuild.exe", |  | ||||||
|             "description": "Which MS Build?", |  | ||||||
|             "id": "MSBuild", |  | ||||||
|             "type": "promptString" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "default": "https://artifactory.intra.infineon.com/artifactory/api/nuget/ngt-fi-package-main-vir/", |  | ||||||
|             "description": "Which Nuget Source?", |  | ||||||
|             "id": "NugetSource", |  | ||||||
|             "type": "promptString" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "default": "win-x64", |  | ||||||
|             "description": "Which Runtime?", |  | ||||||
|             "id": "Runtime", |  | ||||||
|             "options": [ |  | ||||||
|                 "win-x64", |  | ||||||
|                 "win-x32", |  | ||||||
|                 "linux-x64", |  | ||||||
|                 "linux-x32" |  | ||||||
|             ], |  | ||||||
|             "type": "pickString" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "default": "L:/", |  | ||||||
|             "description": "Which System DefaultWorkingDirectory?", |  | ||||||
|             "id": "System.DefaultWorkingDirectory", |  | ||||||
|             "options": [ |  | ||||||
|                 "L:/", |  | ||||||
|                 "D:/", |  | ||||||
|                 "C:/" |  | ||||||
|             ], |  | ||||||
|             "type": "pickString" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "default": "v4.8", |  | ||||||
|             "description": "Which Core Target Framework Version?", |  | ||||||
|             "id": "TargetFrameworkVersion", |  | ||||||
|             "options": [ |  | ||||||
|                 "v4.8" |  | ||||||
|             ], |  | ||||||
|             "type": "pickString" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "default": "{UserSecretsId}", |  | ||||||
|             "description": "Which Core User Secrets Id?", |  | ||||||
|             "id": "UserSecretsId", |  | ||||||
|             "type": "promptString" |  | ||||||
|         } |  | ||||||
|     ], |  | ||||||
|     "tasks": [ |     "tasks": [ | ||||||
|         { |         { | ||||||
|             "args": [ |             "label": "build", | ||||||
|                 "build" |  | ||||||
|             ], |  | ||||||
|             "command": "dotnet", |             "command": "dotnet", | ||||||
|             "label": "Build", |             "type": "process", | ||||||
|             "problemMatcher": "$msCompile", |  | ||||||
|             "type": "process" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "args": [ |             "args": [ | ||||||
|                 "build", |                 "build", | ||||||
|                 "${workspaceFolder}/../Tests/OI.Metrology.Tests.csproj" |                 "${workspaceFolder}/OI.Metrology.Server.csproj", | ||||||
|  |                 "/property:GenerateFullPaths=true", | ||||||
|  |                 "/consoleloggerparameters:NoSummary" | ||||||
|             ], |             ], | ||||||
|             "command": "dotnet", |             "problemMatcher": "$msCompile" | ||||||
|             "label": "Build Tests", |  | ||||||
|             "problemMatcher": "$msCompile", |  | ||||||
|             "type": "process" |  | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "args": [ |             "label": "Format", | ||||||
|                 "test", |  | ||||||
|                 "${workspaceFolder}/../Tests/OI.Metrology.Tests.csproj" |  | ||||||
|             ], |  | ||||||
|             "command": "dotnet", |             "command": "dotnet", | ||||||
|             "label": "Test Debug", |             "type": "process", | ||||||
|             "problemMatcher": "$msCompile", |  | ||||||
|             "type": "process" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "args": [ |  | ||||||
|                 "test", |  | ||||||
|                 "${workspaceFolder}/../Tests/OI.Metrology.Tests.csproj", |  | ||||||
|                 "-c", |  | ||||||
|                 "Release" |  | ||||||
|             ], |  | ||||||
|             "command": "dotnet", |  | ||||||
|             "label": "Test Release", |  | ||||||
|             "problemMatcher": "$msCompile", |  | ||||||
|             "type": "process" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "args": [ |             "args": [ | ||||||
|                 "format", |                 "format", | ||||||
|                 "--report", |                 "--report", | ||||||
| @ -168,321 +26,71 @@ | |||||||
|                 "--severity", |                 "--severity", | ||||||
|                 "warn" |                 "warn" | ||||||
|             ], |             ], | ||||||
|             "command": "dotnet", |             "problemMatcher": "$msCompile" | ||||||
|             "label": "Format", |  | ||||||
|             "problemMatcher": "$msCompile", |  | ||||||
|             "type": "process" |  | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "args": [ |             "label": "publish", | ||||||
|                 "format", |  | ||||||
|                 "whitespace" |  | ||||||
|             ], |  | ||||||
|             "command": "dotnet", |             "command": "dotnet", | ||||||
|             "label": "Format Whitespace", |             "type": "process", | ||||||
|             "problemMatcher": "$msCompile", |  | ||||||
|             "type": "process" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "args": [ |             "args": [ | ||||||
|                 "publish", |                 "publish", | ||||||
|                 "--configuration", |                 "${workspaceFolder}/OI.Metrology.Server.csproj", | ||||||
|                 "Release", |                 "/property:GenerateFullPaths=true", | ||||||
|                 "--runtime", |                 "/consoleloggerparameters:NoSummary" | ||||||
|                 "win-x64", |  | ||||||
|                 "--self-contained", |  | ||||||
|                 "-o", |  | ||||||
|                 "D:/web-sites/OI-Metrology/hh-3498d1da-_______-OI-Metrology-Release/Server" |  | ||||||
|             ], |             ], | ||||||
|             "command": "dotnet", |             "problemMatcher": "$msCompile" | ||||||
|             "label": "Publish", |  | ||||||
|             "problemMatcher": "$msCompile", |  | ||||||
|             "type": "process" |  | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "args": [ |             "label": "old-watch", | ||||||
|                 "publish", |  | ||||||
|                 "--configuration", |  | ||||||
|                 "Release", |  | ||||||
|                 "--runtime", |  | ||||||
|                 "win-x64", |  | ||||||
|                 "-p:PublishAot=true", |  | ||||||
|                 "/property:GenerateFullPaths=true" |  | ||||||
|             ], |  | ||||||
|             "command": "dotnet", |             "command": "dotnet", | ||||||
|             "label": "Publish AOT", |             "type": "process", | ||||||
|             "problemMatcher": "$msCompile", |  | ||||||
|             "type": "process" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "args": [ |             "args": [ | ||||||
|                 "watch", |                 "watch", | ||||||
|                 "run" |                 "run", | ||||||
|  |                 "--project", | ||||||
|  |                 "${workspaceFolder}/OI.Metrology.Server.csproj" | ||||||
|             ], |             ], | ||||||
|             "command": "dotnet", |             "problemMatcher": "$msCompile" | ||||||
|             "label": "Old Watch", |  | ||||||
|             "problemMatcher": "$msCompile", |  | ||||||
|             "type": "process" |  | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|  |             "label": "watch", | ||||||
|  |             "command": "dotnet", | ||||||
|  |             "type": "process", | ||||||
|             "args": [ |             "args": [ | ||||||
|                 "watch", |                 "watch", | ||||||
|                 "--launch-profile", |                 "--launch-profile", | ||||||
|                 "http", |                 "http", | ||||||
|                 "run", |                 "run", | ||||||
|  |                 "--project", | ||||||
|  |                 "${workspaceFolder}/OI.Metrology.Server.csproj", | ||||||
|                 "--verbose" |                 "--verbose" | ||||||
|             ], |             ], | ||||||
|             "command": "dotnet", |             "isBackground": true, | ||||||
|             "dependsOn": [ |             "dependsOn": [ | ||||||
|                 "build" |                 "build" | ||||||
|             ], |             ], | ||||||
|             "isBackground": true, |  | ||||||
|             "label": "Watch", |  | ||||||
|             "problemMatcher": { |             "problemMatcher": { | ||||||
|  |                 "fileLocation": "relative", | ||||||
|  |                 "pattern": { | ||||||
|  |                     "regexp": "^([^\\s].*)\\((\\d+|\\d+,\\d+|\\d+,\\d+,\\d+,\\d+)\\):\\s+(error|warning|info)\\s+(TS\\d+)\\s*:\\s*(.*)$", | ||||||
|  |                     "file": 1, | ||||||
|  |                     "location": 2, | ||||||
|  |                     "severity": 3, | ||||||
|  |                     "code": 4, | ||||||
|  |                     "message": 5 | ||||||
|  |                 }, | ||||||
|                 "background": { |                 "background": { | ||||||
|                     "activeOnStart": true, |                     "activeOnStart": true, | ||||||
|                     "beginsPattern": "^.*Shutdown requested.*", |                     "beginsPattern": "^.*Shutdown requested.*", | ||||||
|                     "endsPattern": "^.*Application started.*" |                     "endsPattern": "^.*Application started.*" | ||||||
|                 }, |  | ||||||
|                 "fileLocation": "relative", |  | ||||||
|                 "pattern": { |  | ||||||
|                     "code": 4, |  | ||||||
|                     "file": 1, |  | ||||||
|                     "location": 2, |  | ||||||
|                     "message": 5, |  | ||||||
|                     "regexp": "^([^\\s].*)\\((\\d+|\\d+,\\d+|\\d+,\\d+,\\d+,\\d+)\\):\\s+(error|warning|info)\\s+(TS\\d+)\\s*:\\s*(.*)$", |  | ||||||
|                     "severity": 3 |  | ||||||
|                 } |                 } | ||||||
|             }, |             } | ||||||
|             "type": "process" |  | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "args": [ |             "label": "File-Folder-Helper AOT s V Repositories", | ||||||
|                 "s", |             "type": "shell", | ||||||
|                 "X", |             "command": "& L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net7.0/win-x64/publish/File-Folder-Helper.exe s V Repositories", | ||||||
|                 "L:/DevOps/Mesa_FI/OI-Metrology Day-Helper-2024-01-08 L:/DevOps/Mesa_FI/OI-Metrology/Server" |             "problemMatcher": [] | ||||||
|             ], |  | ||||||
|             "command": "L:/DevOps/Mesa_FI/File-Folder-Helper/bin/Release/net8.0/win-x64/publish/File-Folder-Helper.exe", |  | ||||||
|             "label": "File-Folder-Helper AOT s X Server", |  | ||||||
|             "problemMatcher": [], |  | ||||||
|             "type": "shell" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "command": "echo Assembly Title: ${input:AssemblyTitle} & echo Build Id: ${input:Build.BuildId} & echo Build Reason: ${input:Build.Reason} & echo Repo Id: ${input:Build.Repository.Id} & echo Repo Name: ${input:Build.Repository.Name} & echo Source Version: ${input:Build.SourceVersion} & echo Configuration: ${input:Configuration} & echo Core Version: ${input:CoreVersion} & echo Nuget Source: ${input:NugetSource} & echo Runtime: ${input:Runtime}", |  | ||||||
|             "label": "Echo Check", |  | ||||||
|             "problemMatcher": [], |  | ||||||
|             "type": "shell" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "command": "dotnet user-secrets init & dotnet user-secrets set BuildNumber ${input:Build.BuildId} & dotnet user-secrets set GitCommit ${input:Build.SourceVersion} & dotnet user-secrets list", |  | ||||||
|             "label": "App - Safe storage of app secrets", |  | ||||||
|             "problemMatcher": [], |  | ||||||
|             "type": "shell" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "args": [ |  | ||||||
|                 "build", |  | ||||||
|                 "--configuration", |  | ||||||
|                 "${input:Configuration}", |  | ||||||
|                 "--source", |  | ||||||
|                 "${input:NugetSource}" |  | ||||||
|             ], |  | ||||||
|             "command": "dotnet", |  | ||||||
|             "label": "App - Build", |  | ||||||
|             "problemMatcher": "$msCompile", |  | ||||||
|             "type": "process" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "args": [ |  | ||||||
|                 "build", |  | ||||||
|                 "${workspaceFolder}/../Tests/OI.Metrology.Tests.csproj", |  | ||||||
|                 "--configuration", |  | ||||||
|                 "${input:Configuration}", |  | ||||||
|                 "--source", |  | ||||||
|                 "${input:NugetSource}" |  | ||||||
|             ], |  | ||||||
|             "command": "dotnet", |  | ||||||
|             "label": "Tests - Build", |  | ||||||
|             "problemMatcher": "$msCompile", |  | ||||||
|             "type": "process" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "args": [ |  | ||||||
|                 "test", |  | ||||||
|                 "${workspaceFolder}/../Tests/OI.Metrology.Tests.csproj", |  | ||||||
|                 "--configuration", |  | ||||||
|                 "${input:Configuration}" |  | ||||||
|             ], |  | ||||||
|             "command": "dotnet", |  | ||||||
|             "label": "Tests - Test", |  | ||||||
|             "problemMatcher": "$msCompile", |  | ||||||
|             "type": "process" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "args": [ |  | ||||||
|                 "publish", |  | ||||||
|                 "--configuration", |  | ||||||
|                 "${input:Configuration}", |  | ||||||
|                 "--runtime", |  | ||||||
|                 "${input:Runtime}", |  | ||||||
|                 "--self-contained" |  | ||||||
|             ], |  | ||||||
|             "command": "dotnet", |  | ||||||
|             "label": "App - Publish", |  | ||||||
|             "problemMatcher": "$msCompile", |  | ||||||
|             "type": "process" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "args": [ |  | ||||||
|                 "publish", |  | ||||||
|                 "--configuration", |  | ||||||
|                 "${input:Configuration}", |  | ||||||
|                 "--runtime", |  | ||||||
|                 "${input:Runtime}", |  | ||||||
|                 "-p:PublishAot=true" |  | ||||||
|             ], |  | ||||||
|             "command": "dotnet", |  | ||||||
|             "label": "App - AOT Publish", |  | ||||||
|             "problemMatcher": "$msCompile", |  | ||||||
|             "type": "process" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "command": "(robocopy /MIR \"bin/${input:Configuration}/${input:CoreVersion}/${input:Runtime}/publish\" \"D:/${input:CoreVersion}/${input:Runtime}/${input:Build.Repository.Name}/${input:Configuration}/${input:Build.BuildId}/${input:AssemblyTitle}\") ^& IF %ERRORLEVEL% LEQ 7 exit 0", |  | ||||||
|             "label": "Copy Files to: D:/", |  | ||||||
|             "problemMatcher": [], |  | ||||||
|             "type": "shell" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "args": [ |  | ||||||
|                 "tool", |  | ||||||
|                 "restore" |  | ||||||
|             ], |  | ||||||
|             "command": "dotnet", |  | ||||||
|             "label": "Tool Restore", |  | ||||||
|             "problemMatcher": [], |  | ||||||
|             "type": "process" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "args": [ |  | ||||||
|                 "ReportGenerator", |  | ||||||
|                 "-reports:${input:System.DefaultWorkingDirectory}/TestResults/**/coverage.cobertura.xml", |  | ||||||
|                 "-targetDir:${input:Build.ArtifactStagingDirectory}/Coverage", |  | ||||||
|                 "-reportTypes:Html_Dark" |  | ||||||
|             ], |  | ||||||
|             "command": "dotnet", |  | ||||||
|             "label": "Report Generator", |  | ||||||
|             "problemMatcher": [], |  | ||||||
|             "type": "process" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "args": [ |  | ||||||
|                 "clean", |  | ||||||
|                 "${workspaceFolder}/../Tests/OI.Metrology.Tests.csproj", |  | ||||||
|                 "--configuration", |  | ||||||
|                 "${input:Configuration}" |  | ||||||
|             ], |  | ||||||
|             "command": "dotnet", |  | ||||||
|             "label": "Tests - Clean", |  | ||||||
|             "problemMatcher": "$msCompile", |  | ||||||
|             "type": "process" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "args": [ |  | ||||||
|                 "clean", |  | ||||||
|                 "--configuration", |  | ||||||
|                 "${input:Configuration}" |  | ||||||
|             ], |  | ||||||
|             "command": "dotnet", |  | ||||||
|             "label": "App - Clean", |  | ||||||
|             "problemMatcher": "$msCompile", |  | ||||||
|             "type": "process" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "command": "C:/Windows/system32/inetsrv/appcmd.exe stop apppool /apppool.name:${input:AssemblyTitle}.${input:Configuration} & exit 0", |  | ||||||
|             "label": "Stop Pool", |  | ||||||
|             "problemMatcher": [], |  | ||||||
|             "type": "shell" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "command": "C:/Windows/system32/inetsrv/appcmd.exe stop site /site.name:${input:AssemblyTitle}.${input:Configuration} & exit 0", |  | ||||||
|             "label": "Stop Website", |  | ||||||
|             "problemMatcher": [], |  | ||||||
|             "type": "shell" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "command": "rmdir D:/web-sites/${input:AssemblyTitle}.${input:Configuration} & exit 0", |  | ||||||
|             "label": "Remove MKLink", |  | ||||||
|             "problemMatcher": [], |  | ||||||
|             "type": "shell" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "command": "mklink /J \"D:\\web-sites\\${input:AssemblyTitle}.${input:Configuration}\" \"D:\\$(CoreVersion)\\$(Runtime)\\$(Build.Repository.Name)\\$(Configuration)\\$(Build.BuildId)\\$(AssemblyTitle)\"", |  | ||||||
|             "label": "Create MKLink", |  | ||||||
|             "problemMatcher": [], |  | ||||||
|             "type": "shell" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "command": "mkdir D:/web-sites/${input:AssemblyTitle}.${input:Configuration}/${input:AssemblyTitle}.${input:Configuration} & exit 0", |  | ||||||
|             "label": "Make Directory", |  | ||||||
|             "problemMatcher": [], |  | ||||||
|             "type": "shell" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "command": "(robocopy /IS /IT /IM \"%USERPROFILE%/AppData/Roaming/Microsoft/UserSecrets/$(UserSecretsId)\" \"D:/$(CoreVersion)/$(Runtime)/$(Build.Repository.Name)/$(Configuration)/$(Build.BuildId)/$(AssemblyTitle)\" secrets.json) ^& IF %ERRORLEVEL% LEQ 7 exit 0", |  | ||||||
|             "label": "Replace User Secrets Id File", |  | ||||||
|             "problemMatcher": [], |  | ||||||
|             "type": "shell" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "command": "(robocopy /IS /IT /IM \"%USERPROFILE%/AppData/Roaming/Microsoft/UserSecrets/$(UserSecretsId)\" \"D:/$(CoreVersion)/$(Runtime)/$(Build.Repository.Name)/$(Configuration)/$(Build.BuildId)/$(AssemblyTitle)\" web.config) ^& IF %ERRORLEVEL% LEQ 7 exit 0", |  | ||||||
|             "label": "Replace Web Configuration File", |  | ||||||
|             "problemMatcher": [], |  | ||||||
|             "type": "shell" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "command": "C:/Windows/system32/inetsrv/appcmd.exe start apppool /apppool.name:${input:AssemblyTitle}.${input:Configuration}", |  | ||||||
|             "label": "Start Pool", |  | ||||||
|             "problemMatcher": [], |  | ||||||
|             "type": "shell" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "command": "C:/Windows/system32/inetsrv/appcmd.exe start site /site.name:${input:AssemblyTitle}.${input:Configuration}", |  | ||||||
|             "label": "Start Website", |  | ||||||
|             "problemMatcher": [], |  | ||||||
|             "type": "shell" |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|             "args": [ |  | ||||||
|                 "App - AOT Publish", |  | ||||||
|                 "Tool Restore", |  | ||||||
|                 "Report Generator" |  | ||||||
|             ], |  | ||||||
|             "command": "echo", |  | ||||||
|             "dependsOn": [ |  | ||||||
|                 "Echo Check", |  | ||||||
|                 "App - Safe storage of app secrets", |  | ||||||
|                 "App - Build", |  | ||||||
|                 "Tests - Build", |  | ||||||
|                 "Tests - Test", |  | ||||||
|                 "App - Publish", |  | ||||||
|                 "Copy Files to: D:/", |  | ||||||
|                 "Tests - Clean", |  | ||||||
|                 "App - Clean", |  | ||||||
|                 "Stop Pool", |  | ||||||
|                 "Stop Website", |  | ||||||
|                 "Remove MKLink", |  | ||||||
|                 "Create MKLink", |  | ||||||
|                 "Make Directory", |  | ||||||
|                 "Replace User Secrets Id File", |  | ||||||
|                 "Replace Web Configuration File", |  | ||||||
|                 "Start Pool", |  | ||||||
|                 "Start Website" |  | ||||||
|             ], |  | ||||||
|             "dependsOrder": "sequence", |  | ||||||
|             "label": "Pipeline", |  | ||||||
|             "problemMatcher": [], |  | ||||||
|             "type": "shell" |  | ||||||
|         } |         } | ||||||
|     ], |     ] | ||||||
|     "version": "2.0.0" |  | ||||||
| } | } | ||||||
| @ -1,5 +1,4 @@ | |||||||
| using Microsoft.AspNetCore.Mvc; | using Microsoft.AspNetCore.Mvc; | ||||||
| using OI.Metrology.Server.Models; |  | ||||||
| using OI.Metrology.Shared.Models.Stateless; | using OI.Metrology.Shared.Models.Stateless; | ||||||
|  |  | ||||||
| namespace OI.Metrology.Server.ApiControllers; | namespace OI.Metrology.Server.ApiControllers; | ||||||
| @ -9,9 +8,9 @@ namespace OI.Metrology.Server.ApiControllers; | |||||||
| public class AppSettingsController : ControllerBase, IAppSettingsController<ActionResult> | public class AppSettingsController : ControllerBase, IAppSettingsController<ActionResult> | ||||||
| { | { | ||||||
|  |  | ||||||
|     private readonly IAppSettingsRepository<AppSettings> _AppSettingsRepository; |     private readonly IAppSettingsRepository<Models.Binder.AppSettings> _AppSettingsRepository; | ||||||
|  |  | ||||||
|     public AppSettingsController(IAppSettingsRepository<AppSettings> AppSettingsRepository) => _AppSettingsRepository = AppSettingsRepository; |     public AppSettingsController(IAppSettingsRepository<Models.Binder.AppSettings> AppSettingsRepository) => _AppSettingsRepository = AppSettingsRepository; | ||||||
|  |  | ||||||
|     [HttpGet(nameof(IAppSettingsController<ActionResult>.Action.App))] |     [HttpGet(nameof(IAppSettingsController<ActionResult>.Action.App))] | ||||||
|     public ActionResult GetAppSettings() => |     public ActionResult GetAppSettings() => | ||||||
|  | |||||||
| @ -38,10 +38,4 @@ public class AwaitingDispoController : Controller, IAwaitingDispoController<IAct | |||||||
|         else |         else | ||||||
|             return StatusCode(444); |             return StatusCode(444); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // this endpoint is used to clear the ReviewDate column, causing the header to show up again |  | ||||||
|     [HttpGet("/api/awaitingdispo/{toolTypeId}/header-attachment-id")] |  | ||||||
|     public IActionResult GetHeaderAttachmentID(int toolTypeId, [FromQuery] long headerid) => |  | ||||||
|         Content(_MetrologyRepository.GetHeaderAttachmentID(toolTypeId, headerid).ToString()); |  | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -4,7 +4,6 @@ namespace OI.Metrology.Server.ApiControllers; | |||||||
|  |  | ||||||
| using OI.Metrology.Shared.DataModels; | using OI.Metrology.Shared.DataModels; | ||||||
| using OI.Metrology.Shared.Models.Stateless; | using OI.Metrology.Shared.Models.Stateless; | ||||||
| using System.Data; |  | ||||||
| using System.Text.Json; | using System.Text.Json; | ||||||
|  |  | ||||||
| [Route("api/[controller]")] | [Route("api/[controller]")] | ||||||
| @ -12,13 +11,9 @@ public class ExportController : Controller, IExportController<IActionResult> | |||||||
| { | { | ||||||
|  |  | ||||||
|     private readonly IExportRepository _ExportRepository; |     private readonly IExportRepository _ExportRepository; | ||||||
|     private readonly IMetrologyRepository _MetrologyRepository; |  | ||||||
|  |  | ||||||
|     public ExportController(IExportRepository exportRepository, IMetrologyRepository metrologyRepository) |     public ExportController(IExportRepository exportRepository) => | ||||||
|     { |  | ||||||
|         _ExportRepository = exportRepository; |         _ExportRepository = exportRepository; | ||||||
|         _MetrologyRepository = metrologyRepository; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static string? GetJson(Stream stream) |     private static string? GetJson(Stream stream) | ||||||
|     { |     { | ||||||
| @ -84,21 +79,4 @@ public class ExportController : Controller, IExportController<IActionResult> | |||||||
|     public IActionResult PostProcessDataStandardFormat() => |     public IActionResult PostProcessDataStandardFormat() => | ||||||
|         Content(_ExportRepository.GetProcessDataStandardFormat(GetHeaderCommon(Request.Body))); |         Content(_ExportRepository.GetProcessDataStandardFormat(GetHeaderCommon(Request.Body))); | ||||||
|  |  | ||||||
|     [HttpGet] |  | ||||||
|     [Route("{toolTypeId}/export")] |  | ||||||
|     public IActionResult GetExportData(int toolTypeId, [FromQuery] string? datebegin, [FromQuery] string? dateend) |  | ||||||
|     { |  | ||||||
|         Result<DataTable> r = _ExportRepository.GetExportData(_MetrologyRepository, toolTypeId, datebegin, dateend); |  | ||||||
|         string json = Newtonsoft.Json.JsonConvert.SerializeObject(r); |  | ||||||
|         return Content(json); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     [HttpGet] |  | ||||||
|     [Route("{toolTypeId}/csv")] |  | ||||||
|     public IActionResult GetCSVExport(int toolTypeId, [FromQuery] string? datebegin, [FromQuery] string? dateend, [FromQuery] string? filename) |  | ||||||
|     { |  | ||||||
|         string r = _ExportRepository.GetCSVExport(_MetrologyRepository, toolTypeId, datebegin, dateend); |  | ||||||
|         return Content(r); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -22,7 +22,7 @@ public class FileShareController : Controller, IFileShareController<IResult> | |||||||
|     [HttpGet("move-file")] |     [HttpGet("move-file")] | ||||||
|     public IResult MoveFile(string from, string to) |     public IResult MoveFile(string from, string to) | ||||||
|     { |     { | ||||||
|         _FileShareRepository.MoveFile(from, to); |         _FileShareRepository.CopyFile(from, to); | ||||||
|         return Results.Ok(); |         return Results.Ok(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | |||||||
| @ -4,7 +4,6 @@ using OI.Metrology.Shared.Models; | |||||||
| using OI.Metrology.Shared.Models.Stateless; | using OI.Metrology.Shared.Models.Stateless; | ||||||
| using OI.Metrology.Shared.Services; | using OI.Metrology.Shared.Services; | ||||||
| using System.Net; | using System.Net; | ||||||
| using System.Text.Json; |  | ||||||
|  |  | ||||||
| namespace OI.Metrology.Server.ApiControllers; | namespace OI.Metrology.Server.ApiControllers; | ||||||
|  |  | ||||||
| @ -30,9 +29,22 @@ public partial class InboundController : ControllerBase, IInboundController<IAct | |||||||
|         _MetrologyRepository = metrologyRepository; |         _MetrologyRepository = metrologyRepository; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     private static string? GetJson(Stream stream) | ||||||
|  |     { | ||||||
|  |         string? result; | ||||||
|  |         if (!stream.CanRead) | ||||||
|  |             result = null; | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             Task<string> task = new StreamReader(stream).ReadToEndAsync(); | ||||||
|  |             result = task.Result; | ||||||
|  |         } | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     [HttpPost] |     [HttpPost] | ||||||
|     [Route("{tooltype}")] |     [Route("{tooltype}")] | ||||||
|     public IActionResult Post(string tooltype, JsonElement? jsonElement) |     public IActionResult Post(string tooltype) | ||||||
|     { |     { | ||||||
|         IPAddress? remoteIP = HttpContext.Connection.RemoteIpAddress; |         IPAddress? remoteIP = HttpContext.Connection.RemoteIpAddress; | ||||||
|         if (!_InboundRepository.IsIPAddressAllowed(_AppSettings.InboundApiAllowedIPList, remoteIP)) |         if (!_InboundRepository.IsIPAddressAllowed(_AppSettings.InboundApiAllowedIPList, remoteIP)) | ||||||
| @ -42,7 +54,8 @@ public partial class InboundController : ControllerBase, IInboundController<IAct | |||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             DataResponse dataResponse = _InboundRepository.Data(_MetrologyRepository, _InboundDataService, tooltype, jsonElement); |             string? json = GetJson(Request.Body); | ||||||
|  |             DataResponse dataResponse = _InboundRepository.Data(_MetrologyRepository, _InboundDataService, tooltype, json); | ||||||
|             if (dataResponse.Errors.Count == 0) |             if (dataResponse.Errors.Count == 0) | ||||||
|                 return Ok(dataResponse); |                 return Ok(dataResponse); | ||||||
|             else |             else | ||||||
| @ -52,7 +65,7 @@ public partial class InboundController : ControllerBase, IInboundController<IAct | |||||||
|  |  | ||||||
|     [HttpPost] |     [HttpPost] | ||||||
|     [Route("{tooltype}/attachment")] |     [Route("{tooltype}/attachment")] | ||||||
|     public IActionResult AttachFile(string tooltype, Attachment? attachment) |     public IActionResult AttachFile(string tooltype, [FromQuery] long headerid, [FromQuery] string datauniqueid = "") | ||||||
|     { |     { | ||||||
|         IPAddress? remoteIP = HttpContext.Connection.RemoteIpAddress; |         IPAddress? remoteIP = HttpContext.Connection.RemoteIpAddress; | ||||||
|         if (!_InboundRepository.IsIPAddressAllowed(_AppSettings.InboundApiAllowedIPList, remoteIP)) |         if (!_InboundRepository.IsIPAddressAllowed(_AppSettings.InboundApiAllowedIPList, remoteIP)) | ||||||
| @ -62,8 +75,16 @@ public partial class InboundController : ControllerBase, IInboundController<IAct | |||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             _InboundRepository.AttachFile(_MetrologyRepository, _AttachmentsService, tooltype, attachment); |             if (Request.Form is null) | ||||||
|             return Ok(); |                 return BadRequest($"Invalid form"); | ||||||
|  |             if (Request.Form.Files.Count != 1) | ||||||
|  |                 return BadRequest($"Invalid file count"); | ||||||
|  |             IFormFile formFile = Request.Form.Files[0]; | ||||||
|  |             string? message = _InboundRepository.AttachFile(_MetrologyRepository, _AttachmentsService, tooltype, headerid, datauniqueid, formFile.FileName, formFile); | ||||||
|  |             if (message is null) | ||||||
|  |                 return Ok(); | ||||||
|  |             else | ||||||
|  |                 return BadRequest(message); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | |||||||
| @ -79,8 +79,12 @@ public class InfinityQSV4Controller : Controller, IInfinityQSV4Controller<IActio | |||||||
|     public IActionResult GetProductionSpecification(string part) => |     public IActionResult GetProductionSpecification(string part) => | ||||||
|        Content(_InfinityQSRepositoryV4.GetProductionSpecification(part)); |        Content(_InfinityQSRepositoryV4.GetProductionSpecification(part)); | ||||||
|  |  | ||||||
|     [HttpGet("{process}/last-group-id-with-value")] |     [HttpGet("engineering-spc-review")] | ||||||
|     public IActionResult GetLastGroupIdWithValue(string process, string? part, int? test) => |     public IActionResult GetEngineeringSpcReview() | ||||||
|        Content(_InfinityQSRepositoryV4.GetLastGroupIdWithValue(process, part, test)); |     { | ||||||
|  |         Dictionary<string, List<string>> results = _InfinityQSRepositoryV4.GetEngineeringSpcReview(); | ||||||
|  |         string json = JsonSerializer.Serialize(results); | ||||||
|  |         return Content(json, "application/json", System.Text.Encoding.UTF8); | ||||||
|  |     } | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -66,6 +66,23 @@ public class ToolTypesController : Controller, IToolTypesController<IActionResul | |||||||
|         return Content(json); |         return Content(json); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     [HttpGet] | ||||||
|  |     [Route("{toolTypeId}/export")] | ||||||
|  |     public IActionResult GetExportData(int toolTypeId, [FromQuery] string? datebegin, [FromQuery] string? dateend) | ||||||
|  |     { | ||||||
|  |         Shared.DataModels.Result<DataTable> r = _ToolTypesRepository.GetExportData(_MetrologyRepo, toolTypeId, datebegin, dateend); | ||||||
|  |         string json = JsonConvert.SerializeObject(r); | ||||||
|  |         return Content(json); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     [HttpGet] | ||||||
|  |     [Route("{toolTypeId}/csv")] | ||||||
|  |     public IActionResult GetCSVExport(int toolTypeId, [FromQuery] string? datebegin, [FromQuery] string? dateend, [FromQuery] string? filename) | ||||||
|  |     { | ||||||
|  |         byte[] r = _ToolTypesRepository.GetCSVExport(_MetrologyRepo, toolTypeId, datebegin, dateend); | ||||||
|  |         return File(r, "application/octet-stream", filename); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     [HttpGet] |     [HttpGet] | ||||||
|     [Route("{toolTypeId}/{tabletype}/files/{attachmentId}/{filename}")] |     [Route("{toolTypeId}/{tabletype}/files/{attachmentId}/{filename}")] | ||||||
|     public IActionResult GetAttachment(int toolTypeId, string tabletype, string attachmentId, string filename) |     public IActionResult GetAttachment(int toolTypeId, string tabletype, string attachmentId, string filename) | ||||||
|  | |||||||
							
								
								
									
										22
									
								
								Server/ApiControllers/WaferCounterController.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,22 @@ | |||||||
|  | using Microsoft.AspNetCore.Mvc; | ||||||
|  | using OI.Metrology.Shared.Models.Stateless; | ||||||
|  |  | ||||||
|  | namespace OI.Metrology.Server.ApiControllers; | ||||||
|  |  | ||||||
|  | [Route("api/v1/WaferCounter")] | ||||||
|  | public class WaferCounterController : Controller, IWaferCounterController<IActionResult> | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     private readonly IWaferCounterRepository _WaferCounterRepository; | ||||||
|  |  | ||||||
|  |     public WaferCounterController(IWaferCounterRepository waferCounterRepository) => | ||||||
|  |         _WaferCounterRepository = waferCounterRepository; | ||||||
|  |  | ||||||
|  |     [HttpGet("{waferSize}/last-quantity-and-slot-map")] | ||||||
|  |     public IActionResult GetLastQuantityAndSlotMap(string area, string waferSize) => | ||||||
|  |         Json(_WaferCounterRepository.GetLastQuantityAndSlotMap(area, waferSize)); | ||||||
|  |  | ||||||
|  |     [HttpGet("{waferSize}/last-quantity-and-slot-map-with-text")] | ||||||
|  |     public IActionResult GetLastQuantityAndSlotMapWithText(string area, string waferSize, string text) => | ||||||
|  |         Json(_WaferCounterRepository.GetLastQuantityAndSlotMapWithText(area, waferSize, text)); | ||||||
|  | } | ||||||
							
								
								
									
										160
									
								
								Server/Controllers/ExportController.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,160 @@ | |||||||
|  | using Infineon.Monitoring.MonA; | ||||||
|  | using Microsoft.AspNetCore.Mvc; | ||||||
|  | using Microsoft.AspNetCore.Mvc.Filters; | ||||||
|  | using OI.Metrology.Server.Models; | ||||||
|  | using OI.Metrology.Shared.DataModels; | ||||||
|  | using OI.Metrology.Shared.Models.Stateless; | ||||||
|  | using OI.Metrology.Shared.ViewModels; | ||||||
|  | using System.Text; | ||||||
|  |  | ||||||
|  | namespace OI.Metrology.Server.Controllers; | ||||||
|  |  | ||||||
|  | public class ExportController : Controller | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     private readonly ILogger _Logger; | ||||||
|  |     private readonly AppSettings _AppSettings; | ||||||
|  |     private readonly bool _IsTestDatabase; | ||||||
|  |     private readonly IMetrologyRepository _MetrologyRepository; | ||||||
|  |  | ||||||
|  |     public ExportController(AppSettings appSettings, ILogger<ExportController> logger, IMetrologyRepository metrologyRepository) | ||||||
|  |     { | ||||||
|  |         _Logger = logger; | ||||||
|  |         _AppSettings = appSettings; | ||||||
|  |         _MetrologyRepository = metrologyRepository; | ||||||
|  |         _IsTestDatabase = appSettings.ConnectionString.Contains("test", StringComparison.InvariantCultureIgnoreCase); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public override void OnActionExecuted(ActionExecutedContext context) | ||||||
|  |     { | ||||||
|  |         base.OnActionExecuted(context); | ||||||
|  |         ViewBag.IsTestDatabase = _IsTestDatabase; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private string GetApiUrl() => string.IsNullOrEmpty(_AppSettings.ApiUrl) ? Url.Content("~/") : _AppSettings.ApiUrl[0] == '~' ? Url.Content(_AppSettings.ApiUrl) : _AppSettings.ApiUrl; | ||||||
|  |  | ||||||
|  |     [HttpGet] | ||||||
|  |     [Route("/Export")] | ||||||
|  |     public ActionResult Index() | ||||||
|  |     { | ||||||
|  |         Export model = new() | ||||||
|  |         { | ||||||
|  |             StartTime = DateTime.Now.AddMonths(-1), | ||||||
|  |             EndTime = DateTime.Now | ||||||
|  |         }; | ||||||
|  |         MonIn monIn = MonIn.GetInstance(); | ||||||
|  |         _ = monIn.SendStatus(_AppSettings.MonASite, _AppSettings.MonAResource, "Heartbeat", State.Up); | ||||||
|  |         ViewBag.ApiUrl = GetApiUrl(); | ||||||
|  |         return View(model); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     [HttpPost] | ||||||
|  |     [Route("/ExportData")] | ||||||
|  |     public ActionResult ExportData(Export model) | ||||||
|  |     { | ||||||
|  |         ToolType? toolType = null; | ||||||
|  |         if (string.IsNullOrEmpty(model.ToolType)) | ||||||
|  |             ModelState.AddModelError("Exception", "Invalid selection"); | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             if (model.StartTime > model.EndTime) | ||||||
|  |                 ModelState.AddModelError("EndTime", "End time must be after start time"); | ||||||
|  |             IEnumerable<ToolType> toolTypes = _MetrologyRepository.GetToolTypes(); | ||||||
|  |             toolType = toolTypes.Where(tt => tt.ID.ToString() == model.ToolType).SingleOrDefault(); | ||||||
|  |             if (toolType is null) | ||||||
|  |                 ModelState.AddModelError("ToolType", "Invalid selection"); | ||||||
|  |             else if (string.IsNullOrWhiteSpace(toolType.ExportSPName)) | ||||||
|  |                 ModelState.AddModelError("ToolType", "Tool type is not exportable"); | ||||||
|  |         } | ||||||
|  |         if (ModelState.IsValid) | ||||||
|  |         { | ||||||
|  |             try | ||||||
|  |             { | ||||||
|  |                 DateTime startDT = model.StartDate.Date.Add(model.StartTime.TimeOfDay); | ||||||
|  |                 DateTime endDT = model.EndDate.Date.Add(model.EndTime.TimeOfDay); | ||||||
|  |  | ||||||
|  |                 return DoCSVExport(toolType?.ToolTypeName, toolType?.ExportSPName, startDT, endDT); | ||||||
|  |             } | ||||||
|  |             catch (Exception ex) | ||||||
|  |             { | ||||||
|  |                 ModelState.AddModelError("Exception", "Error exporting data"); | ||||||
|  |                 ModelState.AddModelError("Exception", ex.Message); | ||||||
|  |                 string errorMessage = $"Error exporting: {ex}"; | ||||||
|  |                 _Logger.LogError(message: errorMessage); | ||||||
|  |                 MonIn monIn = MonIn.GetInstance(); | ||||||
|  |                 _ = monIn.SendStatus(_AppSettings.MonASite, _AppSettings.MonAResource, "Heartbeat", State.Warning); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         ViewBag.ApiUrl = GetApiUrl(); | ||||||
|  |         return View("Index", model); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected ActionResult DoCSVExport(string? toolTypeName, string? spName, DateTime startTime, DateTime endTime) | ||||||
|  |     { | ||||||
|  |         string fileName = string.Format("Export_{0}_{1:yyyyMMddHHmm}_to_{2:yyyyMMddHHmm}.csv", toolTypeName, startTime, endTime); | ||||||
|  |         StringBuilder sb = new(); | ||||||
|  |         if (spName is null) | ||||||
|  |             throw new NullReferenceException(nameof(spName)); | ||||||
|  |         System.Data.DataTable dt = _MetrologyRepository.ExportData(spName, startTime, endTime); | ||||||
|  |         _ = sb.AppendLine(GetColumnHeaders(dt)); | ||||||
|  |         foreach (System.Data.DataRow dr in dt.Rows) | ||||||
|  |             _ = sb.AppendLine(GetRowData(dr)); | ||||||
|  |         byte[] contents = Encoding.UTF8.GetBytes(sb.ToString()); | ||||||
|  |         return File(contents, "application/octet-stream", fileName); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected static string GetRowData(System.Data.DataRow dr) | ||||||
|  |     { | ||||||
|  |         StringBuilder r = new(); | ||||||
|  |         for (int i = 0; i < dr.Table.Columns.Count; i++) | ||||||
|  |         { | ||||||
|  |             if (i > 0) | ||||||
|  |                 _ = r.Append(','); | ||||||
|  |             object v = dr[i]; | ||||||
|  |             if (!Convert.IsDBNull(v)) | ||||||
|  |             { | ||||||
|  |                 string? c = Convert.ToString(v); | ||||||
|  |                 if (c is not null) | ||||||
|  |                     _ = r.Append(FormatForCSV(c)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return r.ToString(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected static string GetColumnHeaders(System.Data.DataTable dt) | ||||||
|  |     { | ||||||
|  |         StringBuilder r = new(); | ||||||
|  |         for (int i = 0; i < dt.Columns.Count; i++) | ||||||
|  |         { | ||||||
|  |             if (i > 0) | ||||||
|  |                 _ = r.Append(','); | ||||||
|  |  | ||||||
|  |             _ = r.Append(FormatForCSV(dt.Columns[i].ColumnName.TrimEnd('_'))); | ||||||
|  |         } | ||||||
|  |         return r.ToString(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected static string FormatForCSV(string v) | ||||||
|  |     { | ||||||
|  |         bool doubleQuoted = false; | ||||||
|  |         StringBuilder r = new(v.Length + 2); | ||||||
|  |         if (v.StartsWith(' ') || v.EndsWith(' ') || v.Contains(',') || v.Contains('"')) | ||||||
|  |         { | ||||||
|  |             _ = r.Append('"'); | ||||||
|  |             doubleQuoted = true; | ||||||
|  |         } | ||||||
|  |         foreach (char c in v) | ||||||
|  |         { | ||||||
|  |             _ = c switch | ||||||
|  |             { | ||||||
|  |                 '\r' or '\n' => r.Append(' '), | ||||||
|  |                 '"' => r.Append("\"\""), | ||||||
|  |                 _ => r.Append(c), | ||||||
|  |             }; | ||||||
|  |         } | ||||||
|  |         if (doubleQuoted) | ||||||
|  |             _ = r.Append('"'); | ||||||
|  |         return r.ToString(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										79
									
								
								Server/Controllers/PagesController.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,79 @@ | |||||||
|  | using Microsoft.AspNetCore.Mvc; | ||||||
|  | using Microsoft.AspNetCore.Mvc.Filters; | ||||||
|  | using OI.Metrology.Server.Models; | ||||||
|  | using OI.Metrology.Shared.Models.Stateless; | ||||||
|  | using OI.Metrology.Shared.ViewModels; | ||||||
|  |  | ||||||
|  | namespace OI.Metrology.Server.Controllers; | ||||||
|  |  | ||||||
|  | public class PagesController : Controller | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     private readonly bool _IsTestDatabase; | ||||||
|  |     private readonly AppSettings _AppSettings; | ||||||
|  |     private readonly IMetrologyRepository _MetrologyRepository; | ||||||
|  |  | ||||||
|  |     public PagesController(AppSettings appSettings, IMetrologyRepository metrologyRepository) | ||||||
|  |     { | ||||||
|  |         _AppSettings = appSettings; | ||||||
|  |         _MetrologyRepository = metrologyRepository; | ||||||
|  |         _IsTestDatabase = appSettings.ConnectionString.Contains("test", StringComparison.InvariantCultureIgnoreCase); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public override void OnActionExecuted(ActionExecutedContext context) | ||||||
|  |     { | ||||||
|  |         base.OnActionExecuted(context); | ||||||
|  |         ViewBag.IsTestDatabase = _IsTestDatabase; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private string GetApiUrl() => string.IsNullOrEmpty(_AppSettings.ApiUrl) ? Url.Content("~/") : _AppSettings.ApiUrl[0] == '~' ? Url.Content(_AppSettings.ApiUrl) : _AppSettings.ApiUrl; | ||||||
|  |  | ||||||
|  |     [HttpGet] | ||||||
|  |     [Route("/")] | ||||||
|  |     public IActionResult Index() | ||||||
|  |     { | ||||||
|  |         ViewBag.ApiUrl = GetApiUrl(); | ||||||
|  |         return View("AwaitingDispo"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     [HttpGet] | ||||||
|  |     [Route("/AwaitingDispo")] | ||||||
|  |     [Route("/Metrology/AwaitingDispo")] | ||||||
|  |     public IActionResult AwaitingDispo() | ||||||
|  |     { | ||||||
|  |         ViewBag.ApiUrl = GetApiUrl(); | ||||||
|  |         return View(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     [HttpGet] | ||||||
|  |     [Route("/RunInfo")] | ||||||
|  |     [Route("/Metrology/RunInfo")] | ||||||
|  |     public IActionResult RunInfo([FromQuery] int tooltypeid = 1, [FromQuery] int headerid = 0) | ||||||
|  |     { | ||||||
|  |         RunInfo m = new() | ||||||
|  |         { | ||||||
|  |             ToolTypeID = tooltypeid, | ||||||
|  |             HeaderID = headerid, | ||||||
|  |             HeaderAttachmentID = Guid.Empty, | ||||||
|  |         }; | ||||||
|  |         if (headerid > 0) | ||||||
|  |         { | ||||||
|  |             m.HeaderAttachmentID = _MetrologyRepository.GetHeaderAttachmentID(tooltypeid, headerid); | ||||||
|  |         } | ||||||
|  |         ViewBag.ApiUrl = GetApiUrl(); | ||||||
|  |         return View(m); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     [HttpGet] | ||||||
|  |     [Route("/RunHeaders")] | ||||||
|  |     [Route("/Metrology/RunHeaders")] | ||||||
|  |     public IActionResult RunHeaders() | ||||||
|  |     { | ||||||
|  |         ViewBag.ApiUrl = GetApiUrl(); | ||||||
|  |         return View(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     [HttpGet] | ||||||
|  |     [Route("/Crash")] | ||||||
|  |     public IActionResult Crash() => throw new Exception("Test unhandled exception"); | ||||||
|  | } | ||||||
| @ -1,5 +1,4 @@ | |||||||
| using System.Text.Json; | using System.Text.Json; | ||||||
| using System.Text.Json.Serialization; |  | ||||||
|  |  | ||||||
| namespace OI.Metrology.Server.Models; | namespace OI.Metrology.Server.Models; | ||||||
|  |  | ||||||
| @ -14,7 +13,6 @@ public record AppSettings(string ApiFileShare, | |||||||
|                           string EcCharacterizationSi, |                           string EcCharacterizationSi, | ||||||
|                           string EcMesaFileShareCharacterizationSi, |                           string EcMesaFileShareCharacterizationSi, | ||||||
|                           string EcMesaFileShareMetrologySi, |                           string EcMesaFileShareMetrologySi, | ||||||
|                           string EcMetrologySi, |  | ||||||
|                           string GitCommitSeven, |                           string GitCommitSeven, | ||||||
|                           string InboundApiAllowedIPList, |                           string InboundApiAllowedIPList, | ||||||
|                           string IqsColumns, |                           string IqsColumns, | ||||||
| @ -37,75 +35,8 @@ public record AppSettings(string ApiFileShare, | |||||||
|  |  | ||||||
|     public override string ToString() |     public override string ToString() | ||||||
|     { |     { | ||||||
|         string result = JsonSerializer.Serialize(this, AppSettingsSourceGenerationContext.Default.AppSettings); |         string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private static void Verify(AppSettings appSettings) |  | ||||||
|     { |  | ||||||
|         if (string.IsNullOrEmpty(appSettings.Company)) |  | ||||||
|             throw new Exception("Company name must have a value!"); |  | ||||||
|         if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) |  | ||||||
|             throw new Exception("Working directory name must have a value!"); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public static AppSettings Get(IConfigurationRoot configurationRoot) |  | ||||||
|     { |  | ||||||
|         AppSettings result; |  | ||||||
|         AppSettings? appSettings = configurationRoot.Get<AppSettings>(); |  | ||||||
| #pragma warning restore IL3050, IL2026 |  | ||||||
|         if (appSettings is null |  | ||||||
|             || appSettings?.Company is null) |  | ||||||
|         { |  | ||||||
|             List<string> paths = []; |  | ||||||
|             foreach (IConfigurationProvider configurationProvider in configurationRoot.Providers) |  | ||||||
|             { |  | ||||||
|                 if (configurationProvider is not Microsoft.Extensions.Configuration.Json.JsonConfigurationProvider jsonConfigurationProvider) |  | ||||||
|                     continue; |  | ||||||
|                 if (jsonConfigurationProvider.Source.FileProvider is not Microsoft.Extensions.FileProviders.PhysicalFileProvider physicalFileProvider) |  | ||||||
|                     continue; |  | ||||||
|                 paths.Add(physicalFileProvider.Root); |  | ||||||
|             } |  | ||||||
|             throw new NotSupportedException($"Not found!{Environment.NewLine}{string.Join(Environment.NewLine, paths.Distinct())}"); |  | ||||||
|         } |  | ||||||
|         result = new(appSettings.ApiFileShare, |  | ||||||
|                      appSettings.ApiLoggingContentTypes, |  | ||||||
|                      appSettings.ApiLoggingPathPrefixes, |  | ||||||
|                      appSettings.ApiLogPath, |  | ||||||
|                      appSettings.ApiUrl, |  | ||||||
|                      appSettings.BuildNumber, |  | ||||||
|                      appSettings.Company, |  | ||||||
|                      appSettings.ConnectionString, |  | ||||||
|                      appSettings.EcCharacterizationSi, |  | ||||||
|                      appSettings.EcMesaFileShareCharacterizationSi, |  | ||||||
|                      appSettings.EcMesaFileShareMetrologySi, |  | ||||||
|                      appSettings.EcMetrologySi, |  | ||||||
|                      appSettings.GitCommitSeven, |  | ||||||
|                      appSettings.InboundApiAllowedIPList, |  | ||||||
|                      appSettings.IqsColumns, |  | ||||||
|                      appSettings.IqsFileSegments, |  | ||||||
|                      appSettings.IqsKey, |  | ||||||
|                      appSettings.IqsRed, |  | ||||||
|                      appSettings.IqsYellow, |  | ||||||
|                      appSettings.IsDevelopment, |  | ||||||
|                      appSettings.IsStaging, |  | ||||||
|                      appSettings.MockRoot, |  | ||||||
|                      appSettings.MonAResource, |  | ||||||
|                      appSettings.MonASite, |  | ||||||
|                      appSettings.OpenInsightApplicationProgrammingInterface, |  | ||||||
|                      appSettings.TableToPath, |  | ||||||
|                      appSettings.URLs, |  | ||||||
|                      appSettings.WaferCounterDestinationDirectory, |  | ||||||
|                      appSettings.WaferCounterTwoFileSecondsWait, |  | ||||||
|                      appSettings.WorkingDirectoryName); |  | ||||||
|         Verify(result); |  | ||||||
|         return result; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } |  | ||||||
|  |  | ||||||
| [JsonSourceGenerationOptions(WriteIndented = true)] |  | ||||||
| [JsonSerializable(typeof(AppSettings))] |  | ||||||
| public partial class AppSettingsSourceGenerationContext : JsonSerializerContext |  | ||||||
| { |  | ||||||
| } | } | ||||||
							
								
								
									
										2
									
								
								Server/Models/Binder/.editorconfig
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,2 @@ | |||||||
|  | [*.cs] | ||||||
|  | csharp_preserve_single_line_statements = true | ||||||
							
								
								
									
										145
									
								
								Server/Models/Binder/AppSettings.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,145 @@ | |||||||
|  | using System.Text.Json; | ||||||
|  | using System.Text.Json.Serialization; | ||||||
|  |  | ||||||
|  | namespace OI.Metrology.Server.Models.Binder; | ||||||
|  |  | ||||||
|  | public class AppSettings | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     public string? ApiFileShare { get; set; } | ||||||
|  |     public string? ApiLoggingContentTypes { get; set; } | ||||||
|  |     public string? ApiLoggingPathPrefixes { get; set; } | ||||||
|  |     public string? ApiLogPath { get; set; } | ||||||
|  |     public string? ApiUrl { get; set; } | ||||||
|  |     public string? BuildNumber { get; set; } | ||||||
|  |     public string? Company { get; set; } | ||||||
|  |     public string? ConnectionString { get; set; } | ||||||
|  |     public string? EcCharacterizationSi { get; set; } | ||||||
|  |     public string? EcMesaFileShareCharacterizationSi { get; set; } | ||||||
|  |     public string? EcMesaFileShareMetrologySi { get; set; } | ||||||
|  |     public string? GitCommitSeven { get; set; } | ||||||
|  |     public string? InboundApiAllowedIPList { get; set; } | ||||||
|  |     public string? IqsColumns { get; set; } | ||||||
|  |     public string[]? IqsFileSegments { get; set; } | ||||||
|  |     public string? IqsKey { get; set; } | ||||||
|  |     public string? IqsRed { get; set; } | ||||||
|  |     public string? IqsYellow { get; set; } | ||||||
|  |     public bool? IsDevelopment { get; set; } | ||||||
|  |     public bool? IsStaging { get; set; } | ||||||
|  |     public string? MockRoot { get; set; } | ||||||
|  |     public string? MonAResource { get; set; } | ||||||
|  |     public string? MonASite { get; set; } | ||||||
|  |     public string? OpenInsightApplicationProgrammingInterface { get; set; } | ||||||
|  |     public Dictionary<string, string>? TableToPath { get; set; } | ||||||
|  |     public string? URLs { get; set; } | ||||||
|  |     public string? WaferCounterDestinationDirectory { get; set; } | ||||||
|  |     public int? WaferCounterTwoFileSecondsWait { get; set; } | ||||||
|  |     public string? WorkingDirectoryName { get; set; } | ||||||
|  |  | ||||||
|  |     public override string ToString() | ||||||
|  |     { | ||||||
|  |         string result = JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true }); | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private static void PreVerify(IConfigurationRoot configurationRoot, AppSettings? appSettings) | ||||||
|  |     { | ||||||
|  |         if (appSettings?.ApiFileShare is null) | ||||||
|  |         { | ||||||
|  |             List<string> paths = new(); | ||||||
|  |             foreach (IConfigurationProvider configurationProvider in configurationRoot.Providers) | ||||||
|  |             { | ||||||
|  |                 if (configurationProvider is not Microsoft.Extensions.Configuration.Json.JsonConfigurationProvider jsonConfigurationProvider) | ||||||
|  |                     continue; | ||||||
|  |                 if (jsonConfigurationProvider.Source.FileProvider is not Microsoft.Extensions.FileProviders.PhysicalFileProvider physicalFileProvider) | ||||||
|  |                     continue; | ||||||
|  |                 paths.Add(physicalFileProvider.Root); | ||||||
|  |             } | ||||||
|  |             throw new NotSupportedException($"Not found!{Environment.NewLine}{string.Join(Environment.NewLine, paths.Distinct())}"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private static Models.AppSettings Get(AppSettings? appSettings) | ||||||
|  |     { | ||||||
|  |         Models.AppSettings result; | ||||||
|  |         if (appSettings is null) throw new NullReferenceException(nameof(appSettings)); | ||||||
|  |         if (appSettings.ApiFileShare is null) throw new NullReferenceException(nameof(ApiFileShare)); | ||||||
|  |         if (appSettings.ApiLoggingContentTypes is null) throw new NullReferenceException(nameof(ApiLoggingContentTypes)); | ||||||
|  |         if (appSettings.ApiLoggingPathPrefixes is null) throw new NullReferenceException(nameof(ApiLoggingPathPrefixes)); | ||||||
|  |         if (appSettings.ApiLogPath is null) throw new NullReferenceException(nameof(ApiLogPath)); | ||||||
|  |         if (appSettings.ApiUrl is null) throw new NullReferenceException(nameof(ApiUrl)); | ||||||
|  |         if (appSettings.BuildNumber is null) throw new NullReferenceException(nameof(BuildNumber)); | ||||||
|  |         if (appSettings.Company is null) throw new NullReferenceException(nameof(Company)); | ||||||
|  |         if (appSettings.ConnectionString is null) throw new NullReferenceException(nameof(ConnectionString)); | ||||||
|  |         if (appSettings.EcCharacterizationSi is null) throw new NullReferenceException(nameof(EcCharacterizationSi)); | ||||||
|  |         if (appSettings.EcMesaFileShareCharacterizationSi is null) throw new NullReferenceException(nameof(EcMesaFileShareCharacterizationSi)); | ||||||
|  |         if (appSettings.EcMesaFileShareMetrologySi is null) throw new NullReferenceException(nameof(EcMesaFileShareMetrologySi)); | ||||||
|  |         if (appSettings.GitCommitSeven is null) throw new NullReferenceException(nameof(GitCommitSeven)); | ||||||
|  |         if (appSettings.InboundApiAllowedIPList is null) throw new NullReferenceException(nameof(InboundApiAllowedIPList)); | ||||||
|  |         if (appSettings.IqsColumns is null) throw new NullReferenceException(nameof(IqsColumns)); | ||||||
|  |         if (appSettings.IqsFileSegments is null) throw new NullReferenceException(nameof(IqsFileSegments)); | ||||||
|  |         if (appSettings.IqsKey is null) throw new NullReferenceException(nameof(IqsKey)); | ||||||
|  |         if (appSettings.IqsRed is null) throw new NullReferenceException(nameof(IqsRed)); | ||||||
|  |         if (appSettings.IqsYellow is null) throw new NullReferenceException(nameof(IqsYellow)); | ||||||
|  |         if (appSettings.IsDevelopment is null) throw new NullReferenceException(nameof(IsDevelopment)); | ||||||
|  |         if (appSettings.IsStaging is null) throw new NullReferenceException(nameof(IsStaging)); | ||||||
|  |         if (appSettings.MockRoot is null) throw new NullReferenceException(nameof(MockRoot)); | ||||||
|  |         if (appSettings.MonAResource is null) throw new NullReferenceException(nameof(MonAResource)); | ||||||
|  |         if (appSettings.MonASite is null) throw new NullReferenceException(nameof(MonASite)); | ||||||
|  |         if (appSettings.OpenInsightApplicationProgrammingInterface is null) throw new NullReferenceException(nameof(OpenInsightApplicationProgrammingInterface)); | ||||||
|  |         if (appSettings.URLs is null) throw new NullReferenceException(nameof(URLs)); | ||||||
|  |         if (appSettings.TableToPath is null) throw new NullReferenceException(nameof(TableToPath)); | ||||||
|  |         if (appSettings.WaferCounterDestinationDirectory is null) throw new NullReferenceException(nameof(WaferCounterDestinationDirectory)); | ||||||
|  |         if (appSettings.WaferCounterTwoFileSecondsWait is null) throw new NullReferenceException(nameof(WaferCounterTwoFileSecondsWait)); | ||||||
|  |         if (appSettings.WorkingDirectoryName is null) throw new NullReferenceException(nameof(WorkingDirectoryName)); | ||||||
|  |         result = new( | ||||||
|  |             appSettings.ApiFileShare, | ||||||
|  |             appSettings.ApiLoggingContentTypes, | ||||||
|  |             appSettings.ApiLoggingPathPrefixes, | ||||||
|  |             appSettings.ApiLogPath, | ||||||
|  |             appSettings.ApiUrl, | ||||||
|  |             appSettings.BuildNumber, | ||||||
|  |             appSettings.Company, | ||||||
|  |             appSettings.ConnectionString, | ||||||
|  |             appSettings.EcCharacterizationSi, | ||||||
|  |             appSettings.EcMesaFileShareCharacterizationSi, | ||||||
|  |             appSettings.EcMesaFileShareMetrologySi, | ||||||
|  |             appSettings.GitCommitSeven, | ||||||
|  |             appSettings.InboundApiAllowedIPList, | ||||||
|  |             appSettings.IqsColumns, | ||||||
|  |             appSettings.IqsFileSegments, | ||||||
|  |             appSettings.IqsKey, | ||||||
|  |             appSettings.IqsRed, | ||||||
|  |             appSettings.IqsYellow, | ||||||
|  |             appSettings.IsDevelopment.Value, | ||||||
|  |             appSettings.IsStaging.Value, | ||||||
|  |             appSettings.MockRoot, | ||||||
|  |             appSettings.MonAResource, | ||||||
|  |             appSettings.MonASite, | ||||||
|  |             appSettings.OpenInsightApplicationProgrammingInterface, | ||||||
|  |             appSettings.TableToPath, | ||||||
|  |             appSettings.URLs, | ||||||
|  |             appSettings.WaferCounterDestinationDirectory, | ||||||
|  |             appSettings.WaferCounterTwoFileSecondsWait.Value, | ||||||
|  |             appSettings.WorkingDirectoryName); | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public static Models.AppSettings Get(IConfigurationRoot configurationRoot) | ||||||
|  |     { | ||||||
|  |         Models.AppSettings result; | ||||||
|  | #pragma warning disable IL3050, IL2026 | ||||||
|  |         AppSettings? appSettings = configurationRoot.Get<AppSettings>(); | ||||||
|  | #pragma warning restore IL3050, IL2026 | ||||||
|  |         PreVerify(configurationRoot, appSettings); | ||||||
|  |         result = Get(appSettings); | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  | [JsonSourceGenerationOptions(WriteIndented = true)] | ||||||
|  | [JsonSerializable(typeof(AppSettings))] | ||||||
|  | internal partial class BinderAppSettingsSourceGenerationContext : JsonSerializerContext | ||||||
|  | { | ||||||
|  | } | ||||||
| @ -6,7 +6,6 @@ | |||||||
|         <SccLocalPath>SAK</SccLocalPath> |         <SccLocalPath>SAK</SccLocalPath> | ||||||
|     </PropertyGroup> |     </PropertyGroup> | ||||||
|     <PropertyGroup> |     <PropertyGroup> | ||||||
|         <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild> |  | ||||||
|         <ImplicitUsings>enable</ImplicitUsings> |         <ImplicitUsings>enable</ImplicitUsings> | ||||||
|         <IsPackable>false</IsPackable> |         <IsPackable>false</IsPackable> | ||||||
|         <Nullable>enable</Nullable> |         <Nullable>enable</Nullable> | ||||||
| @ -25,22 +24,22 @@ | |||||||
|         <Content Remove="compilerconfig.json" /> |         <Content Remove="compilerconfig.json" /> | ||||||
|     </ItemGroup> |     </ItemGroup> | ||||||
|     <ItemGroup> |     <ItemGroup> | ||||||
|         <PackageReference Include="Dapper" Version="2.1.44" /> |         <PackageReference Include="Dapper" Version="2.1.24" /> | ||||||
|         <PackageReference Include="EntityFramework" Version="6.5.1" /> |         <PackageReference Include="EntityFramework" Version="6.4.4" /> | ||||||
|         <PackageReference Include="jQuery" Version="3.7.1" /> |         <PackageReference Include="jQuery" Version="3.7.1" /> | ||||||
|         <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.10" /> |         <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.0" /> | ||||||
|         <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" /> |         <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" /> | ||||||
|         <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1" /> |         <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" /> | ||||||
|         <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.1" /> |         <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" /> | ||||||
|         <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" /> |         <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" /> | ||||||
|         <PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.1" /> |         <PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="8.0.0" /> | ||||||
|         <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" /> |         <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> | ||||||
|         <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" /> |         <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" /> | ||||||
|         <PackageReference Include="Microsoft.Extensions.Logging.EventLog" Version="8.0.1" /> |         <PackageReference Include="Microsoft.Extensions.Logging.EventLog" Version="8.0.0" /> | ||||||
|         <PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> |         <PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> | ||||||
|         <PackageReference Include="Swashbuckle.AspNetCore" Version="6.8.1" /> |         <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" /> | ||||||
|         <PackageReference Include="System.Data.SqlClient" Version="4.8.6" /> |         <PackageReference Include="System.Data.SqlClient" Version="4.8.5" /> | ||||||
|         <PackageReference Include="System.Drawing.Common" Version="8.0.10" /> |         <PackageReference Include="System.Drawing.Common" Version="8.0.0" /> | ||||||
|     </ItemGroup> |     </ItemGroup> | ||||||
|     <ItemGroup> |     <ItemGroup> | ||||||
|         <ProjectReference Include="..\Shared\OI.Metrology.Shared.csproj" /> |         <ProjectReference Include="..\Shared\OI.Metrology.Shared.csproj" /> | ||||||
|  | |||||||
| @ -43,7 +43,7 @@ public class Program | |||||||
|         (string assemblyName, WebApplicationOptions _) = Get(args); |         (string assemblyName, WebApplicationOptions _) = Get(args); | ||||||
|         WebApplicationBuilder webApplicationBuilder = WebApplication.CreateBuilder(args); |         WebApplicationBuilder webApplicationBuilder = WebApplication.CreateBuilder(args); | ||||||
|         _ = webApplicationBuilder.Configuration.AddUserSecrets<Program>(); |         _ = webApplicationBuilder.Configuration.AddUserSecrets<Program>(); | ||||||
|         AppSettings appSettings = AppSettings.Get(webApplicationBuilder.Configuration); |         AppSettings appSettings = Models.Binder.AppSettings.Get(webApplicationBuilder.Configuration); | ||||||
|         if (string.IsNullOrEmpty(appSettings.Company)) |         if (string.IsNullOrEmpty(appSettings.Company)) | ||||||
|             throw new Exception("Company name must have a value!"); |             throw new Exception("Company name must have a value!"); | ||||||
|         if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) |         if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName)) | ||||||
| @ -74,11 +74,12 @@ public class Program | |||||||
|             _ = webApplicationBuilder.Services.AddSingleton<IInfinityQSV2Repository, InfinityQSV2Repository>(); |             _ = webApplicationBuilder.Services.AddSingleton<IInfinityQSV2Repository, InfinityQSV2Repository>(); | ||||||
|             _ = webApplicationBuilder.Services.AddSingleton<IInfinityQSV3Repository, InfinityQSV3Repository>(); |             _ = webApplicationBuilder.Services.AddSingleton<IInfinityQSV3Repository, InfinityQSV3Repository>(); | ||||||
|             _ = webApplicationBuilder.Services.AddSingleton<IInfinityQSV4Repository, InfinityQSV4Repository>(); |             _ = webApplicationBuilder.Services.AddSingleton<IInfinityQSV4Repository, InfinityQSV4Repository>(); | ||||||
|  |             _ = webApplicationBuilder.Services.AddSingleton<IWaferCounterRepository, WaferCounterRepository>(); | ||||||
|             _ = webApplicationBuilder.Services.AddSingleton<IClientSettingsRepository>(_ => clientSettingsRepository); |             _ = webApplicationBuilder.Services.AddSingleton<IClientSettingsRepository>(_ => clientSettingsRepository); | ||||||
|             _ = webApplicationBuilder.Services.AddSingleton<IServiceShopOrderRepository, ServiceShopOrderRepository>(); |             _ = webApplicationBuilder.Services.AddSingleton<IServiceShopOrderRepository, ServiceShopOrderRepository>(); | ||||||
|             _ = webApplicationBuilder.Services.AddSingleton<ISpreadingResistanceProfileService, SpreadingResistanceProfileService>(); |             _ = webApplicationBuilder.Services.AddSingleton<ISpreadingResistanceProfileService, SpreadingResistanceProfileService>(); | ||||||
|             _ = webApplicationBuilder.Services.AddSingleton<IDbConnectionFactory, SQLDbConnectionFactory>(_ => sqlDbConnectionFactory); |             _ = webApplicationBuilder.Services.AddSingleton<IDbConnectionFactory, SQLDbConnectionFactory>(_ => sqlDbConnectionFactory); | ||||||
|             _ = webApplicationBuilder.Services.AddSingleton<IAppSettingsRepository<AppSettings>>(_ => appSettingsRepository); |             _ = webApplicationBuilder.Services.AddSingleton<IAppSettingsRepository<Models.Binder.AppSettings>>(_ => appSettingsRepository); | ||||||
|  |  | ||||||
|             _ = webApplicationBuilder.Services.AddSwaggerGen(); |             _ = webApplicationBuilder.Services.AddSwaggerGen(); | ||||||
|             _ = webApplicationBuilder.Services.AddSession(sessionOptions => |             _ = webApplicationBuilder.Services.AddSession(sessionOptions => | ||||||
|  | |||||||
| @ -3,20 +3,27 @@ using OI.Metrology.Shared.Models.Stateless; | |||||||
|  |  | ||||||
| namespace OI.Metrology.Server.Repository; | namespace OI.Metrology.Server.Repository; | ||||||
|  |  | ||||||
| public class AppSettingsRepository : IAppSettingsRepository<AppSettings> | public class AppSettingsRepository : IAppSettingsRepository<Models.Binder.AppSettings> | ||||||
| { | { | ||||||
|  |  | ||||||
|     private readonly AppSettings _AppSettings; |     private readonly AppSettings _AppSettings; | ||||||
|  |  | ||||||
|     public AppSettingsRepository(AppSettings appSettings) => _AppSettings = appSettings; |     public AppSettingsRepository(AppSettings appSettings) => _AppSettings = appSettings; | ||||||
|  |  | ||||||
|     internal AppSettings GetAppSettings() |     internal Models.Binder.AppSettings GetAppSettings() | ||||||
|     { |     { | ||||||
|         AppSettings result = _AppSettings; |         Models.Binder.AppSettings result = new() | ||||||
|  |         { | ||||||
|  |             BuildNumber = _AppSettings.BuildNumber, | ||||||
|  |             Company = _AppSettings.Company, | ||||||
|  |             GitCommitSeven = _AppSettings.GitCommitSeven, | ||||||
|  |             IsDevelopment = _AppSettings.IsDevelopment, | ||||||
|  |             IsStaging = _AppSettings.IsStaging, | ||||||
|  |         }; | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     AppSettings IAppSettingsRepository<AppSettings>.GetAppSettings() => GetAppSettings(); |     Models.Binder.AppSettings IAppSettingsRepository<Models.Binder.AppSettings>.GetAppSettings() => GetAppSettings(); | ||||||
|  |  | ||||||
|     internal string GetBuildNumberAndGitCommitSeven() |     internal string GetBuildNumberAndGitCommitSeven() | ||||||
|     { |     { | ||||||
| @ -38,8 +45,8 @@ public class AppSettingsRepository : IAppSettingsRepository<AppSettings> | |||||||
| #endif | #endif | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     string IAppSettingsRepository<AppSettings>.GetBuildNumberAndGitCommitSeven() => GetBuildNumberAndGitCommitSeven(); |     string IAppSettingsRepository<Models.Binder.AppSettings>.GetBuildNumberAndGitCommitSeven() => GetBuildNumberAndGitCommitSeven(); | ||||||
|  |  | ||||||
|     void IAppSettingsRepository<AppSettings>.VerifyConnectionStrings() => VerifyConnectionStrings(); |     void IAppSettingsRepository<Models.Binder.AppSettings>.VerifyConnectionStrings() => VerifyConnectionStrings(); | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -2,10 +2,7 @@ using OI.Metrology.Server.Models; | |||||||
| using OI.Metrology.Shared.DataModels; | using OI.Metrology.Shared.DataModels; | ||||||
| using OI.Metrology.Shared.Models; | using OI.Metrology.Shared.Models; | ||||||
| using OI.Metrology.Shared.Models.Stateless; | using OI.Metrology.Shared.Models.Stateless; | ||||||
| using System.Collections.ObjectModel; |  | ||||||
| using System.Data; |  | ||||||
| using System.Globalization; | using System.Globalization; | ||||||
| using System.Text; |  | ||||||
| using System.Text.Json; | using System.Text.Json; | ||||||
|  |  | ||||||
| namespace OI.Metrology.Server.Repository; | namespace OI.Metrology.Server.Repository; | ||||||
| @ -45,15 +42,15 @@ public class ExportRepository : IExportRepository | |||||||
|         List<NginxFileSystemSortable> results = new(); |         List<NginxFileSystemSortable> results = new(); | ||||||
|         Uri uri; |         Uri uri; | ||||||
|         string[] weeks = Get(); |         string[] weeks = Get(); | ||||||
|         ReadOnlyCollection<NginxFileSystemSortable> collection; |         List<NginxFileSystemSortable> nginxFileSystemSortableCollection; | ||||||
|         foreach (string weekYear in weeks) |         foreach (string weekYear in weeks) | ||||||
|         { |         { | ||||||
|             if (headerCommon.ID < 1) |             if (headerCommon.ID < 1) | ||||||
|                 uri = _FileShareRepository.Append(new Uri(_AppSettings.EcMesaFileShareMetrologySi), "Archive", "API", weekYear, $"-{headerCommon.PSN}", $"-{headerCommon.Reactor}", $"-{headerCommon.RDS}"); |                 uri = _FileShareRepository.Append(new Uri(_AppSettings.EcMesaFileShareMetrologySi), "Archive", "API", weekYear, $"-{headerCommon.PSN}", $"-{headerCommon.Reactor}", $"-{headerCommon.RDS}"); | ||||||
|             else |             else | ||||||
|                 uri = _FileShareRepository.Append(new Uri(_AppSettings.EcMesaFileShareMetrologySi), "Archive", "API", weekYear, $"-{headerCommon.PSN}", $"-{headerCommon.Reactor}", $"-{headerCommon.RDS}", $"-{headerCommon.ID}"); |                 uri = _FileShareRepository.Append(new Uri(_AppSettings.EcMesaFileShareMetrologySi), "Archive", "API", weekYear, $"-{headerCommon.PSN}", $"-{headerCommon.Reactor}", $"-{headerCommon.RDS}", $"-{headerCommon.ID}"); | ||||||
|             collection = _FileShareRepository.GetNginxFileSystemSortableCollection(httpClient, uri, endsWith); |             nginxFileSystemSortableCollection = _FileShareRepository.GetNginxFileSystemSortableCollection(httpClient, uri, endsWith); | ||||||
|             results.AddRange(collection); |             results.AddRange(nginxFileSystemSortableCollection); | ||||||
|         } |         } | ||||||
|         return results.OrderByDescending(l => l.DateTime).ToArray(); |         return results.OrderByDescending(l => l.DateTime).ToArray(); | ||||||
|     } |     } | ||||||
| @ -163,86 +160,4 @@ public class ExportRepository : IExportRepository | |||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     Result<DataTable> IExportRepository.GetExportData(IMetrologyRepository metrologyRepository, int toolTypeId, string? datebegin, string? dateend) |  | ||||||
|     { |  | ||||||
|         Result<DataTable>? r; |  | ||||||
|         DateTime dateEnd = dateend is null ? DateTime.Now : DateTime.Parse(dateend); |  | ||||||
|         DateTime dateBegin = datebegin is null ? dateEnd.AddMonths(-1) : DateTime.Parse(datebegin); |  | ||||||
|         ToolType tt = metrologyRepository.GetToolTypeByID(toolTypeId); |  | ||||||
|         if (string.IsNullOrEmpty(tt.ExportSPName)) |  | ||||||
|             throw new NullReferenceException(nameof(tt.ExportSPName)); |  | ||||||
|         DataTable dataTable = metrologyRepository.ExportData(tt.ExportSPName, dateBegin, dateEnd); |  | ||||||
|         r = new() |  | ||||||
|         { |  | ||||||
|             Results = dataTable, |  | ||||||
|             TotalRows = dataTable.Rows.Count, |  | ||||||
|         }; |  | ||||||
|         return r; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     protected static string FormatForCSV(string v) |  | ||||||
|     { |  | ||||||
|         StringBuilder result = new(v.Length + 2); |  | ||||||
|         bool doubleQuoted = false; |  | ||||||
|         if (v.StartsWith(' ') || v.EndsWith(' ') || v.Contains(',') || v.Contains('"')) |  | ||||||
|         { |  | ||||||
|             _ = result.Append('"'); |  | ||||||
|             doubleQuoted = true; |  | ||||||
|         } |  | ||||||
|         foreach (char c in v) |  | ||||||
|         { |  | ||||||
|             _ = c switch |  | ||||||
|             { |  | ||||||
|                 '\r' or '\n' => result.Append(' '), |  | ||||||
|                 '"' => result.Append("\"\""), |  | ||||||
|                 _ => result.Append(c), |  | ||||||
|             }; |  | ||||||
|         } |  | ||||||
|         if (doubleQuoted) |  | ||||||
|             _ = result.Append('"'); |  | ||||||
|         return result.ToString(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     protected static string GetColumnHeaders(DataTable dataTable) |  | ||||||
|     { |  | ||||||
|         StringBuilder result = new(); |  | ||||||
|         for (int i = 0; i < dataTable.Columns.Count; i++) |  | ||||||
|         { |  | ||||||
|             if (i > 0) |  | ||||||
|                 _ = result.Append(','); |  | ||||||
|             _ = result.Append(FormatForCSV(dataTable.Columns[i].ColumnName.TrimEnd('_'))); |  | ||||||
|         } |  | ||||||
|         return result.ToString(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     protected static string GetRowData(DataRow dr) |  | ||||||
|     { |  | ||||||
|         StringBuilder result = new(); |  | ||||||
|         for (int i = 0; i < dr.Table.Columns.Count; i++) |  | ||||||
|         { |  | ||||||
|             if (i > 0) |  | ||||||
|                 _ = result.Append(','); |  | ||||||
|             object v = dr[i]; |  | ||||||
|             if (v is not null && !Convert.IsDBNull(v)) |  | ||||||
|                 _ = result.Append(FormatForCSV(string.Concat(Convert.ToString(v)))); |  | ||||||
|         } |  | ||||||
|         return result.ToString(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     string IExportRepository.GetCSVExport(IMetrologyRepository metrologyRepository, int toolTypeId, string? datebegin, string? dateend) |  | ||||||
|     { |  | ||||||
|         string results; |  | ||||||
|         Result<DataTable> result; |  | ||||||
|         IExportRepository repository = this; |  | ||||||
|         result = repository.GetExportData(metrologyRepository, toolTypeId, datebegin, dateend); |  | ||||||
|         if (result.Results is null) |  | ||||||
|             throw new NullReferenceException(nameof(result.Results)); |  | ||||||
|         StringBuilder stringBuilder = new(); |  | ||||||
|         _ = stringBuilder.AppendLine(GetColumnHeaders(result.Results)); |  | ||||||
|         foreach (DataRow dr in result.Results.Rows) |  | ||||||
|             _ = stringBuilder.AppendLine(GetRowData(dr)); |  | ||||||
|         results = stringBuilder.ToString(); |  | ||||||
|         return results; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -1,9 +1,6 @@ | |||||||
| using OI.Metrology.Shared.DataModels; |  | ||||||
| using OI.Metrology.Shared.Models; | using OI.Metrology.Shared.Models; | ||||||
| using OI.Metrology.Shared.Models.Stateless; | using OI.Metrology.Shared.Models.Stateless; | ||||||
| using System.Collections.ObjectModel; |  | ||||||
| using System.Text.Json; | using System.Text.Json; | ||||||
| using System.Web; |  | ||||||
|  |  | ||||||
| namespace OI.Metrology.Server.Repository; | namespace OI.Metrology.Server.Repository; | ||||||
|  |  | ||||||
| @ -36,8 +33,6 @@ public class FileShareRepository : IFileShareRepository | |||||||
|         string directory = Path.GetDirectoryName(to) ?? throw new NullReferenceException(); |         string directory = Path.GetDirectoryName(to) ?? throw new NullReferenceException(); | ||||||
|         if (!Directory.Exists(directory)) |         if (!Directory.Exists(directory)) | ||||||
|             _ = Directory.CreateDirectory(directory); |             _ = Directory.CreateDirectory(directory); | ||||||
|         if (File.Exists(to)) |  | ||||||
|             File.Move(to, $"{to}.{DateTime.Now.Ticks}.old"); |  | ||||||
|         File.Move(from, to); |         File.Move(from, to); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @ -52,9 +47,7 @@ public class FileShareRepository : IFileShareRepository | |||||||
|     void IFileShareRepository.CopyFile(HttpClient httpClient, string from, string to) |     void IFileShareRepository.CopyFile(HttpClient httpClient, string from, string to) | ||||||
|     { |     { | ||||||
|         Uri uri = GetEndPoint(httpClient, "copy-file"); |         Uri uri = GetEndPoint(httpClient, "copy-file"); | ||||||
|         string encodedTo = HttpUtility.UrlEncode(to); |         Task<HttpResponseMessage> httpResponseMessage = httpClient.GetAsync(uri); | ||||||
|         string encodedFrom = HttpUtility.UrlEncode(from); |  | ||||||
|         Task<HttpResponseMessage> httpResponseMessage = httpClient.GetAsync($"{uri.OriginalString}?from={encodedFrom}&to={encodedTo}"); |  | ||||||
|         httpResponseMessage.Wait(); |         httpResponseMessage.Wait(); | ||||||
|         if (httpResponseMessage.Result.StatusCode != System.Net.HttpStatusCode.OK) |         if (httpResponseMessage.Result.StatusCode != System.Net.HttpStatusCode.OK) | ||||||
|             throw new Exception(httpResponseMessage.Result.StatusCode.ToString()); |             throw new Exception(httpResponseMessage.Result.StatusCode.ToString()); | ||||||
| @ -63,9 +56,16 @@ public class FileShareRepository : IFileShareRepository | |||||||
|     void IFileShareRepository.MoveFile(HttpClient httpClient, string from, string to) |     void IFileShareRepository.MoveFile(HttpClient httpClient, string from, string to) | ||||||
|     { |     { | ||||||
|         Uri uri = GetEndPoint(httpClient, "move-file"); |         Uri uri = GetEndPoint(httpClient, "move-file"); | ||||||
|         string encodedTo = HttpUtility.UrlEncode(to); |         Task<HttpResponseMessage> httpResponseMessage = httpClient.GetAsync(uri); | ||||||
|         string encodedFrom = HttpUtility.UrlEncode(from); |         httpResponseMessage.Wait(); | ||||||
|         Task<HttpResponseMessage> httpResponseMessage = httpClient.GetAsync($"{uri.OriginalString}?from={encodedFrom}&to={encodedTo}"); |         if (httpResponseMessage.Result.StatusCode != System.Net.HttpStatusCode.OK) | ||||||
|  |             throw new Exception(httpResponseMessage.Result.StatusCode.ToString()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void IFileShareRepository.FileWrite(HttpClient httpClient, string path, string contents) | ||||||
|  |     { | ||||||
|  |         Uri uri = GetEndPoint(httpClient, "file-write"); | ||||||
|  |         Task<HttpResponseMessage> httpResponseMessage = httpClient.GetAsync(uri); | ||||||
|         httpResponseMessage.Wait(); |         httpResponseMessage.Wait(); | ||||||
|         if (httpResponseMessage.Result.StatusCode != System.Net.HttpStatusCode.OK) |         if (httpResponseMessage.Result.StatusCode != System.Net.HttpStatusCode.OK) | ||||||
|             throw new Exception(httpResponseMessage.Result.StatusCode.ToString()); |             throw new Exception(httpResponseMessage.Result.StatusCode.ToString()); | ||||||
| @ -80,7 +80,7 @@ public class FileShareRepository : IFileShareRepository | |||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ReadOnlyCollection<NginxFileSystemSortable> IFileShareRepository.GetNginxFileSystemSortableCollection(HttpClient httpClient, Uri uri, string? endsWith) |     List<NginxFileSystemSortable> IFileShareRepository.GetNginxFileSystemSortableCollection(HttpClient httpClient, Uri uri, string? endsWith) | ||||||
|     { |     { | ||||||
|         List<NginxFileSystemSortable> results = new(); |         List<NginxFileSystemSortable> results = new(); | ||||||
|         Task<HttpResponseMessage> httpResponseMessage = httpClient.GetAsync(uri); |         Task<HttpResponseMessage> httpResponseMessage = httpClient.GetAsync(uri); | ||||||
| @ -99,13 +99,7 @@ public class FileShareRepository : IFileShareRepository | |||||||
|                 results.Add(nginxFileSystemSortable); |                 results.Add(nginxFileSystemSortable); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         return new(results); |         return results; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ReadOnlyCollection<CharacterizationInfo> IFileShareRepository.GetArchiveData(CharacterizationParameters archiveParameters) => |  | ||||||
|         throw new NotImplementedException(); |  | ||||||
|  |  | ||||||
|     ReadOnlyCollection<ToolTypeNameId> IFileShareRepository.GetEquipmentIds() => |  | ||||||
|         throw new NotImplementedException(); |  | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -31,42 +31,76 @@ public class InboundRepository : IInboundRepository | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     DataResponse IInboundRepository.Data(IMetrologyRepository metrologyRepository, IInboundDataService inboundDataService, string toolTypeName, JsonElement? jsonElement) |     // this is the main endpoint, it accepts a JSON message that contains both the header and data records together | ||||||
|  |     // tooltype is the ToolTypeName column from the ToolType table | ||||||
|  |     // JToken is how you can accept a JSON message without deserialization. | ||||||
|  |     // Using "string" doesn't work because ASP.NET Core will expect a json encoded string, not give you the actual string. | ||||||
|  |     DataResponse IInboundRepository.Data(IMetrologyRepository metrologyRepository, IInboundDataService inboundDataService, string tooltype, string? json) | ||||||
|     { |     { | ||||||
|         DataResponse result = new(); |         DataResponse result = new(); | ||||||
|         if (jsonElement is null || jsonElement.Value.ValueKind != JsonValueKind.Object) |         ToolType? toolType = metrologyRepository.GetToolTypeByName(tooltype); | ||||||
|             throw new Exception("Invalid body!"); |         if (toolType is null) | ||||||
|         string? json = jsonElement.ToString(); |             result.Errors.Add($"Invalid tool type: {tooltype}"); | ||||||
|         JToken jToken = (string.IsNullOrEmpty(json) ? JToken.Parse("{}") : JToken.Parse(json)) ?? |         else | ||||||
|             throw new Exception($"Invalid body: {json}"); |  | ||||||
|         ToolType toolType = metrologyRepository.GetToolTypeByName(toolTypeName) ?? |  | ||||||
|             throw new Exception($"Invalid tool type: {toolTypeName}"); |  | ||||||
|         List<ToolTypeMetadata> metaData = metrologyRepository.GetToolTypeMetadataByToolTypeID(toolType.ID).ToList(); |  | ||||||
|         inboundDataService.ValidateJSONFields(jToken, 0, metaData, result.Errors, result.Warnings); |  | ||||||
|         if (result.Errors.Count == 0) |  | ||||||
|         { |         { | ||||||
|             try |             InboundCommon? inboundCommon = string.IsNullOrEmpty(json) ? null : JsonSerializer.Deserialize<InboundCommon>(json); | ||||||
|  |             if (inboundCommon is null || string.IsNullOrEmpty(inboundCommon.ProcessDataStandardFormat)) | ||||||
|  |                 result.Errors.Add($"Invalid body: {json}"); | ||||||
|  |             else | ||||||
|             { |             { | ||||||
|                 result.HeaderID = inboundDataService.DoSQLInsert(jToken, toolType, metaData); |                 string? sourceDirectory = Path.GetDirectoryName(inboundCommon.ProcessDataStandardFormat); | ||||||
|                 result.Success = result.HeaderID > 0; |                 string? parentDirectory = Path.GetDirectoryName(sourceDirectory); | ||||||
|  |                 if (string.IsNullOrEmpty(sourceDirectory) || string.IsNullOrEmpty(parentDirectory) || !Directory.Exists(parentDirectory)) | ||||||
|  |                     result.Errors.Add($"Invalid body:path: <{inboundCommon.ProcessDataStandardFormat}>"); | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     JToken jToken = string.IsNullOrEmpty(json) ? JToken.Parse("{}") : JToken.Parse(json); | ||||||
|  |                     if (jToken is null) | ||||||
|  |                         result.Errors.Add($"Invalid body: {json}"); | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         List<ToolTypeMetadata> metaData = metrologyRepository.GetToolTypeMetadataByToolTypeID(toolType.ID).ToList(); | ||||||
|  |                         if (metaData is null) | ||||||
|  |                             result.Errors.Add($"Invalid metadata for tool type: {tooltype}"); | ||||||
|  |                         else | ||||||
|  |                         { | ||||||
|  |                             inboundDataService.ValidateJSONFields(jToken, 0, metaData, result.Errors, result.Warnings); | ||||||
|  |                             if (result.Errors.Count == 0) | ||||||
|  |                             { | ||||||
|  |                                 try | ||||||
|  |                                 { | ||||||
|  |                                     result.HeaderID = inboundDataService.DoSQLInsert(jToken, toolType, metaData); | ||||||
|  |                                     result.Success = result.HeaderID > 0; | ||||||
|  |                                     string? destinationDirectory = Path.Combine(parentDirectory, result.HeaderID.ToString()); | ||||||
|  |                                     Directory.Move(sourceDirectory, destinationDirectory); | ||||||
|  |                                 } | ||||||
|  |                                 catch (Exception ex) { result.Errors.Add(ex.Message); } | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|             catch (Exception ex) { result.Errors.Add(ex.Message); } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void IInboundRepository.AttachFile(IMetrologyRepository metrologyRepository, IAttachmentsService attachmentsService, string toolTypeName, Attachment? attachment) |     // this is the endpoint for attaching a field.  It is not JSON, it is form-data/multipart like an HTML form because that's the normal way. | ||||||
|  |     // header ID is the ID value from the Header table | ||||||
|  |     // datauniqueid is the Title value from the Data/Detail table | ||||||
|  |     string? IInboundRepository.AttachFile(IMetrologyRepository metrologyRepository, IAttachmentsService attachmentsService, string tooltype, long headerid, string datauniqueid, string fileName, object uploadedFile) | ||||||
|     { |     { | ||||||
|         if (attachment is null) |         string? result = null; | ||||||
|             throw new Exception("Invalid body!"); |         ToolType toolType = metrologyRepository.GetToolTypeByName(tooltype); | ||||||
|         ToolType toolType = metrologyRepository.GetToolTypeByName(toolTypeName) ?? |         if (toolType is null) | ||||||
|             throw new Exception($"Invalid tool type: {toolTypeName}"); |             result = $"Invalid tool type: {tooltype}"; | ||||||
|         if (string.IsNullOrWhiteSpace(attachment.DestinationFileName)) |         string filename = Path.GetFileName(fileName); | ||||||
|             throw new Exception("Empty filename"); |         if (string.IsNullOrWhiteSpace(filename)) | ||||||
|         if (attachment.DestinationFileName.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0) |             result = "Empty filename"; | ||||||
|             throw new Exception("Invalid filename"); |         if (filename.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0) | ||||||
|         attachmentsService.SaveAttachment(toolType, attachment); |             result = "Invalid filename"; | ||||||
|  |         if (result is null && toolType is not null) | ||||||
|  |             attachmentsService.SaveAttachment(toolType, headerid, datauniqueid, filename, uploadedFile); | ||||||
|  |         return result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -6,6 +6,7 @@ using OI.Metrology.Shared.Repositories; | |||||||
| using System.Collections.ObjectModel; | using System.Collections.ObjectModel; | ||||||
| using System.Data; | using System.Data; | ||||||
| using System.Data.Common; | using System.Data.Common; | ||||||
|  | using System.Reflection; | ||||||
| using System.Text; | using System.Text; | ||||||
| using System.Text.Json; | using System.Text.Json; | ||||||
|  |  | ||||||
| @ -37,139 +38,124 @@ public class InfinityQSV4Repository : IInfinityQSV4Repository | |||||||
|  |  | ||||||
|     string IInfinityQSV4Repository.GetCommandText(string subGroupId) |     string IInfinityQSV4Repository.GetCommandText(string subGroupId) | ||||||
|     { // cSpell:disable |     { // cSpell:disable | ||||||
|         List<string> results = []; |         StringBuilder result = new(); | ||||||
|         if (string.IsNullOrEmpty(subGroupId)) |         if (string.IsNullOrEmpty(subGroupId)) | ||||||
|             throw new ArgumentException(null, nameof(subGroupId)); |             throw new ArgumentException(null, nameof(subGroupId)); | ||||||
|         results.Add(" select "); |         _ = result | ||||||
|         results.Add("       sd.f_sgrp sd_sgrp, "); |             .AppendLine(" select ") | ||||||
|         results.Add("       sd.f_tsno sd_tsno, "); |             .AppendLine("       sd.f_sgrp sd_sgrp, ") | ||||||
|         results.Add("       dd.f_dsgp dd_dsgp, "); |             .AppendLine("       sd.f_tsno sd_tsno, ") | ||||||
|         results.Add("       dg.f_name gd_name, "); |             .AppendLine("       dd.f_dsgp dd_dsgp, ") | ||||||
|         results.Add("       dd.f_name dd_name "); |             .AppendLine("       dg.f_name gd_name, ") | ||||||
|         results.Add(" from [SPCEPIWORLD].[dbo].[SGRP_DSC] sd "); |             .AppendLine("       dd.f_name dd_name ") | ||||||
|         results.Add(" join [SPCEPIWORLD].[dbo].[DESC_DAT] dd "); |             .AppendLine(" from [SPCEPIWORLD].[dbo].[SGRP_DSC] sd ") | ||||||
|         results.Add("   on sd.f_dsgp = dd.f_dsgp "); |             .AppendLine(" join [SPCEPIWORLD].[dbo].[DESC_DAT] dd ") | ||||||
|         results.Add("  and sd.f_desc = dd.f_desc "); |             .AppendLine("   on sd.f_dsgp = dd.f_dsgp ") | ||||||
|         results.Add(" join [SPCEPIWORLD].[dbo].[DESC_GRP] dg "); |             .AppendLine("  and sd.f_desc = dd.f_desc ") | ||||||
|         results.Add("   on dd.f_dsgp = dg.f_dsgp "); |             .AppendLine(" join [SPCEPIWORLD].[dbo].[DESC_GRP] dg ") | ||||||
|         results.Add($" where sd.f_sgrp = {subGroupId} "); |             .AppendLine("   on dd.f_dsgp = dg.f_dsgp "); | ||||||
|         results.Add(" for json path "); |         _ = result.Append(" where sd.f_sgrp = ").Append(subGroupId).AppendLine(" "); | ||||||
|         return string.Join(' ', results); |         _ = result.AppendLine(" for json path "); | ||||||
|  |         return result.ToString(); | ||||||
|     } // cSpell:enable |     } // cSpell:enable | ||||||
|  |  | ||||||
|     string IInfinityQSV4Repository.GetCommandText(string? subGroupId, string? process, string? job, string? part, string? lot, string? dateTime) |     string IInfinityQSV4Repository.GetCommandText(string? subGroupId, string? process, string? job, string? part, string? lot, string? dateTime) | ||||||
|     { // cSpell:disable |     { // cSpell:disable | ||||||
|         List<string> results = []; |         StringBuilder result = new(); | ||||||
|         const string dateTimeFormat = "yyyy-MM-dd HH:mm:ss"; |         const string dateTimeFormat = "yyyy-MM-dd HH:mm:ss"; | ||||||
|         if (!string.IsNullOrEmpty(dateTime) && (dateTime.Contains('-') || dateTime.Contains(' ') || dateTime.Contains(':')) && dateTime.Length != dateTimeFormat.Length) |         if (!string.IsNullOrEmpty(dateTime) && (dateTime.Contains('-') || dateTime.Contains(' ') || dateTime.Contains(':')) && dateTime.Length != dateTimeFormat.Length) | ||||||
|             throw new ArgumentException(null, nameof(dateTime)); |             throw new ArgumentException(null, nameof(dateTime)); | ||||||
|         results.Add(" select case when iq.sl_loos is null then 0 else iq.sl_loos end + "); |         _ = result | ||||||
|         results.Add("        case when iq.sl_uoos is null then 0 else iq.sl_uoos end + "); |             .AppendLine(" select case when iq.sl_loos is null then 0 else iq.sl_loos end + ") | ||||||
|         results.Add("        iq.ev_count as iq_sum, "); |             .AppendLine("        case when iq.sl_uoos is null then 0 else iq.sl_uoos end + ") | ||||||
|         results.Add("        iq.sl_aflag, "); |             .AppendLine("        iq.ev_count as iq_sum, ") | ||||||
|         results.Add("        iq.sl_loos, "); |             .AppendLine("        iq.sl_aflag, ") | ||||||
|         results.Add("        iq.sl_uoos, "); |             .AppendLine("        iq.sl_loos, ") | ||||||
|         results.Add("        iq.se_sgrp, "); |             .AppendLine("        iq.sl_uoos, ") | ||||||
|         results.Add("        iq.se_sgtm, "); |             .AppendLine("        iq.se_sgrp, ") | ||||||
|         results.Add("        iq.se_tsno, "); |             .AppendLine("        iq.se_sgtm, ") | ||||||
|         results.Add("        iq.td_test, "); |             .AppendLine("        iq.se_tsno, ") | ||||||
|         results.Add("        iq.pr_name, "); |             .AppendLine("        iq.td_test, ") | ||||||
|         results.Add("        iq.jd_name, "); |             .AppendLine("        iq.pr_name, ") | ||||||
|         results.Add("        iq.pl_name, "); |             .AppendLine("        iq.jd_name, ") | ||||||
|         results.Add("        iq.pd_name, "); |             .AppendLine("        iq.pl_name, ") | ||||||
|         results.Add("        iq.td_name, "); |             .AppendLine("        iq.pd_name, ") | ||||||
|         results.Add("        iq.se_val, "); |             .AppendLine("        iq.td_name, ") | ||||||
|         results.Add("        iq.sl_eflag, "); |             .AppendLine("        iq.se_val, ") | ||||||
|         results.Add("        iq.sl_scal, "); |             .AppendLine("        iq.sl_eflag, ") | ||||||
|         results.Add("        iq.sl_sls, "); |             .AppendLine("        iq.sl_scal, ") | ||||||
|         results.Add("        iq.sl_usl "); |             .AppendLine("        iq.sl_sls, ") | ||||||
|         results.Add(" from ( "); |             .AppendLine("        iq.sl_usl ") | ||||||
|         results.Add(" select "); |             .AppendLine(" from ( ") | ||||||
|         results.Add("       se.f_sgrp se_sgrp, "); |             .AppendLine(" select ") | ||||||
|         results.Add("       se.f_sgtm se_sgtm, "); |             .AppendLine("       se.f_sgrp se_sgrp, ") | ||||||
|         results.Add("       se.f_tsno se_tsno, "); |             .AppendLine("       se.f_sgtm se_sgtm, ") | ||||||
|         results.Add("       se.f_val se_val, "); |             .AppendLine("       se.f_tsno se_tsno, ") | ||||||
|         results.Add("       pr.f_name pr_name, "); |             .AppendLine("       se.f_val se_val, ") | ||||||
|         results.Add("       jd.f_name jd_name, "); |             .AppendLine("       pr.f_name pr_name, ") | ||||||
|         results.Add("       pl.f_name pl_name, "); |             .AppendLine("       jd.f_name jd_name, ") | ||||||
|         results.Add("       pd.f_name pd_name, "); |             .AppendLine("       pl.f_name pl_name, ") | ||||||
|         results.Add("       td.f_test td_test, "); |             .AppendLine("       pd.f_name pd_name, ") | ||||||
|         results.Add("       td.f_name td_name, "); |             .AppendLine("       td.f_test td_test, ") | ||||||
|         results.Add("       sl.f_eflag sl_eflag, "); |             .AppendLine("       td.f_name td_name, ") | ||||||
|         results.Add("       sl.f_aflag sl_aflag, "); |             .AppendLine("       sl.f_eflag sl_eflag, ") | ||||||
|         results.Add("       sl.f_scal sl_scal, "); |             .AppendLine("       sl.f_aflag sl_aflag, ") | ||||||
|         results.Add("       sl.f_lsl sl_sls, "); |             .AppendLine("       sl.f_scal sl_scal, ") | ||||||
|         results.Add("       sl.f_usl sl_usl, "); |             .AppendLine("       sl.f_lsl sl_sls, ") | ||||||
|         results.Add("       case when sl.f_aflag is null or sl.f_aflag = 0 then null else "); |             .AppendLine("       sl.f_usl sl_usl, ") | ||||||
|         results.Add("         case when round(se.f_val, sl.F_scal, 1) < sl.f_lsl then 1 else 0 end "); |             .AppendLine("       case when sl.f_aflag is null or sl.f_aflag = 0 then null else ") | ||||||
|         results.Add("       end as sl_loos, "); |             .AppendLine("         case when round(se.f_val, sl.F_scal, 1) < sl.f_lsl then 1 else 0 end ") | ||||||
|         results.Add("       case when sl.f_aflag is null or sl.f_aflag = 0 then null else "); |             .AppendLine("       end as sl_loos, ") | ||||||
|         results.Add("         case when round(se.f_val, sl.F_scal, 1) > sl.f_usl then 1 else 0 end "); |             .AppendLine("       case when sl.f_aflag is null or sl.f_aflag = 0 then null else ") | ||||||
|         results.Add("       end as sl_uoos, "); |             .AppendLine("         case when round(se.f_val, sl.F_scal, 1) > sl.f_usl then 1 else 0 end ") | ||||||
|         results.Add("       (select count(ev.f_evnt) "); |             .AppendLine("       end as sl_uoos, ") | ||||||
|         results.Add("       from [spcepiworld].[dbo].[evnt_inf] ev "); |             .AppendLine("       (select count(ev.f_evnt) ") | ||||||
|         results.Add("       where ev.f_prcs = pr.f_prcs "); |             .AppendLine("       from [spcepiworld].[dbo].[evnt_inf] ev ") | ||||||
|         results.Add("         and ev.f_part = pd.f_part "); |             .AppendLine("       where ev.f_prcs = pr.f_prcs ") | ||||||
|         results.Add("         and ev.f_sgtm = se.f_sgtm "); |             .AppendLine("         and ev.f_part = pd.f_part ") | ||||||
|         results.Add("       ) ev_count "); |             .AppendLine("         and ev.f_sgtm = se.f_sgtm ") | ||||||
|         results.Add(" from [spcepiworld].[dbo].[sgrp_ext] se "); |             .AppendLine("       ) ev_count ") | ||||||
|         results.Add(" join [spcepiworld].[dbo].[prcs_dat] pr "); |             .AppendLine(" from [spcepiworld].[dbo].[sgrp_ext] se ") | ||||||
|         results.Add("   on se.f_prcs = pr.f_prcs "); |             .AppendLine(" join [spcepiworld].[dbo].[prcs_dat] pr ") | ||||||
|         results.Add(" join [spcepiworld].[dbo].[job_dat] jd "); |             .AppendLine("   on se.f_prcs = pr.f_prcs ") | ||||||
|         results.Add("   on se.f_job = jd.f_job "); |             .AppendLine(" join [spcepiworld].[dbo].[job_dat] jd ") | ||||||
|         results.Add(" join [spcepiworld].[dbo].[part_lot] pl "); |             .AppendLine("   on se.f_job = jd.f_job ") | ||||||
|         results.Add("   on se.f_lot = pl.f_lot "); |             .AppendLine(" join [spcepiworld].[dbo].[part_lot] pl ") | ||||||
|         results.Add(" join [spcepiworld].[dbo].[part_dat] pd "); |             .AppendLine("   on se.f_lot = pl.f_lot ") | ||||||
|         results.Add("   on se.f_part = pd.f_part "); |             .AppendLine(" join [spcepiworld].[dbo].[part_dat] pd ") | ||||||
|         results.Add(" join [spcepiworld].[dbo].[test_dat] td "); |             .AppendLine("   on se.f_part = pd.f_part ") | ||||||
|         results.Add("   on se.f_test = td.f_test "); |             .AppendLine(" join [spcepiworld].[dbo].[test_dat] td ") | ||||||
|         results.Add(" left join [spcepiworld].[dbo].[spec_lim] sl "); |             .AppendLine("   on se.f_test = td.f_test ") | ||||||
|         results.Add("   on se.f_part = sl.f_part "); |             .AppendLine(" left join [spcepiworld].[dbo].[spec_lim] sl ") | ||||||
|         results.Add("  and se.f_test = sl.f_test "); |             .AppendLine("   on se.f_part = sl.f_part ") | ||||||
|         results.Add(" where se.f_flag = 0 "); |             .AppendLine("  and se.f_test = sl.f_test ") | ||||||
|         results.Add("   and (sl.f_prcs is null or se.f_prcs = sl.f_prcs or sl.f_prcs = 0) "); |             .AppendLine(" where se.f_flag = 0 ") | ||||||
|  |             .AppendLine("   and (sl.f_prcs is null or se.f_prcs = sl.f_prcs or sl.f_prcs = 0) "); | ||||||
|         if (!string.IsNullOrEmpty(subGroupId)) |         if (!string.IsNullOrEmpty(subGroupId)) | ||||||
|             results.Add($"   and se.f_sgrp = {subGroupId.Split(" ")[0]} "); |             _ = result.Append("   and se.f_sgrp = ").Append(subGroupId.Split(" ")[0]).AppendLine("  "); | ||||||
|         if (!string.IsNullOrEmpty(process)) |         if (!string.IsNullOrEmpty(process)) | ||||||
|             results.Add($"   and pr.f_name = '{process}' "); |             _ = result.Append("   and pr.f_name = '").Append(process).AppendLine("' "); | ||||||
|         if (!string.IsNullOrEmpty(part)) |         if (!string.IsNullOrEmpty(part)) | ||||||
|             results.Add($"   and pd.f_name = '{part}' "); |             _ = result.Append("   and pd.f_name = '").Append(part).AppendLine("' "); | ||||||
|         if (!string.IsNullOrEmpty(job)) |         if (!string.IsNullOrEmpty(job)) | ||||||
|             results.Add($"   and jd.f_name = '{job}' "); |             _ = result.Append("   and jd.f_name = '").Append(job).AppendLine("' "); | ||||||
|         if (!string.IsNullOrEmpty(lot)) |         if (!string.IsNullOrEmpty(lot)) | ||||||
|             results.Add($"   and pl.f_name = '{lot}' "); |             _ = result.Append("   and pl.f_name = '").Append(lot).AppendLine("' "); | ||||||
|         if (!string.IsNullOrEmpty(dateTime) && (dateTime.Contains('-') || dateTime.Contains(' ') || dateTime.Contains(':'))) |         if (!string.IsNullOrEmpty(dateTime) && (dateTime.Contains('-') || dateTime.Contains(' ') || dateTime.Contains(':'))) | ||||||
|             results.Add($"   and dateadd(HH, -7, (dateadd(SS, convert(bigint, se.f_sgtm), '19700101'))) = '{dateTime}' "); |             _ = result.Append("   and dateadd(HH, -7, (dateadd(SS, convert(bigint, se.f_sgtm), '19700101'))) = '").Append(dateTime).AppendLine("' "); | ||||||
|         results.Add(" ) as iq "); |         _ = result.AppendLine(" ) as iq ") | ||||||
|         results.Add(" order by iq.sl_loos + iq.sl_uoos + iq.ev_count desc, "); |                   .AppendLine(" order by iq.sl_loos + iq.sl_uoos + iq.ev_count desc, ") | ||||||
|         results.Add("          iq.sl_aflag desc, "); |                   .AppendLine("          iq.sl_aflag desc, ") | ||||||
|         results.Add("          iq.se_sgrp, "); |                   .AppendLine("          iq.se_sgrp, ") | ||||||
|         results.Add("          iq.se_tsno, "); |                   .AppendLine("          iq.se_tsno, ") | ||||||
|         results.Add("          iq.td_test "); |                   .AppendLine("          iq.td_test ") | ||||||
|         results.Add("   for json path "); |                   .AppendLine("   for json path "); | ||||||
|         return string.Join(' ', results); |         return result.ToString(); | ||||||
|     } // cSpell:enable |     } // cSpell:enable | ||||||
|  |  | ||||||
|     private JsonElement[] GetAllReactorsAsJsonElementElement() |  | ||||||
|     { |  | ||||||
|         JsonElement[]? results; |  | ||||||
|         HttpClient httpClient = _HttpClientFactory.CreateClient(); |  | ||||||
|         Task<string> task = httpClient.GetStringAsync($"{_OpenInsightApplicationProgrammingInterface}/reactors"); |  | ||||||
|         task.Wait(); |  | ||||||
|         JsonElement? jsonElement = JsonSerializer.Deserialize<JsonElement>(task.Result); |  | ||||||
|         if (jsonElement is null) |  | ||||||
|             throw new NullReferenceException(nameof(jsonElement)); |  | ||||||
|         string json = jsonElement.Value.EnumerateObject().First().Value.ToString(); |  | ||||||
|         results = JsonSerializer.Deserialize<JsonElement[]>(json); |  | ||||||
|         if (results is null) |  | ||||||
|             throw new NullReferenceException(nameof(results)); |  | ||||||
|         return results; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static StringBuilder GetForJsonPath(IDbConnectionFactory dbConnectionFactory, string commandText, bool useIqsConnection) |     private static StringBuilder GetForJsonPath(IDbConnectionFactory dbConnectionFactory, string commandText, bool useIqsConnection) | ||||||
|     { |     { | ||||||
|         StringBuilder stringBuilder = new(); |         StringBuilder stringBuilder = new(); | ||||||
|         File.WriteAllText("../../.sql", commandText); |  | ||||||
|         using DbConnection dbConnection = dbConnectionFactory.GetDbConnection(useIqsConnection); |         using DbConnection dbConnection = dbConnectionFactory.GetDbConnection(useIqsConnection); | ||||||
|         DbCommand dbCommand = dbConnection.CreateCommand(); |         DbCommand dbCommand = dbConnection.CreateCommand(); | ||||||
|         dbCommand.CommandText = commandText; |         dbCommand.CommandText = commandText; | ||||||
| @ -179,50 +165,6 @@ public class InfinityQSV4Repository : IInfinityQSV4Repository | |||||||
|         return stringBuilder; |         return stringBuilder; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private void GetOI(InfinityQSV4 infinityQSV4) |  | ||||||
|     { |  | ||||||
|         IInfinityQSV4Repository infinityQSV4Repository = this; |  | ||||||
|         if (string.IsNullOrEmpty(infinityQSV4.Part)) |  | ||||||
|             throw new ArgumentException(nameof(infinityQSV4.Part)); |  | ||||||
|         string json = infinityQSV4Repository.GetProductionSpecification(infinityQSV4.Part); |  | ||||||
|         File.WriteAllText("../../.json", json); |  | ||||||
|         ProdSpecRoot? prodSpec = JsonSerializer.Deserialize(json, ProdSpecRootSourceGenerationContext.Default.ProdSpecRoot); |  | ||||||
|         if (prodSpec is null) |  | ||||||
|         { |  | ||||||
|             if (prodSpec is null) |  | ||||||
|             { } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static List<string> Convert(int[] night) |  | ||||||
|     { |  | ||||||
|         List<string> results = new(); |  | ||||||
|         foreach (int reactor in night) |  | ||||||
|             results.Add(reactor.ToString()); |  | ||||||
|         return results; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private ReadOnlyDictionary<int, Reactor> GetReactorsMatchingType(string? reactTypeFilter) |  | ||||||
|     { |  | ||||||
|         Dictionary<int, Reactor> results = new(); |  | ||||||
|         string json; |  | ||||||
|         Reactor? reactor; |  | ||||||
|         JsonElement[]? jsonElements = GetAllReactorsAsJsonElementElement(); |  | ||||||
|         foreach (JsonElement jsonElement in jsonElements) |  | ||||||
|         { |  | ||||||
|             json = jsonElement.EnumerateObject().First().Value.ToString(); |  | ||||||
|             if (reactTypeFilter is not null && !json.Contains(reactTypeFilter)) |  | ||||||
|                 continue; |  | ||||||
|             try |  | ||||||
|             { reactor = JsonSerializer.Deserialize(json, ReactorSourceGenerationContext.Default.Reactor); } |  | ||||||
|             catch (Exception) { reactor = null; } |  | ||||||
|             if (reactor is null || (reactTypeFilter is not null && reactor.ReactType != reactTypeFilter)) |  | ||||||
|                 continue; |  | ||||||
|             results.Add(reactor.ReactorNo, reactor); |  | ||||||
|         } |  | ||||||
|         return new(results); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static InfinityQSV4 GetInfinityQSV4(IDbConnectionFactory dbConnectionFactory, IInfinityQSV4Repository infinityQSV4Repository, string subGroupId) |     private static InfinityQSV4 GetInfinityQSV4(IDbConnectionFactory dbConnectionFactory, IInfinityQSV4Repository infinityQSV4Repository, string subGroupId) | ||||||
|     { |     { | ||||||
|         InfinityQSV4 result; |         InfinityQSV4 result; | ||||||
| @ -293,32 +235,33 @@ public class InfinityQSV4Repository : IInfinityQSV4Repository | |||||||
|  |  | ||||||
|     string IInfinityQSV4Repository.GetCommandText(InfinityQSV4 infinityQSV4) |     string IInfinityQSV4Repository.GetCommandText(InfinityQSV4 infinityQSV4) | ||||||
|     { // cSpell:disable |     { // cSpell:disable | ||||||
|         List<string> results = []; |         StringBuilder result = new(); | ||||||
|         if (string.IsNullOrEmpty(infinityQSV4.Process)) |         if (string.IsNullOrEmpty(infinityQSV4.Process)) | ||||||
|             throw new ArgumentException(nameof(infinityQSV4.Process)); |             throw new ArgumentException(nameof(infinityQSV4.Process)); | ||||||
|         if (string.IsNullOrEmpty(infinityQSV4.Part)) |         if (string.IsNullOrEmpty(infinityQSV4.Part)) | ||||||
|             throw new ArgumentException(nameof(infinityQSV4.Part)); |             throw new ArgumentException(nameof(infinityQSV4.Part)); | ||||||
|         results.Add(" select "); |         _ = result | ||||||
|         results.Add(" ev.f_evnt [ev_evnt], "); |             .AppendLine(" select ") | ||||||
|         results.Add(" ev.f_sgtm [ev_sgtm], "); |             .AppendLine(" ev.f_evnt [ev_evnt], ") | ||||||
|         results.Add(" dateadd(HH, -7, (dateadd(SS, convert(bigint, ev.f_sgtm), '19700101'))) [ev_utc7], "); |             .AppendLine(" ev.f_sgtm [ev_sgtm], ") | ||||||
|         results.Add(" pr.f_name [pr_name], "); |             .AppendLine(" dateadd(HH, -7, (dateadd(SS, convert(bigint, ev.f_sgtm), '19700101'))) [ev_utc7], ") | ||||||
|         results.Add(" pd.f_name [pd_name], "); |             .AppendLine(" pr.f_name [pr_name], ") | ||||||
|         results.Add(" td.f_test [td_test], "); |             .AppendLine(" pd.f_name [pd_name], ") | ||||||
|         results.Add(" td.f_name [td_name], "); |             .AppendLine(" td.f_test [td_test], ") | ||||||
|         results.Add(" ev.f_name [ev_name] "); |             .AppendLine(" td.f_name [td_name], ") | ||||||
|         results.Add(" from [spcepiworld].[dbo].[evnt_inf] ev "); |             .AppendLine(" ev.f_name [ev_name] ") | ||||||
|         results.Add(" join [spcepiworld].[dbo].[prcs_dat] pr "); |             .AppendLine(" from [spcepiworld].[dbo].[evnt_inf] ev ") | ||||||
|         results.Add(" on ev.f_prcs = pr.f_prcs "); |             .AppendLine(" join [spcepiworld].[dbo].[prcs_dat] pr ") | ||||||
|         results.Add(" join [spcepiworld].[dbo].[part_dat] pd "); |             .AppendLine(" on ev.f_prcs = pr.f_prcs ") | ||||||
|         results.Add(" on ev.f_part = pd.f_part "); |             .AppendLine(" join [spcepiworld].[dbo].[part_dat] pd ") | ||||||
|         results.Add(" join [spcepiworld].[dbo].[test_dat] td "); |             .AppendLine(" on ev.f_part = pd.f_part ") | ||||||
|         results.Add(" on ev.f_test = td.f_test "); |             .AppendLine(" join [spcepiworld].[dbo].[test_dat] td ") | ||||||
|         results.Add($" where pr.f_name = '{infinityQSV4.Process}' "); |             .AppendLine(" on ev.f_test = td.f_test ") | ||||||
|         results.Add($" and pd.f_name = '{infinityQSV4.Part}' "); |             .Append(" where pr.f_name = '").Append(infinityQSV4.Process).AppendLine("' ") | ||||||
|         results.Add($" and ev.f_sgtm = {infinityQSV4.SubGroupDateTime} "); |             .Append(" and pd.f_name = '").Append(infinityQSV4.Part).AppendLine("' ") | ||||||
|         results.Add(" for json path "); |             .Append(" and ev.f_sgtm = ").Append(infinityQSV4.SubGroupDateTime).AppendLine(" ") | ||||||
|         return string.Join(' ', results); |             .AppendLine(" for json path "); | ||||||
|  |         return result.ToString(); | ||||||
|     } // cSpell:enable |     } // cSpell:enable | ||||||
|  |  | ||||||
|     Result<InfinityQSV4[]> IInfinityQSV4Repository.GetHeader(string subGroupId) |     Result<InfinityQSV4[]> IInfinityQSV4Repository.GetHeader(string subGroupId) | ||||||
| @ -347,27 +290,28 @@ public class InfinityQSV4Repository : IInfinityQSV4Repository | |||||||
|  |  | ||||||
|     string IInfinityQSV4Repository.GetCommandText(string process, string? part) |     string IInfinityQSV4Repository.GetCommandText(string process, string? part) | ||||||
|     { // cSpell:disable |     { // cSpell:disable | ||||||
|         List<string> results = []; |         StringBuilder result = new(); | ||||||
|         if (string.IsNullOrEmpty(process)) |         if (string.IsNullOrEmpty(process)) | ||||||
|             throw new ArgumentException(null, nameof(process)); |             throw new ArgumentException(null, nameof(process)); | ||||||
|         if (string.IsNullOrEmpty(part)) |         if (string.IsNullOrEmpty(part)) | ||||||
|             throw new ArgumentException(null, nameof(part)); |             throw new ArgumentException(null, nameof(part)); | ||||||
|         results.Add(" select [f_mean] as ProcessMean, "); |         _ = result | ||||||
|         results.Add("        [f_sp] as ProcessSigma "); |             .AppendLine(" select [f_mean] as ProcessMean, ") | ||||||
|         results.Add(" from [spcepiworld].[dbo].[test_dat] test "); |             .AppendLine("        [f_sp] as ProcessSigma ") | ||||||
|         results.Add(" join [spcepiworld].[dbo].[ctrl_lim] ctrl "); |             .AppendLine(" from [spcepiworld].[dbo].[test_dat] test ") | ||||||
|         results.Add("   on test.f_test = ctrl.f_test "); |             .AppendLine(" join [spcepiworld].[dbo].[ctrl_lim] ctrl ") | ||||||
|         results.Add("   and test.f_tsgp = 1104848523 /* Product Data */ "); |             .AppendLine("   on test.f_test = ctrl.f_test ") | ||||||
|         results.Add(" join [spcepiworld].[dbo].[part_dat] part "); |             .AppendLine("   and test.f_tsgp = 1104848523 /* Product Data */ ") | ||||||
|         results.Add("   on part.f_part = ctrl.f_part "); |             .AppendLine(" join [spcepiworld].[dbo].[part_dat] part ") | ||||||
|         results.Add("  and ctrl.f_test = 1125073605 /* Average Sum of Defects */ "); |             .AppendLine("   on part.f_part = ctrl.f_part ") | ||||||
|         results.Add(" join [spcepiworld].[dbo].[prcs_dat] process "); |             .AppendLine("  and ctrl.f_test = 1125073605 /* Average Sum of Defects */ ") | ||||||
|         results.Add("   on process.f_prcs = ctrl.f_prcs "); |             .AppendLine(" join [spcepiworld].[dbo].[prcs_dat] process ") | ||||||
|         results.Add(" where test.f_name = 'Average Sum of Defects' "); |             .AppendLine("   on process.f_prcs = ctrl.f_prcs ") | ||||||
|         results.Add($"       and process.f_name = '{process}' "); |             .AppendLine(" where test.f_name = 'Average Sum of Defects' ") | ||||||
|         results.Add($"       and part.f_name = '{part}' "); |             .Append("       and process.f_name = '").Append(process).AppendLine("' ") | ||||||
|         results.Add(" for json path; "); |             .Append("       and part.f_name = '").Append(part).AppendLine("' ") | ||||||
|         return string.Join(' ', results); |             .AppendLine(" for json path; "); | ||||||
|  |         return result.ToString(); | ||||||
|     } // cSpell:enable |     } // cSpell:enable | ||||||
|  |  | ||||||
|     string IInfinityQSV4Repository.GetProductDataAverageSumOfDefectsProcessMeanProcessSigma(string process, string? recipe) |     string IInfinityQSV4Repository.GetProductDataAverageSumOfDefectsProcessMeanProcessSigma(string process, string? recipe) | ||||||
| @ -389,56 +333,102 @@ public class InfinityQSV4Repository : IInfinityQSV4Repository | |||||||
|         return result.ToString(); |         return result.ToString(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     private JsonElement[] GetAllReactorsAsJsonElementElement() | ||||||
|  |     { | ||||||
|  |         JsonElement[]? results; | ||||||
|  |         HttpClient httpClient = _HttpClientFactory.CreateClient(); | ||||||
|  |         Task<string> task = httpClient.GetStringAsync($"{_OpenInsightApplicationProgrammingInterface}/reactors"); | ||||||
|  |         task.Wait(); | ||||||
|  |         JsonElement? jsonElement = JsonSerializer.Deserialize<JsonElement>(task.Result); | ||||||
|  |         if (jsonElement is null) | ||||||
|  |             throw new NullReferenceException(nameof(jsonElement)); | ||||||
|  |         string json = jsonElement.Value.EnumerateObject().First().Value.ToString(); | ||||||
|  |         results = JsonSerializer.Deserialize<JsonElement[]>(json); | ||||||
|  |         if (results is null) | ||||||
|  |             throw new NullReferenceException(nameof(results)); | ||||||
|  |         return results; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private ReadOnlyDictionary<int, Reactor> GetReactorsMatchingType(string? reactTypeFilter) | ||||||
|  |     { | ||||||
|  |         Dictionary<int, Reactor> results = new(); | ||||||
|  |         string json; | ||||||
|  |         Reactor? reactor; | ||||||
|  |         JsonElement[]? jsonElements = GetAllReactorsAsJsonElementElement(); | ||||||
|  |         foreach (JsonElement jsonElement in jsonElements) | ||||||
|  |         { | ||||||
|  |             json = jsonElement.EnumerateObject().First().Value.ToString(); | ||||||
|  |             if (reactTypeFilter is not null && !json.Contains(reactTypeFilter)) | ||||||
|  |                 continue; | ||||||
|  |             try | ||||||
|  |             { reactor = JsonSerializer.Deserialize(json, ReactorSourceGenerationContext.Default.Reactor); } | ||||||
|  |             catch (Exception) { reactor = null; } | ||||||
|  |             if (reactor is null || (reactTypeFilter is not null && reactor.ReactType != reactTypeFilter)) | ||||||
|  |                 continue; | ||||||
|  |             results.Add(reactor.ReactorNo, reactor); | ||||||
|  |         } | ||||||
|  |         return new(results); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     string IInfinityQSV4Repository.GetCommandText(List<string> eppReactorNumbers) |     string IInfinityQSV4Repository.GetCommandText(List<string> eppReactorNumbers) | ||||||
|     { // cSpell:disable |     { // cSpell:disable | ||||||
|         List<string> results = []; |         StringBuilder result = new(); | ||||||
|         results.Add(" select se.f_sgrp, "); |         _ = result | ||||||
|         results.Add("        dateadd(HH, -7, (dateadd(SS, convert(bigint, se.f_sgrp), '19700101'))) date_time, "); |             .AppendLine(" select se.f_sgrp, ") | ||||||
|         results.Add("        iq.pr_name, "); |             .AppendLine("        dateadd(HH, -7, (dateadd(SS, convert(bigint, se.f_sgrp), '19700101'))) date_time, ") | ||||||
|         results.Add("        iq.pd_name, "); |             .AppendLine("        iq.pr_name, ") | ||||||
|         results.Add("        max(case "); |             .AppendLine("        iq.pd_name, ") | ||||||
|         results.Add("         when td.f_test = 1104769646 "); |             .AppendLine("        max(case ") | ||||||
|         results.Add("         then se.f_val "); |             .AppendLine("         when td.f_test = 1104769646 ") | ||||||
|         results.Add("         else null "); |             .AppendLine("         then se.f_val ") | ||||||
|         results.Add("         end) as iq_value, "); |             .AppendLine("         else null ") | ||||||
|         results.Add("        max(case "); |             .AppendLine("         end) as iq_value, ") | ||||||
|         results.Add("         when td.f_test = 1312288843 "); |             .AppendLine("        max(case ") | ||||||
|         results.Add("         then se.f_val else null "); |             .AppendLine("         when td.f_test = 1312288843 ") | ||||||
|         results.Add("         end) as iq_temp_offset_percent "); |             .AppendLine("         then se.f_val else null ") | ||||||
|         results.Add(" from ( "); |             .AppendLine("         end) as iq_temp_offset_percent ") | ||||||
|         results.Add(" select "); |             .AppendLine(" from ( ") | ||||||
|         results.Add("       max(se.f_sgrp) se_max_sgrp, "); |             .AppendLine(" select ") | ||||||
|         results.Add("       se.f_test se_test, "); |             .AppendLine("       max(se.f_sgrp) se_max_sgrp, ") | ||||||
|         results.Add("       pr.f_name pr_name, "); |             .AppendLine("       se.f_test se_test, ") | ||||||
|         results.Add("       pd.f_name pd_name "); |             .AppendLine("       pr.f_name pr_name, ") | ||||||
|         results.Add(" from [spcepiworld].[dbo].[sgrp_ext] se "); |             .AppendLine("       pd.f_name pd_name ") | ||||||
|         results.Add(" join [spcepiworld].[dbo].[prcs_dat] pr "); |             .AppendLine(" from [spcepiworld].[dbo].[sgrp_ext] se ") | ||||||
|         results.Add("   on se.f_prcs = pr.f_prcs "); |             .AppendLine(" join [spcepiworld].[dbo].[prcs_dat] pr ") | ||||||
|         results.Add(" join [spcepiworld].[dbo].[part_dat] pd "); |             .AppendLine("   on se.f_prcs = pr.f_prcs ") | ||||||
|         results.Add("   on se.f_part = pd.f_part "); |             .AppendLine(" join [spcepiworld].[dbo].[part_dat] pd ") | ||||||
|         results.Add(" where se.f_flag = 0 "); |             .AppendLine("   on se.f_part = pd.f_part ") | ||||||
|         results.Add($"   and pr.f_name in ({string.Join(',', eppReactorNumbers)}) "); |             .AppendLine(" where se.f_flag = 0 ") | ||||||
|         results.Add("   and pd.f_name = '1090 - Full Load' "); |             .Append("   and pr.f_name in (").Append(string.Join(',', eppReactorNumbers)).AppendLine(") ") | ||||||
|         results.Add("   and se.f_test in (1104769646, 1312288843) "); |             .AppendLine("   and pd.f_name = '1090 - Full Load' ") | ||||||
|         results.Add(" group by se.f_test, "); |             .AppendLine("   and se.f_test in (1104769646, 1312288843) ") | ||||||
|         results.Add("          pr.f_name, "); |             .AppendLine(" group by se.f_test, ") | ||||||
|         results.Add("          pd.f_name "); |             .AppendLine("          pr.f_name, ") | ||||||
|         results.Add(" ) as iq "); |             .AppendLine("          pd.f_name ") | ||||||
|         results.Add(" join [spcepiworld].[dbo].[sgrp_ext] se "); |             .AppendLine(" ) as iq ") | ||||||
|         results.Add("   on iq.se_max_sgrp = se.f_sgrp "); |             .AppendLine(" join [spcepiworld].[dbo].[sgrp_ext] se ") | ||||||
|         results.Add(" join [spcepiworld].[dbo].[test_dat] td "); |             .AppendLine("   on iq.se_max_sgrp = se.f_sgrp ") | ||||||
|         results.Add("   on iq.se_test = td.f_test "); |             .AppendLine(" join [spcepiworld].[dbo].[test_dat] td ") | ||||||
|         results.Add("  and se.f_test = td.f_test "); |             .AppendLine("   on iq.se_test = td.f_test ") | ||||||
|         results.Add(" where se.f_flag = 0 "); |             .AppendLine("  and se.f_test = td.f_test ") | ||||||
|         results.Add("   and td.f_test in (1104769646, 1312288843) "); |             .AppendLine(" where se.f_flag = 0 ") | ||||||
|         results.Add(" group by se.f_sgrp, "); |             .AppendLine("   and td.f_test in (1104769646, 1312288843) ") | ||||||
|         results.Add("          iq.pr_name, "); |             .AppendLine(" group by se.f_sgrp, ") | ||||||
|         results.Add("          iq.pd_name "); |             .AppendLine("          iq.pr_name, ") | ||||||
|         results.Add(" order by iq.pr_name "); |             .AppendLine("          iq.pd_name ") | ||||||
|         results.Add(" for json path; "); |             .AppendLine(" order by iq.pr_name ") | ||||||
|         return string.Join(' ', results); |             .AppendLine(" for json path; "); | ||||||
|  |         return result.ToString(); | ||||||
|     } // cSpell:enable |     } // cSpell:enable | ||||||
|  |  | ||||||
|  |     private static List<string> Convert(int[] night) | ||||||
|  |     { | ||||||
|  |         List<string> results = new(); | ||||||
|  |         foreach (int reactor in night) | ||||||
|  |             results.Add(reactor.ToString()); | ||||||
|  |         return results; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     List<string[]> IInfinityQSV4Repository.GetEpiProTempVerificationRows(int[] night) |     List<string[]> IInfinityQSV4Repository.GetEpiProTempVerificationRows(int[] night) | ||||||
|     { |     { | ||||||
|         List<string[]>? results; |         List<string[]>? results; | ||||||
| @ -648,55 +638,171 @@ public class InfinityQSV4Repository : IInfinityQSV4Repository | |||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private static string GetCommandText(string process, string? part, int? test) |     private void GetOI(InfinityQSV4 infinityQSV4) | ||||||
|     { // cSpell:disable |  | ||||||
|         List<string> results = []; |  | ||||||
|         if (string.IsNullOrEmpty(process)) |  | ||||||
|             throw new ArgumentException(null, nameof(process)); |  | ||||||
|         if (string.IsNullOrEmpty(part)) |  | ||||||
|             throw new ArgumentException(null, nameof(part)); |  | ||||||
|         if (test is null) |  | ||||||
|             throw new ArgumentException(null, nameof(test)); |  | ||||||
|         results.Add(" select se_max_sgrp, se.f_val se_value "); |  | ||||||
|         results.Add(" from ( "); |  | ||||||
|         results.Add("   select "); |  | ||||||
|         results.Add("         max(se.f_sgrp) se_max_sgrp "); |  | ||||||
|         results.Add("   from [spcepiworld].[dbo].[sgrp_ext] se "); |  | ||||||
|         results.Add("   join [spcepiworld].[dbo].[prcs_dat] pr "); |  | ||||||
|         results.Add("     on se.f_prcs = pr.f_prcs "); |  | ||||||
|         results.Add("   join [spcepiworld].[dbo].[part_dat] pd "); |  | ||||||
|         results.Add("     on se.f_part = pd.f_part "); |  | ||||||
|         results.Add("   where se.f_flag = 0 "); |  | ||||||
|         results.Add("     and se.f_tsno = 1 "); |  | ||||||
|         results.Add($"     and pr.f_name = '{process}' "); |  | ||||||
|         results.Add($"     and pd.f_name = '{part}' "); |  | ||||||
|         results.Add($"     and se.f_test = {test.Value} "); |  | ||||||
|         results.Add(" ) as iq "); |  | ||||||
|         results.Add(" join [spcepiworld].[dbo].[sgrp_ext] se "); |  | ||||||
|         results.Add("   on se_max_sgrp = se.f_sgrp "); |  | ||||||
|         results.Add(" where se.f_flag = 0 "); |  | ||||||
|         results.Add("   and se.f_tsno = 1 "); |  | ||||||
|         results.Add($"   and se.f_test = {test.Value} "); |  | ||||||
|         results.Add(" for json path "); |  | ||||||
|         return string.Join(' ', results); |  | ||||||
|     } // cSpell:enable |  | ||||||
|  |  | ||||||
|     string IInfinityQSV4Repository.GetLastGroupIdWithValue(string process, string? part, int? test) |  | ||||||
|     { |     { | ||||||
|         StringBuilder result; |         IInfinityQSV4Repository infinityQSV4Repository = this; | ||||||
|  |         if (string.IsNullOrEmpty(infinityQSV4.Part)) | ||||||
|  |             throw new ArgumentException(nameof(infinityQSV4.Part)); | ||||||
|  |         string json = infinityQSV4Repository.GetProductionSpecification(infinityQSV4.Part); | ||||||
|  |         ProdSpecRoot? prodSpec = JsonSerializer.Deserialize(json, ProdSpecRootSourceGenerationContext.Default.ProdSpecRoot); | ||||||
|  |         if (prodSpec is null) | ||||||
|  |         { | ||||||
|  |             if (prodSpec is null) | ||||||
|  |             { } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private static Record? GetValue(AppSettings appSettings, string line) | ||||||
|  |     { | ||||||
|  |         Record? result; | ||||||
|  |         string[] attributes = line.Split('>'); | ||||||
|  |         if (attributes.Length != 3) | ||||||
|  |             result = null; | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             string[] text = attributes[1].Replace(appSettings.IqsRed, "red").Replace(appSettings.IqsYellow, "Yellow").Split($"</{line[1]}{line[2]}"); | ||||||
|  |             if (text.Length != 2) | ||||||
|  |                 result = null; | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 string[] attributeValues = attributes[0].Split('"'); | ||||||
|  |                 if (attributeValues.Length != 3) | ||||||
|  |                     result = new(null, text[0]); | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     result = new(attributeValues[1], text[0]); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private static ReadOnlyCollection<Record> GetRecords(AppSettings appSettings, string[] lines) | ||||||
|  |     { | ||||||
|  |         Record? record; | ||||||
|  |         List<Record> results = new(); | ||||||
|  |         List<string> checkColumns = new(); | ||||||
|  |         foreach (string line in lines) | ||||||
|  |         { | ||||||
|  |             if (line.StartsWith("<th")) | ||||||
|  |             { | ||||||
|  |                 record = GetValue(appSettings, line); | ||||||
|  |                 if (record is null) | ||||||
|  |                     continue; | ||||||
|  |                 checkColumns.Add(record.Text); | ||||||
|  |             } | ||||||
|  |             if (line.StartsWith("<td")) | ||||||
|  |             { | ||||||
|  |                 record = GetValue(appSettings, line); | ||||||
|  |                 if (record is null) | ||||||
|  |                     continue; | ||||||
|  |                 results.Add(record); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         if (string.Join(',', checkColumns) != appSettings.IqsColumns) | ||||||
|  |             throw new NotSupportedException("Columns don't match!"); | ||||||
|  |         return new(results); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private static List<Dictionary<string, Record>> GetCollection(string columns, ReadOnlyCollection<Record> records) | ||||||
|  |     { | ||||||
|  |         string[] columnNames = columns.Split(','); | ||||||
|  |         List<Dictionary<string, Record>> collection = new(); | ||||||
|  |         Dictionary<string, Record> keyValuePairs; | ||||||
|  |         for (int i = 0; i < records.Count; i++) | ||||||
|  |         { | ||||||
|  |             keyValuePairs = new(); | ||||||
|  |             for (int j = 0; j < columnNames.Length; j++) | ||||||
|  |             { | ||||||
|  |                 keyValuePairs.Add(columnNames[j], records[i]); | ||||||
|  |                 i++; | ||||||
|  |             } | ||||||
|  |             i--; | ||||||
|  |             collection.Add(keyValuePairs); | ||||||
|  |         } | ||||||
|  |         return collection; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private static Dictionary<string, List<string>> GetResults(AppSettings appSettings, List<Dictionary<string, Record>> collection) | ||||||
|  |     { | ||||||
|  |         Dictionary<string, List<string>> results = new(); | ||||||
|  |         Record record; | ||||||
|  |         List<string>? colors; | ||||||
|  |         foreach (Dictionary<string, Record> keyValuePairs in collection) | ||||||
|  |         { | ||||||
|  |             record = keyValuePairs[appSettings.IqsKey]; | ||||||
|  |             if (!results.TryGetValue(record.Text, out colors)) | ||||||
|  |             { | ||||||
|  |                 results.Add(record.Text, new()); | ||||||
|  |                 if (!results.TryGetValue(record.Text, out colors)) | ||||||
|  |                     throw new Exception(); | ||||||
|  |             } | ||||||
|  |             if (record.Color is null) | ||||||
|  |                 continue; | ||||||
|  |             colors.Add(record.Color.Replace(appSettings.IqsRed, "red").Replace(appSettings.IqsYellow, "Yellow")); | ||||||
|  |         } | ||||||
|  |         foreach (KeyValuePair<string, List<string>> keyValuePair in results) | ||||||
|  |             keyValuePair.Value.Sort(); | ||||||
|  |         return results; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private void FileFindReplaceAndSave(FileInfo fileInfo, string value) | ||||||
|  |     { | ||||||
|  |         string lines = value.Replace(_AppSettings.IqsRed, "red").Replace(_AppSettings.IqsYellow, "Yellow"); | ||||||
|  |         File.WriteAllText(fileInfo.FullName, lines); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private static string GetWwwRootDirectory() | ||||||
|  |     { | ||||||
|  |         string result; | ||||||
|  |         Assembly assembly = Assembly.GetExecutingAssembly(); | ||||||
|  |         string? assemblyName = assembly.GetName()?.Name; | ||||||
|  |         if (string.IsNullOrEmpty(assemblyName)) | ||||||
|  |             throw new Exception(); | ||||||
|  |         result = Path.Combine(AppContext.BaseDirectory, "wwwroot"); | ||||||
|  |         if (!Directory.Exists(result)) | ||||||
|  |             _ = Directory.CreateDirectory(result); | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     Dictionary<string, List<string>> IInfinityQSV4Repository.GetEngineeringSpcReview() | ||||||
|  |     { | ||||||
|  |         Dictionary<string, List<string>>? results; | ||||||
|         if (!string.IsNullOrEmpty(_MockRoot)) |         if (!string.IsNullOrEmpty(_MockRoot)) | ||||||
|         { |         { | ||||||
|             string json = File.ReadAllText(Path.Combine(string.Concat(AppContext.BaseDirectory, _MockRoot), $"{_RepositoryName}-{nameof(IInfinityQSV4Repository.GetLastGroupIdWithValue)}.json")); |             string json = File.ReadAllText(Path.Combine(string.Concat(AppContext.BaseDirectory, _MockRoot), $"{_RepositoryName}-{nameof(IInfinityQSV4Repository.GetEngineeringSpcReview)}.json")); | ||||||
|             result = new(json); |             results = JsonSerializer.Deserialize<Dictionary<string, List<string>>>(json); | ||||||
|  |             if (results is null) | ||||||
|  |                 throw new NullReferenceException(nameof(results)); | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             string commandText = GetCommandText(process, part, test); |             string wwwRootDirectory = GetWwwRootDirectory(); | ||||||
|             result = GetForJsonPath(_DBConnectionFactory, commandText, useIqsConnection: false); |             HttpClient httpClient = _HttpClientFactory.CreateClient(); | ||||||
|             if (result.Length == 0) |             FileInfo localFileInfo = new(Path.Combine(wwwRootDirectory, _AppSettings.IqsFileSegments.Last())); | ||||||
|                 result = new("{}"); |             Uri uri = _FileShareRepository.Append(new Uri(_AppSettings.EcMesaFileShareCharacterizationSi), _AppSettings.IqsFileSegments[0..^1]); | ||||||
|  |             List<NginxFileSystemSortable> nginxFileSystemSortableCollection = _FileShareRepository.GetNginxFileSystemSortableCollection(httpClient, uri, ".html"); | ||||||
|  |             if (!localFileInfo.Exists && nginxFileSystemSortableCollection.Count == 0) | ||||||
|  |                 results = new(); | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 string[] lines; | ||||||
|  |                 HttpResponseMessage httpResponseMessage = _FileShareRepository.ReadFile(httpClient, nginxFileSystemSortableCollection[0].Uri); | ||||||
|  |                 Task<string> value = httpResponseMessage.Content.ReadAsStringAsync(); | ||||||
|  |                 value.Wait(); | ||||||
|  |                 if (localFileInfo.Exists && localFileInfo.LastWriteTime == nginxFileSystemSortableCollection[0].DateTime) | ||||||
|  |                     lines = File.ReadAllLines(localFileInfo.FullName); | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     FileFindReplaceAndSave(localFileInfo, value.Result); | ||||||
|  |                     lines = value.Result.Split("\r\n"); | ||||||
|  |                 } | ||||||
|  |                 ReadOnlyCollection<Record> records = GetRecords(_AppSettings, lines); | ||||||
|  |                 List<Dictionary<string, Record>> collection = GetCollection(_AppSettings.IqsColumns, records); | ||||||
|  |                 results = GetResults(_AppSettings, collection); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         return result.ToString(); |         return results; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -16,7 +16,6 @@ namespace OI.Metrology.Server.Repositories; | |||||||
|  |  | ||||||
| public class MetrologyRepository : IMetrologyRepository | public class MetrologyRepository : IMetrologyRepository | ||||||
| { | { | ||||||
|  |  | ||||||
|     private readonly string _MockRoot; |     private readonly string _MockRoot; | ||||||
|     private readonly string _RepositoryName; |     private readonly string _RepositoryName; | ||||||
|     private readonly IMemoryCache _MemoryCache; |     private readonly IMemoryCache _MemoryCache; | ||||||
| @ -33,8 +32,7 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|     protected DbProviderFactory GetDbProviderFactory(IDbConnection conn) => |     protected DbProviderFactory GetDbProviderFactory(IDbConnection conn) => | ||||||
|         DbProviderFactories.GetFactory(conn.GetType().Namespace); |         DbProviderFactories.GetFactory(conn.GetType().Namespace); | ||||||
|  |  | ||||||
|     internal static TransactionScope StartTransaction() => |     internal static TransactionScope StartTransaction() => new(); | ||||||
|         new(); |  | ||||||
|  |  | ||||||
|     protected void CacheItem(string key, object v) |     protected void CacheItem(string key, object v) | ||||||
|     { |     { | ||||||
| @ -58,7 +56,7 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|         return r; |         return r; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ToolType IMetrologyRepository.GetToolTypeByName(string name) |     internal ToolType GetToolTypeByName(string name) | ||||||
|     { |     { | ||||||
|         ToolType cached; |         ToolType cached; | ||||||
|         string cacheKey = "GetToolTypeByName_" + name; |         string cacheKey = "GetToolTypeByName_" + name; | ||||||
| @ -109,7 +107,7 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|         return r; |         return r; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     long IMetrologyRepository.InsertToolDataJSON(JToken jsonrow, long headerId, List<ToolTypeMetadata> metaData, string tableName) |     internal long InsertToolDataJSON(JToken jsonrow, long headerId, List<ToolTypeMetadata> metaData, string tableName) | ||||||
|     { |     { | ||||||
|         long r = -1; |         long r = -1; | ||||||
|         using (DbConnection conn = _DBConnectionFactory.GetDbConnection()) |         using (DbConnection conn = _DBConnectionFactory.GetDbConnection()) | ||||||
| @ -117,8 +115,7 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|             bool isHeader = headerId <= 0; |             bool isHeader = headerId <= 0; | ||||||
|  |  | ||||||
|             // get fields from metadata |             // get fields from metadata | ||||||
|             List<ToolTypeMetadata> fields = metaData.Where(md => |             List<ToolTypeMetadata> fields = metaData.Where(md => md.Header == isHeader).ToList(); | ||||||
|                 md.Header == isHeader).ToList(); |  | ||||||
|  |  | ||||||
|             // maps ApiName to ColumnName |             // maps ApiName to ColumnName | ||||||
|             Dictionary<string, string> fieldmap = new(); |             Dictionary<string, string> fieldmap = new(); | ||||||
| @ -158,8 +155,7 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 // Find the container field in the json |                 // Find the container field in the json | ||||||
|                 JProperty contJP = jsonrow.Children<JProperty>().Where(c => |                 JProperty contJP = jsonrow.Children<JProperty>().Where(c => string.Equals(c.Name.Trim(), containerField, StringComparison.OrdinalIgnoreCase)).SingleOrDefault(); | ||||||
|                     string.Equals(c.Name.Trim(), containerField, StringComparison.OrdinalIgnoreCase)).SingleOrDefault(); |  | ||||||
|  |  | ||||||
|                 if ((contJP is not null) && (contJP.Value is JArray array)) |                 if ((contJP is not null) && (contJP.Value is JArray array)) | ||||||
|                 { |                 { | ||||||
| @ -186,7 +182,7 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|         _ = cmd.Parameters.Add(p); |         _ = cmd.Parameters.Add(p); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private long InsertRowFromJSON( |     protected long InsertRowFromJSON( | ||||||
|         IDbConnection conn, |         IDbConnection conn, | ||||||
|         string tableName, |         string tableName, | ||||||
|         JToken jsonrow, |         JToken jsonrow, | ||||||
| @ -266,7 +262,7 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|         return Convert.ToInt64(o); |         return Convert.ToInt64(o); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     DataTable IMetrologyRepository.ExportData(string spName, DateTime startTime, DateTime endTime) |     internal DataTable ExportData(string spName, DateTime startTime, DateTime endTime) | ||||||
|     { |     { | ||||||
|         DataTable dt = new(); |         DataTable dt = new(); | ||||||
|         DateTime endTimeLocal = endTime.ToLocalTime(); |         DateTime endTimeLocal = endTime.ToLocalTime(); | ||||||
| @ -316,7 +312,7 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|         return sb.ToString(); |         return sb.ToString(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     DataTable IMetrologyRepository.GetHeaders(int toolTypeId, string? startTime, string? endTime, int? pageNo, int? pageSize, long? headerId, out long totalRecords) |     internal DataTable GetHeaders(int toolTypeId, string? startTime, string? endTime, int? pageNo, int? pageSize, long? headerId, out long totalRecords) | ||||||
|     { |     { | ||||||
|         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); |         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); | ||||||
|  |  | ||||||
| @ -328,8 +324,7 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|             StringBuilder sb = new(); |             StringBuilder sb = new(); | ||||||
|             _ = sb.Append( |             _ = sb.Append( | ||||||
|                 FormDynamicSelectQuery( |                 FormDynamicSelectQuery( | ||||||
|                     md.Where(m => |                     md.Where(m => m.Header == true).ToList(), | ||||||
|                         m.Header == true).ToList(), |  | ||||||
|                     tt.HeaderTableName) |                     tt.HeaderTableName) | ||||||
|             ); |             ); | ||||||
|  |  | ||||||
| @ -406,7 +401,7 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|         return dt; |         return dt; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     DataTable IMetrologyRepository.GetData(int toolTypeId, long headerid) |     internal DataTable GetData(int toolTypeId, long headerid) | ||||||
|     { |     { | ||||||
|         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); |         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); | ||||||
|  |  | ||||||
| @ -418,9 +413,7 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|             StringBuilder sb = new(); |             StringBuilder sb = new(); | ||||||
|             _ = sb.Append( |             _ = sb.Append( | ||||||
|                 FormDynamicSelectQuery( |                 FormDynamicSelectQuery( | ||||||
|                     md.Where(m => |                     md.Where(m => m.Header == false).OrderBy(m => m.GridDisplayOrder).ToList(), | ||||||
|                         m.Header == false).OrderBy(m => |  | ||||||
|                         m.GridDisplayOrder).ToList(), |  | ||||||
|                     tt.DataTableName) |                     tt.DataTableName) | ||||||
|             ); |             ); | ||||||
|  |  | ||||||
| @ -499,32 +492,17 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|         return dt; |         return dt; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     Guid IMetrologyRepository.GetHeaderAttachmentID(int toolTypeId, long headerId) |     internal Guid GetHeaderAttachmentID(int toolTypeId, long headerId) | ||||||
|     { |  | ||||||
|         Guid result; |  | ||||||
|         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); |  | ||||||
|  |  | ||||||
|         using DbConnection conn = _DBConnectionFactory.GetDbConnection(); |  | ||||||
|         string sql = |  | ||||||
|             $"SELECT AttachmentID FROM [{tt.HeaderTableName}] WHERE ID = @HeaderID"; |  | ||||||
|         result = conn.ExecuteScalar<Guid>(sql, param: new { HeaderID = headerId }); |  | ||||||
|         return result; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void IMetrologyRepository.SetHeaderAttachmentID(int toolTypeId, long headerId, string attachmentId) |  | ||||||
|     { |     { | ||||||
|         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); |         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); | ||||||
|  |  | ||||||
|         using DbConnection conn = _DBConnectionFactory.GetDbConnection(); |         using DbConnection conn = _DBConnectionFactory.GetDbConnection(); | ||||||
|         string sql = |         string sql = | ||||||
|             $"UPDATE [{tt.HeaderTableName}] SET AttachmentID = @AttachmentID WHERE ID = @HeaderID AND AttachmentID IS NULL; " + |             $"UPDATE [{tt.HeaderTableName}] SET AttachmentID = NEWID() WHERE ID = @HeaderID AND AttachmentID IS NULL; " + | ||||||
|             $"SELECT AttachmentID FROM [{tt.HeaderTableName}] WHERE ID = @HeaderID"; |             $"SELECT AttachmentID FROM [{tt.HeaderTableName}] WHERE ID = @HeaderID"; | ||||||
|         Guid guid = conn.ExecuteScalar<Guid>(sql, param: new { HeaderID = headerId, AttachmentID = attachmentId }); |         return conn.ExecuteScalar<Guid>(sql, param: new { HeaderID = headerId }); | ||||||
|         if (attachmentId != guid.ToString()) |  | ||||||
|             throw new NotSupportedException($"{attachmentId} != {guid}"); |  | ||||||
|     } |     } | ||||||
|  |     internal string GetHeaderInsertDate(int toolTypeId, long headerId) | ||||||
|     string IMetrologyRepository.GetHeaderInsertDate(int toolTypeId, long headerId) |  | ||||||
|     { |     { | ||||||
|         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); |         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); | ||||||
|  |  | ||||||
| @ -533,8 +511,7 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|             $"SELECT CONVERT(varchar, case when [InsertDate] < [Date] or [Date] is null then [InsertDate] else [Date] end, 120) d FROM[{tt.HeaderTableName}] where ID = @HeaderID"; |             $"SELECT CONVERT(varchar, case when [InsertDate] < [Date] or [Date] is null then [InsertDate] else [Date] end, 120) d FROM[{tt.HeaderTableName}] where ID = @HeaderID"; | ||||||
|         return conn.ExecuteScalar<string>(sql, param: new { HeaderID = headerId }); |         return conn.ExecuteScalar<string>(sql, param: new { HeaderID = headerId }); | ||||||
|     } |     } | ||||||
|  |     internal string GetAttachmentInsertDateByGUID(string tableName, Guid attachmentId) | ||||||
|     string IMetrologyRepository.GetAttachmentInsertDateByGUID(string tableName, Guid attachmentId) |  | ||||||
|     { |     { | ||||||
|         using DbConnection conn = _DBConnectionFactory.GetDbConnection(); |         using DbConnection conn = _DBConnectionFactory.GetDbConnection(); | ||||||
|         string sql = ""; |         string sql = ""; | ||||||
| @ -549,27 +526,24 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|  |  | ||||||
|         return conn.ExecuteScalar<string>(sql, param: new { AttachmentID = attachmentId }); |         return conn.ExecuteScalar<string>(sql, param: new { AttachmentID = attachmentId }); | ||||||
|     } |     } | ||||||
|  |     internal void SetHeaderDirName(string tableName, long headerId, string dateDir) | ||||||
|     void IMetrologyRepository.SetHeaderDirName(string tableName, long headerId, string dateDir) |  | ||||||
|     { |     { | ||||||
|         using DbConnection conn = _DBConnectionFactory.GetDbConnection(); |         using DbConnection conn = _DBConnectionFactory.GetDbConnection(); | ||||||
|         _ = conn.Execute($"UPDATE [{tableName}] SET AttachDirName = @AttachDirName WHERE ID = @HeaderID;", new { HeaderID = headerId, AttachDirName = dateDir }); |         _ = conn.Execute($"UPDATE [{tableName}] SET AttachDirName = @AttachDirName WHERE ID = @HeaderID;", new { HeaderID = headerId, AttachDirName = dateDir }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void IMetrologyRepository.SetDataAttachmentID(int toolTypeId, long headerId, string title, string attachmentId) |     internal Guid GetDataAttachmentID(int toolTypeId, long headerId, string title) | ||||||
|     { |     { | ||||||
|         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); |         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); | ||||||
|  |  | ||||||
|         using DbConnection conn = _DBConnectionFactory.GetDbConnection(); |         using DbConnection conn = _DBConnectionFactory.GetDbConnection(); | ||||||
|         string sql = |         string sql = | ||||||
|             $"UPDATE [{tt.DataTableName}] SET AttachmentID = @AttachmentID WHERE HeaderID = @HeaderID AND Title = @Title AND AttachmentID IS NULL; " + |             $"UPDATE [{tt.DataTableName}] SET AttachmentID = NEWID() WHERE HeaderID = @HeaderID AND Title = @Title AND AttachmentID IS NULL; " + | ||||||
|             $"SELECT AttachmentID FROM [{tt.DataTableName}] WHERE HeaderID = @HeaderID AND Title = @Title"; |             $"SELECT AttachmentID FROM [{tt.DataTableName}] WHERE HeaderID = @HeaderID AND Title = @Title"; | ||||||
|         Guid guid = conn.ExecuteScalar<Guid>(sql, param: new { HeaderID = headerId, AttachmentID = attachmentId, Title = title }); |         return conn.ExecuteScalar<Guid>(sql, param: new { HeaderID = headerId, Title = title }); | ||||||
|         if (attachmentId != guid.ToString()) |  | ||||||
|             throw new NotSupportedException($"{attachmentId} != {guid}"); |  | ||||||
|     } |     } | ||||||
|  |     // J Ouellette Added | ||||||
|     string IMetrologyRepository.GetDataInsertDate(int toolTypeId, long headerId, string title) |     internal string GetDataInsertDate(int toolTypeId, long headerId, string title) | ||||||
|     { |     { | ||||||
|         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); |         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); | ||||||
|  |  | ||||||
| @ -586,8 +560,7 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|  |  | ||||||
|         return conn.ExecuteScalar<string>(sql, param: new { HeaderID = headerId, Title = title }); |         return conn.ExecuteScalar<string>(sql, param: new { HeaderID = headerId, Title = title }); | ||||||
|     } |     } | ||||||
|  |     internal void SetDataDirName(string tableName, long headerId, string title, string dateDir) | ||||||
|     void IMetrologyRepository.SetDataDirName(string tableName, long headerId, string title, string dateDir) |  | ||||||
|     { |     { | ||||||
|         using DbConnection conn = _DBConnectionFactory.GetDbConnection(); |         using DbConnection conn = _DBConnectionFactory.GetDbConnection(); | ||||||
|         string sql = |         string sql = | ||||||
| @ -595,13 +568,13 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|         _ = conn.Execute(sql, param: new { HeaderID = headerId, Title = title, AttachDirName = dateDir }); |         _ = conn.Execute(sql, param: new { HeaderID = headerId, Title = title, AttachDirName = dateDir }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void IMetrologyRepository.PurgeExistingData(int toolTypeId, string title) |     internal void PurgeExistingData(int toolTypeId, string title) | ||||||
|     { |     { | ||||||
|         using DbConnection conn = _DBConnectionFactory.GetDbConnection(); |         using DbConnection conn = _DBConnectionFactory.GetDbConnection(); | ||||||
|         _ = conn.Execute("PurgeExistingData", param: new { ToolTypeID = toolTypeId, Title = title }, commandType: CommandType.StoredProcedure); |         _ = conn.Execute("PurgeExistingData", param: new { ToolTypeID = toolTypeId, Title = title }, commandType: CommandType.StoredProcedure); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     DataSet IMetrologyRepository.GetOIExportData(int toolTypeId, long headerid) |     internal DataSet GetOIExportData(int toolTypeId, long headerid) | ||||||
|     { |     { | ||||||
|         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); |         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); | ||||||
|  |  | ||||||
| @ -653,7 +626,7 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|         return results.ToArray(); |         return results.ToArray(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     HeaderCommon[] IMetrologyRepository.GetHeaderTitles(int? toolTypeId, int? pageNo, int? pageSize, out long totalRecords) |     internal HeaderCommon[] GetHeaderTitles(int? toolTypeId, int? pageNo, int? pageSize, out long totalRecords) | ||||||
|     { |     { | ||||||
|         HeaderCommon[] headers; |         HeaderCommon[] headers; | ||||||
|         if (toolTypeId is not null && (pageNo is not null || pageSize is not null)) |         if (toolTypeId is not null && (pageNo is not null || pageSize is not null)) | ||||||
| @ -689,7 +662,7 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|         return headers; |         return headers; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     IEnumerable<KeyValuePair<string, string>> IMetrologyRepository.GetHeaderFields(int toolTypeId, long headerid) |     internal IEnumerable<KeyValuePair<string, string>> GetHeaderFields(int toolTypeId, long headerid) | ||||||
|     { |     { | ||||||
|         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); |         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); | ||||||
|  |  | ||||||
| @ -716,9 +689,7 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|             if (dt.Rows.Count > 0) |             if (dt.Rows.Count > 0) | ||||||
|                 dr = dt.Rows[0]; |                 dr = dt.Rows[0]; | ||||||
|  |  | ||||||
|             foreach (ToolTypeMetadata m in md.Where(m => |             foreach (ToolTypeMetadata m in md.Where(m => m.Header == true && m.TableDisplayOrder > 0).OrderBy(m => m.TableDisplayOrder)) | ||||||
|                 m.Header == true && m.TableDisplayOrder > 0).OrderBy(m => |  | ||||||
|                 m.TableDisplayOrder)) |  | ||||||
|             { |             { | ||||||
|                 string v = ""; |                 string v = ""; | ||||||
|                 if (dr is not null) |                 if (dr is not null) | ||||||
| @ -734,7 +705,7 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|         return r; |         return r; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     IEnumerable<AwaitingDisposition> IMetrologyRepository.GetAwaitingDisposition() |     internal IEnumerable<AwaitingDisposition> GetAwaitingDisposition() | ||||||
|     { |     { | ||||||
|         IEnumerable<AwaitingDisposition>? r; |         IEnumerable<AwaitingDisposition>? r; | ||||||
|         if (!string.IsNullOrEmpty(_MockRoot)) |         if (!string.IsNullOrEmpty(_MockRoot)) | ||||||
| @ -752,7 +723,7 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|         return r; |         return r; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     int IMetrologyRepository.UpdateReviewDate(int toolTypeId, long headerId, bool clearDate) |     internal int UpdateReviewDate(int toolTypeId, long headerId, bool clearDate) | ||||||
|     { |     { | ||||||
|         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); |         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); | ||||||
|  |  | ||||||
| @ -772,7 +743,7 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     Guid IMetrologyRepository.GetHeaderAttachmentIDByTitle(int toolTypeId, string title) |     internal Guid GetHeaderAttachmentIDByTitle(int toolTypeId, string title) | ||||||
|     { |     { | ||||||
|         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); |         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); | ||||||
|  |  | ||||||
| @ -782,7 +753,7 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|         return conn.ExecuteScalar<Guid>(sql, param: new { Title = title }); |         return conn.ExecuteScalar<Guid>(sql, param: new { Title = title }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     Guid IMetrologyRepository.GetDataAttachmentIDByTitle(int toolTypeId, string title) |     internal Guid GetDataAttachmentIDByTitle(int toolTypeId, string title) | ||||||
|     { |     { | ||||||
|         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); |         ToolType tt = GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); | ||||||
|  |  | ||||||
| @ -792,13 +763,31 @@ public class MetrologyRepository : IMetrologyRepository | |||||||
|         return conn.ExecuteScalar<Guid>(sql, param: new { Title = title }); |         return conn.ExecuteScalar<Guid>(sql, param: new { Title = title }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     IEnumerable<ToolType> IMetrologyRepository.GetToolTypes() => |     DataTable IMetrologyRepository.GetDataSharePoint(int toolTypeId, string headerId) => throw new NotImplementedException(); | ||||||
|         GetToolTypes(); |  | ||||||
|     ToolType IMetrologyRepository.GetToolTypeByID(int id) => |     IEnumerable<ToolType> IMetrologyRepository.GetToolTypes() => GetToolTypes(); | ||||||
|         GetToolTypeByID(id); |     ToolType IMetrologyRepository.GetToolTypeByName(string name) => GetToolTypeByName(name); | ||||||
|     TransactionScope IMetrologyRepository.StartTransaction() => |     ToolType IMetrologyRepository.GetToolTypeByID(int id) => GetToolTypeByID(id); | ||||||
|         StartTransaction(); |     IEnumerable<ToolTypeMetadata> IMetrologyRepository.GetToolTypeMetadataByToolTypeID(int id) => GetToolTypeMetadataByToolTypeID(id); | ||||||
|     IEnumerable<ToolTypeMetadata> IMetrologyRepository.GetToolTypeMetadataByToolTypeID(int id) => |     TransactionScope IMetrologyRepository.StartTransaction() => StartTransaction(); | ||||||
|         GetToolTypeMetadataByToolTypeID(id); |     void IMetrologyRepository.PurgeExistingData(int toolTypeId, string title) => PurgeExistingData(toolTypeId, title); | ||||||
|  |     long IMetrologyRepository.InsertToolDataJSON(JToken jsonbody, long headerId, List<ToolTypeMetadata> metaData, string tableName) => InsertToolDataJSON(jsonbody, headerId, metaData, tableName); | ||||||
|  |     DataTable IMetrologyRepository.ExportData(string spName, DateTime startTime, DateTime endTime) => ExportData(spName, startTime, endTime); | ||||||
|  |     DataTable IMetrologyRepository.GetHeaders(int toolTypeId, string? startTime, string? endTime, int? pageNo, int? pageSize, long? headerid, out long totalRecords) => GetHeaders(toolTypeId, startTime, endTime, pageNo, pageSize, headerid, out totalRecords); | ||||||
|  |     DataTable IMetrologyRepository.GetData(int toolTypeId, long headerId) => GetData(toolTypeId, headerId); | ||||||
|  |     HeaderCommon[] IMetrologyRepository.GetHeaderTitles(int? toolTypeId, int? pageNo, int? pageSize, out long totalRecords) => GetHeaderTitles(toolTypeId, pageNo, pageSize, out totalRecords); | ||||||
|  |     Guid IMetrologyRepository.GetHeaderAttachmentIDByTitle(int toolTypeId, string title) => GetHeaderAttachmentIDByTitle(toolTypeId, title); | ||||||
|  |     Guid IMetrologyRepository.GetDataAttachmentIDByTitle(int toolTypeId, string title) => GetDataAttachmentIDByTitle(toolTypeId, title); | ||||||
|  |     Guid IMetrologyRepository.GetHeaderAttachmentID(int toolTypeId, long headerId) => GetHeaderAttachmentID(toolTypeId, headerId); | ||||||
|  |     string IMetrologyRepository.GetHeaderInsertDate(int toolTypeId, long headerId) => GetHeaderInsertDate(toolTypeId, headerId); | ||||||
|  |     string IMetrologyRepository.GetAttachmentInsertDateByGUID(string tableName, Guid attachmentId) => GetAttachmentInsertDateByGUID(tableName, attachmentId); | ||||||
|  |     void IMetrologyRepository.SetHeaderDirName(string tableName, long headerId, string dateDir) => SetHeaderDirName(tableName, headerId, dateDir); | ||||||
|  |     Guid IMetrologyRepository.GetDataAttachmentID(int toolTypeId, long headerId, string title) => GetDataAttachmentID(toolTypeId, headerId, title); | ||||||
|  |     string IMetrologyRepository.GetDataInsertDate(int toolTypeId, long headerId, string title) => GetDataInsertDate(toolTypeId, headerId, title); | ||||||
|  |     void IMetrologyRepository.SetDataDirName(string tableName, long headerId, string title, string dateDir) => SetDataDirName(tableName, headerId, title, dateDir); | ||||||
|  |     DataSet IMetrologyRepository.GetOIExportData(int toolTypeId, long headerid) => GetOIExportData(toolTypeId, headerid); | ||||||
|  |     IEnumerable<KeyValuePair<string, string>> IMetrologyRepository.GetHeaderFields(int toolTypeId, long headerid) => GetHeaderFields(toolTypeId, headerid); | ||||||
|  |     IEnumerable<AwaitingDisposition> IMetrologyRepository.GetAwaitingDisposition() => GetAwaitingDisposition(); | ||||||
|  |     int IMetrologyRepository.UpdateReviewDate(int toolTypeId, long headerId, bool clearDate) => UpdateReviewDate(toolTypeId, headerId, clearDate); | ||||||
|  |  | ||||||
| } | } | ||||||
| @ -3,6 +3,7 @@ using OI.Metrology.Shared.DataModels; | |||||||
| using OI.Metrology.Shared.Models.Stateless; | using OI.Metrology.Shared.Models.Stateless; | ||||||
| using OI.Metrology.Shared.Services; | using OI.Metrology.Shared.Services; | ||||||
| using System.Data; | using System.Data; | ||||||
|  | using System.Text; | ||||||
| using System.Text.Json; | using System.Text.Json; | ||||||
|  |  | ||||||
| namespace OI.Metrology.Server.Repository; | namespace OI.Metrology.Server.Repository; | ||||||
| @ -236,4 +237,96 @@ public class ToolTypesRepository : IToolTypesRepository | |||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     Result<DataTable> IToolTypesRepository.GetExportData(IMetrologyRepository metrologyRepository, int toolTypeId, string? datebegin, string? dateend) | ||||||
|  |     { | ||||||
|  |         Result<DataTable>? r; | ||||||
|  |         if (!string.IsNullOrEmpty(_MockRoot)) | ||||||
|  |         { | ||||||
|  |             string json = File.ReadAllText(Path.Combine(string.Concat(AppContext.BaseDirectory, _MockRoot), $"{_RepositoryName}-{nameof(IToolTypesRepository.GetExportData)}.json")); | ||||||
|  |             r = Newtonsoft.Json.JsonConvert.DeserializeObject<Result<DataTable>>(json); | ||||||
|  |             if (r is null) | ||||||
|  |                 throw new NullReferenceException(nameof(r)); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             DateTime dateEnd = dateend is null ? DateTime.Now : DateTime.Parse(dateend); | ||||||
|  |             DateTime dateBegin = datebegin is null ? dateEnd.AddMonths(-1) : DateTime.Parse(datebegin); | ||||||
|  |             ToolType tt = metrologyRepository.GetToolTypeByID(toolTypeId); | ||||||
|  |             if (string.IsNullOrEmpty(tt.ExportSPName)) | ||||||
|  |                 throw new NullReferenceException(nameof(tt.ExportSPName)); | ||||||
|  |             DataTable dataTable = metrologyRepository.ExportData(tt.ExportSPName, dateBegin, dateEnd); | ||||||
|  |             r = new() | ||||||
|  |             { | ||||||
|  |                 Results = dataTable, | ||||||
|  |                 TotalRows = dataTable.Rows.Count, | ||||||
|  |             }; | ||||||
|  |         } | ||||||
|  |         return r; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected static string FormatForCSV(string v) | ||||||
|  |     { | ||||||
|  |         StringBuilder result = new(v.Length + 2); | ||||||
|  |         bool doubleQuoted = false; | ||||||
|  |         if (v.StartsWith(' ') || v.EndsWith(' ') || v.Contains(',') || v.Contains('"')) | ||||||
|  |         { | ||||||
|  |             _ = result.Append('"'); | ||||||
|  |             doubleQuoted = true; | ||||||
|  |         } | ||||||
|  |         foreach (char c in v) | ||||||
|  |         { | ||||||
|  |             _ = c switch | ||||||
|  |             { | ||||||
|  |                 '\r' or '\n' => result.Append(' '), | ||||||
|  |                 '"' => result.Append("\"\""), | ||||||
|  |                 _ => result.Append(c), | ||||||
|  |             }; | ||||||
|  |         } | ||||||
|  |         if (doubleQuoted) | ||||||
|  |             _ = result.Append('"'); | ||||||
|  |         return result.ToString(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected static string GetColumnHeaders(DataTable dataTable) | ||||||
|  |     { | ||||||
|  |         StringBuilder result = new(); | ||||||
|  |         for (int i = 0; i < dataTable.Columns.Count; i++) | ||||||
|  |         { | ||||||
|  |             if (i > 0) | ||||||
|  |                 _ = result.Append(','); | ||||||
|  |             _ = result.Append(FormatForCSV(dataTable.Columns[i].ColumnName.TrimEnd('_'))); | ||||||
|  |         } | ||||||
|  |         return result.ToString(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected static string GetRowData(DataRow dr) | ||||||
|  |     { | ||||||
|  |         StringBuilder result = new(); | ||||||
|  |         for (int i = 0; i < dr.Table.Columns.Count; i++) | ||||||
|  |         { | ||||||
|  |             if (i > 0) | ||||||
|  |                 _ = result.Append(','); | ||||||
|  |             object v = dr[i]; | ||||||
|  |             if (v is not null && !Convert.IsDBNull(v)) | ||||||
|  |                 _ = result.Append(FormatForCSV(string.Concat(Convert.ToString(v)))); | ||||||
|  |         } | ||||||
|  |         return result.ToString(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     byte[] IToolTypesRepository.GetCSVExport(IMetrologyRepository metrologyRepository, int toolTypeId, string? datebegin, string? dateend) | ||||||
|  |     { | ||||||
|  |         byte[] results; | ||||||
|  |         Result<DataTable> result; | ||||||
|  |         IToolTypesRepository repository = this; | ||||||
|  |         result = repository.GetExportData(metrologyRepository, toolTypeId, datebegin, dateend); | ||||||
|  |         if (result.Results is null) | ||||||
|  |             throw new NullReferenceException(nameof(result.Results)); | ||||||
|  |         StringBuilder stringBuilder = new(); | ||||||
|  |         _ = stringBuilder.AppendLine(GetColumnHeaders(result.Results)); | ||||||
|  |         foreach (DataRow dr in result.Results.Rows) | ||||||
|  |             _ = stringBuilder.AppendLine(GetRowData(dr)); | ||||||
|  |         results = Encoding.UTF8.GetBytes(stringBuilder.ToString()); | ||||||
|  |         return results; | ||||||
|  |     } | ||||||
|  |  | ||||||
| } | } | ||||||
							
								
								
									
										211
									
								
								Server/Repositories/WaferCounterRepository.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,211 @@ | |||||||
|  | using OI.Metrology.Server.Models; | ||||||
|  | using OI.Metrology.Shared.DataModels; | ||||||
|  | using OI.Metrology.Shared.Models; | ||||||
|  | using OI.Metrology.Shared.Models.Stateless; | ||||||
|  | using OI.Metrology.Shared.Repositories; | ||||||
|  | using System.Globalization; | ||||||
|  |  | ||||||
|  | namespace OI.Metrology.Server.Repository; | ||||||
|  |  | ||||||
|  | public class WaferCounterRepository : IWaferCounterRepository | ||||||
|  | { | ||||||
|  |  | ||||||
|  |     private record Record(int Check, | ||||||
|  |                           int Total, | ||||||
|  |                           string? SlotMap); | ||||||
|  |  | ||||||
|  |     private readonly string _MockRoot; | ||||||
|  |     private readonly string _RepositoryName; | ||||||
|  |     private readonly AppSettings _AppSettings; | ||||||
|  |     private readonly IHttpClientFactory _HttpClientFactory; | ||||||
|  |     private readonly IDbConnectionFactory _DBConnectionFactory; | ||||||
|  |     private readonly IFileShareRepository _FileShareRepository; | ||||||
|  |     private readonly string _OpenInsightApplicationProgrammingInterface; | ||||||
|  |  | ||||||
|  |     public WaferCounterRepository(AppSettings appSettings, IDbConnectionFactory dbConnectionFactory, IHttpClientFactory httpClientFactory, IFileShareRepository fileShareRepository) | ||||||
|  |     { | ||||||
|  |         _AppSettings = appSettings; | ||||||
|  |         _MockRoot = appSettings.MockRoot; | ||||||
|  |         _HttpClientFactory = httpClientFactory; | ||||||
|  |         _DBConnectionFactory = dbConnectionFactory; | ||||||
|  |         _FileShareRepository = fileShareRepository; | ||||||
|  |         _RepositoryName = nameof(WaferCounterRepository)[..^10]; | ||||||
|  |         _OpenInsightApplicationProgrammingInterface = appSettings.OpenInsightApplicationProgrammingInterface; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private void MoveFile(string waferSizeDirectory, NginxFileSystemSortable nginxFileSystemSortable) | ||||||
|  |     { | ||||||
|  |         Calendar calendar = new CultureInfo("en-US").Calendar; | ||||||
|  |         string from = Path.Combine(waferSizeDirectory, nginxFileSystemSortable.Name); | ||||||
|  |         string weekOfYear = $"{nginxFileSystemSortable.DateTime:yyyy}_Week_{calendar.GetWeekOfYear(nginxFileSystemSortable.DateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday):00}"; | ||||||
|  |         string to = Path.Combine(waferSizeDirectory, "Archive", weekOfYear, nginxFileSystemSortable.Name); | ||||||
|  |         _FileShareRepository.MoveFile(from, to); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private static Record GetRecord(string line1, string line2) | ||||||
|  |     { | ||||||
|  |         Record result; | ||||||
|  |         string? waferMap = string.IsNullOrEmpty(line2) || line2.Length != 8 ? null : line2.Substring(1, 1); | ||||||
|  |         int check = waferMap == "1" ? 1 : 0; | ||||||
|  |         int total = int.Parse(line1[1..]); | ||||||
|  |         // string wafers = Array.from(line2[2..]); | ||||||
|  |         foreach (char item in line2[2..]) | ||||||
|  |         { | ||||||
|  |             switch (item) | ||||||
|  |             { | ||||||
|  |                 case '0': | ||||||
|  |                     check += 0; | ||||||
|  |                     waferMap += "0000"; | ||||||
|  |                     break; | ||||||
|  |                 case '1': | ||||||
|  |                     check += 1; | ||||||
|  |                     waferMap += "0001"; | ||||||
|  |                     break; | ||||||
|  |                 case '2': | ||||||
|  |                     check += 1; | ||||||
|  |                     waferMap += "0010"; | ||||||
|  |                     break; | ||||||
|  |                 case '3': | ||||||
|  |                     check += 2; | ||||||
|  |                     waferMap += "0011"; | ||||||
|  |                     break; | ||||||
|  |                 case '4': | ||||||
|  |                     check += 1; | ||||||
|  |                     waferMap += "0100"; | ||||||
|  |                     break; | ||||||
|  |                 case '5': | ||||||
|  |                     check += 2; | ||||||
|  |                     waferMap += "0101"; | ||||||
|  |                     break; | ||||||
|  |                 case '6': | ||||||
|  |                     check += 2; | ||||||
|  |                     waferMap += "0110"; | ||||||
|  |                     break; | ||||||
|  |                 case '7': | ||||||
|  |                     check += 3; | ||||||
|  |                     waferMap += "0111"; | ||||||
|  |                     break; | ||||||
|  |                 case '8': | ||||||
|  |                     check += 1; | ||||||
|  |                     waferMap += "1000"; | ||||||
|  |                     break; | ||||||
|  |                 case '9': | ||||||
|  |                     check += 2; | ||||||
|  |                     waferMap += "1001"; | ||||||
|  |                     break; | ||||||
|  |                 case 'A': | ||||||
|  |                     check += 2; | ||||||
|  |                     waferMap += "1010"; | ||||||
|  |                     break; | ||||||
|  |                 case 'B': | ||||||
|  |                     check += 3; | ||||||
|  |                     waferMap += "1011"; | ||||||
|  |                     break; | ||||||
|  |                 case 'C': | ||||||
|  |                     check += 2; | ||||||
|  |                     waferMap += "1100"; | ||||||
|  |                     break; | ||||||
|  |                 case 'D': | ||||||
|  |                     check += 3; | ||||||
|  |                     waferMap += "1101"; | ||||||
|  |                     break; | ||||||
|  |                 case 'E': | ||||||
|  |                     check += 3; | ||||||
|  |                     waferMap += "1110"; | ||||||
|  |                     break; | ||||||
|  |                 case 'F': | ||||||
|  |                     check += 4; | ||||||
|  |                     waferMap += "1111"; | ||||||
|  |                     break; | ||||||
|  |                 default: | ||||||
|  |                     break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         result = new(check, total, waferMap); | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private Uri GetWaferSizeUri(string area, string waferSize) => | ||||||
|  |         _FileShareRepository.Append(new Uri(_AppSettings.EcMesaFileShareCharacterizationSi), "WaferCounter", area, waferSize); | ||||||
|  |  | ||||||
|  |     private string GetWaferSizeDirectory(string area, string waferSize, bool destination) => | ||||||
|  |         destination ? Path.Combine(_AppSettings.WaferCounterDestinationDirectory, area, waferSize) : Path.Combine(_AppSettings.EcCharacterizationSi, "WaferCounter", area, waferSize); | ||||||
|  |  | ||||||
|  |     string? IWaferCounterRepository.GetSlotMap(string line1, string line2) => | ||||||
|  |         GetRecord(line1, line2).SlotMap; | ||||||
|  |  | ||||||
|  |     private List<NginxFileSystemSortable> GetNginxFileSystemSortableCollection(HttpClient httpClient, Uri waferSizeUri, string waferSizeDirectory) | ||||||
|  |     { | ||||||
|  |         List<NginxFileSystemSortable> results = new(); | ||||||
|  |         DateTime dateTime = DateTime.Now; | ||||||
|  |         long ticks = dateTime.AddSeconds(_AppSettings.WaferCounterTwoFileSecondsWait).Ticks; | ||||||
|  |         for (int i = 0; i < int.MaxValue; i++) | ||||||
|  |         { | ||||||
|  |             results = _FileShareRepository.GetNginxFileSystemSortableCollection(httpClient, waferSizeUri, ".wc"); | ||||||
|  |             if (results.Count > 1 || DateTime.Now.Ticks > ticks) | ||||||
|  |                 break; | ||||||
|  |             Thread.Sleep(250); | ||||||
|  |         } | ||||||
|  |         for (int i = 1; i < results.Count; i++) | ||||||
|  |             MoveFile(waferSizeDirectory, results[i]); | ||||||
|  |         return results; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private static WaferCounter GetLastQuantityAndSlotMapWithText(string waferSize, string text, HttpClient httpClient, NginxFileSystemSortable nginxFileSystemSortable) | ||||||
|  |     { | ||||||
|  |         WaferCounter result; | ||||||
|  |         Task<string> value = httpClient.GetStringAsync(nginxFileSystemSortable.Uri); | ||||||
|  |         value.Wait(); | ||||||
|  |         string[] lines = value.Result.Split("\r\n"); | ||||||
|  |         if (lines.Length <= 1) | ||||||
|  |             throw new Exception("Incomplete file length!"); | ||||||
|  |         string[] segments = nginxFileSystemSortable.Name.Split('-'); | ||||||
|  |         Record record = GetRecord(lines[0], lines[1]); | ||||||
|  |         string equipmentId = segments.Length <= 1 ? nginxFileSystemSortable.Name : segments[1].Split('.')[0]; | ||||||
|  |         if (string.IsNullOrEmpty(record.SlotMap) || record.SlotMap.Length != 25) | ||||||
|  |             throw new Exception("Wrong length!"); | ||||||
|  |         if (record.Total != record.Check) | ||||||
|  |             throw new Exception("Invalid!"); | ||||||
|  |         result = new(nginxFileSystemSortable.DateTime, nginxFileSystemSortable.DateTime.ToString("yyyy-MM-dd hh:mm tt"), $"WC{waferSize}{equipmentId}", text, record.Total, record.SlotMap); | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     WaferCounter IWaferCounterRepository.GetLastQuantityAndSlotMap(string area, string waferSize) | ||||||
|  |     { | ||||||
|  |         WaferCounter result; | ||||||
|  |         Uri waferSizeUri = GetWaferSizeUri(area, waferSize); | ||||||
|  |         HttpClient httpClient = _HttpClientFactory.CreateClient(); | ||||||
|  |         string waferSizeDirectory = GetWaferSizeDirectory(area, waferSize, destination: false); | ||||||
|  |         List<NginxFileSystemSortable> nginxFileSystemSortableCollection = GetNginxFileSystemSortableCollection(httpClient, waferSizeUri, waferSizeDirectory); | ||||||
|  |         if (nginxFileSystemSortableCollection.Count < 1) | ||||||
|  |             throw new Exception("No files!"); | ||||||
|  |         string text = string.Empty; | ||||||
|  |         result = GetLastQuantityAndSlotMapWithText(waferSize, text, httpClient, nginxFileSystemSortableCollection[0]); | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private void Save(string waferSizeDestinationDirectory, string area, string waferSize, string text, NginxFileSystemSortable nginxFileSystemSortable, WaferCounter result) => | ||||||
|  |         _FileShareRepository.FileWrite(Path.Combine(waferSizeDestinationDirectory, $"{nginxFileSystemSortable.Name}.csv"), $"100,{waferSize},{area},{nginxFileSystemSortable.DateTime},{text},{result.Total:00},{result.SlotMap} "); | ||||||
|  |  | ||||||
|  |     WaferCounter IWaferCounterRepository.GetLastQuantityAndSlotMapWithText(string area, string waferSize, string text) | ||||||
|  |     { | ||||||
|  |         WaferCounter result; | ||||||
|  |         Uri waferSizeUri = GetWaferSizeUri(area, waferSize); | ||||||
|  |         HttpClient httpClient = _HttpClientFactory.CreateClient(); | ||||||
|  |         string waferSizeDirectory = GetWaferSizeDirectory(area, waferSize, destination: false); | ||||||
|  |         List<NginxFileSystemSortable> nginxFileSystemSortableCollection = GetNginxFileSystemSortableCollection(httpClient, waferSizeUri, waferSizeDirectory); | ||||||
|  |         if (nginxFileSystemSortableCollection.Count < 1) | ||||||
|  |             throw new Exception("No files!"); | ||||||
|  |         result = GetLastQuantityAndSlotMapWithText(waferSize, text, httpClient, nginxFileSystemSortableCollection[0]); | ||||||
|  |         if (result is not null) | ||||||
|  |         { | ||||||
|  |             string waferSizeDestinationDirectory = _AppSettings.WaferCounterDestinationDirectory; | ||||||
|  |             // string waferSizeDestinationDirectory = GetWaferSizeUri(area, waferSize, destination: true); | ||||||
|  |             Save(waferSizeDestinationDirectory, area, waferSize, text, nginxFileSystemSortableCollection[0], result); | ||||||
|  |         } | ||||||
|  |         if (result is null) | ||||||
|  |             throw new NullReferenceException(nameof(result)); | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -39,7 +39,7 @@ public class AttachmentsService : IAttachmentsService | |||||||
|         HttpClient httpClient = _HttpClientFactory.CreateClient(); |         HttpClient httpClient = _HttpClientFactory.CreateClient(); | ||||||
|         Uri mesaFileShareMetrologySi = new(_AppSettings.EcMesaFileShareMetrologySi); |         Uri mesaFileShareMetrologySi = new(_AppSettings.EcMesaFileShareMetrologySi); | ||||||
|         int weekNum = CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(insertDate, CalendarWeekRule.FirstDay, DayOfWeek.Sunday); |         int weekNum = CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(insertDate, CalendarWeekRule.FirstDay, DayOfWeek.Sunday); | ||||||
|         Uri uri = _FileShareRepository.Append(mesaFileShareMetrologySi, "MetrologyAttachments", $"{tableName}_", year, $"WW{weekNum:00}", attachmentId.ToString(), filename); |         Uri uri = _FileShareRepository.Append(mesaFileShareMetrologySi, $"{tableName}_", year, $"WW{weekNum:00}", attachmentId.ToString(), filename); | ||||||
|         HttpResponseMessage httpResponseMessage = _FileShareRepository.ReadFile(httpClient, uri); |         HttpResponseMessage httpResponseMessage = _FileShareRepository.ReadFile(httpClient, uri); | ||||||
|         if (httpResponseMessage.StatusCode != System.Net.HttpStatusCode.OK) |         if (httpResponseMessage.StatusCode != System.Net.HttpStatusCode.OK) | ||||||
|             throw new Exception("File not found!"); |             throw new Exception("File not found!"); | ||||||
| @ -77,36 +77,63 @@ public class AttachmentsService : IAttachmentsService | |||||||
|         return GetAttachmentStream(tableName, attachmentId, filename); |         return GetAttachmentStream(tableName, attachmentId, filename); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void IAttachmentsService.SaveAttachment(ToolType toolType, Attachment attachment) |     private void SaveAttachment(ToolType toolType, long headerId, string dataUniqueId, string filename, IFormFile uploadedFile) | ||||||
|     { |     { | ||||||
|         if (toolType is null) |         if (toolType is null) | ||||||
|             throw new Exception("Invalid tool type"); |             throw new Exception("Invalid tool type"); | ||||||
|         if (attachment.HeaderId is null) |  | ||||||
|             throw new NullReferenceException($"{nameof(attachment.HeaderId)}"); |         using System.Transactions.TransactionScope trans = _MetrologyRepository.StartTransaction(); | ||||||
|         if (attachment.AttachmentId is null) |         Guid attachmentId = Guid.Empty; | ||||||
|             throw new NullReferenceException($"{nameof(attachment.AttachmentId)}"); |         DateTime insertDate = new(); | ||||||
|         if (attachment.DestinationFileName is null) |         string? tableName = ""; | ||||||
|             throw new NullReferenceException($"{nameof(attachment.DestinationFileName)}"); |         if (string.IsNullOrWhiteSpace(dataUniqueId)) | ||||||
|         if (string.IsNullOrWhiteSpace(attachment.UniqueId)) |         { | ||||||
|             throw new NullReferenceException($"{nameof(attachment.UniqueId)}"); |             attachmentId = _MetrologyRepository.GetHeaderAttachmentID(toolType.ID, headerId); | ||||||
|         if (attachment.DestinationFileName != "Image.pdf") |             insertDate = Convert.ToDateTime(_MetrologyRepository.GetHeaderInsertDate(toolType.ID, headerId)); | ||||||
|             _MetrologyRepository.SetHeaderAttachmentID(toolType.ID, attachment.HeaderId.Value, attachment.AttachmentId); |             tableName = toolType.HeaderTableName; | ||||||
|  |         } | ||||||
|         else |         else | ||||||
|             _MetrologyRepository.SetDataAttachmentID(toolType.ID, attachment.HeaderId.Value, attachment.UniqueId, attachment.AttachmentId); |         { | ||||||
|  |             attachmentId = _MetrologyRepository.GetDataAttachmentID(toolType.ID, headerId, dataUniqueId); | ||||||
|  |             insertDate = Convert.ToDateTime(_MetrologyRepository.GetDataInsertDate(toolType.ID, headerId, dataUniqueId)); | ||||||
|  |             // Get Date for new directory name | ||||||
|  |             tableName = toolType.DataTableName; | ||||||
|  |         } | ||||||
|  |         if (Equals(attachmentId, Guid.Empty)) | ||||||
|  |         { | ||||||
|  |             trans.Dispose(); | ||||||
|  |             throw new Exception("Invalid attachment ID!"); | ||||||
|  |         } | ||||||
|  |         string year = insertDate.Year.ToString(); | ||||||
|  |         HttpClient httpClient = _HttpClientFactory.CreateClient(); | ||||||
|  |         Uri mesaFileShareMetrologySi = new(_AppSettings.EcMesaFileShareMetrologySi); | ||||||
|  |         int weekNum = CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(insertDate, CalendarWeekRule.FirstDay, DayOfWeek.Sunday); | ||||||
|  |         Uri uri = _FileShareRepository.Append(mesaFileShareMetrologySi, $"{tableName}_", year, $"WW{weekNum:00}", attachmentId.ToString(), filename); | ||||||
|  |         HttpResponseMessage httpResponseMessage = _FileShareRepository.ReadFile(httpClient, uri); | ||||||
|  |         if (httpResponseMessage.StatusCode != System.Net.HttpStatusCode.OK) | ||||||
|  |         { | ||||||
|  |             trans.Dispose(); | ||||||
|  |             throw new Exception("Invalid attachment path!"); | ||||||
|  |         } | ||||||
|  |         uploadedFile.CopyTo(httpResponseMessage.Content.ReadAsStream()); | ||||||
|  |         trans.Complete(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void IAttachmentsService.SaveAttachment(ToolType toolType, long headerId, string dataUniqueId, string filename, object uploadedFile) | ||||||
|  |     { | ||||||
|  |         IFormFile formFile = (IFormFile)uploadedFile; | ||||||
|  |         SaveAttachment(toolType, headerId, dataUniqueId, filename, formFile); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     string? IAttachmentsService.GetProcessDataStandardFormat(IMetrologyRepository metrologyRepository, int toolTypeId, long headerId) |     string? IAttachmentsService.GetProcessDataStandardFormat(IMetrologyRepository metrologyRepository, int toolTypeId, long headerId) | ||||||
|     { |     { | ||||||
|         string? result; |         string? result; | ||||||
|         int weekNum; |         int weekNum; | ||||||
|         string file; |  | ||||||
|         string year; |         string year; | ||||||
|         string directory; |  | ||||||
|         Task<string> json; |         Task<string> json; | ||||||
|         Uri weekDirectory; |         Uri weekDirectory; | ||||||
|         Uri checkDirectory; |         Uri checkDirectory; | ||||||
|         List<string> files = new(); |         List<string> files = new(); | ||||||
|         string[] collection = ["-", string.Empty]; |  | ||||||
|         NginxFileSystem[]? nginxFileSystemCollection; |         NginxFileSystem[]? nginxFileSystemCollection; | ||||||
|         Task<HttpResponseMessage> httpResponseMessage; |         Task<HttpResponseMessage> httpResponseMessage; | ||||||
|         HttpClient httpClient = _HttpClientFactory.CreateClient(); |         HttpClient httpClient = _HttpClientFactory.CreateClient(); | ||||||
| @ -115,32 +142,21 @@ public class AttachmentsService : IAttachmentsService | |||||||
|         ToolType toolType = metrologyRepository.GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); |         ToolType toolType = metrologyRepository.GetToolTypeByID(toolTypeId) ?? throw new Exception("Invalid tool type ID"); | ||||||
|         foreach (DateTime dateTime in dateTimes) |         foreach (DateTime dateTime in dateTimes) | ||||||
|         { |         { | ||||||
|             foreach (string item in collection) |             year = dateTime.Year.ToString(); | ||||||
|             { |             weekNum = CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday); | ||||||
|                 year = dateTime.Year.ToString(); |             weekDirectory = _FileShareRepository.Append(mesaFileShareMetrologySi, $"{toolType.HeaderTableName}_", year, $"WW{weekNum:00}"); | ||||||
|                 weekNum = CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday); |             checkDirectory = _FileShareRepository.Append(weekDirectory, headerId.ToString()); | ||||||
|                 weekDirectory = _FileShareRepository.Append(mesaFileShareMetrologySi, "MetrologyAttachments", $"{toolType.HeaderTableName}_", year, $"WW{weekNum:00}"); |             httpResponseMessage = httpClient.GetAsync(checkDirectory); | ||||||
|                 checkDirectory = _FileShareRepository.Append(weekDirectory, $"{item}{headerId}"); |             httpResponseMessage.Wait(); | ||||||
|                 directory = Path.Combine(_AppSettings.EcMetrologySi, "MetrologyAttachments", $"{toolType.HeaderTableName}_", year, $"WW{weekNum:00}", $"{item}{headerId}"); |             if (httpResponseMessage.Result.StatusCode != System.Net.HttpStatusCode.OK) | ||||||
|                 httpResponseMessage = httpClient.GetAsync(checkDirectory); |                 continue; | ||||||
|                 httpResponseMessage.Wait(); |             json = httpResponseMessage.Result.Content.ReadAsStringAsync(); | ||||||
|                 if (httpResponseMessage.Result.StatusCode != System.Net.HttpStatusCode.OK) |             json.Wait(); | ||||||
|                     continue; |             nginxFileSystemCollection = JsonSerializer.Deserialize(json.Result, NginxFileSystemCollectionSourceGenerationContext.Default.NginxFileSystemArray); | ||||||
|                 json = httpResponseMessage.Result.Content.ReadAsStringAsync(); |             if (nginxFileSystemCollection is null) | ||||||
|                 json.Wait(); |                 continue; | ||||||
|                 nginxFileSystemCollection = JsonSerializer.Deserialize(json.Result, NginxFileSystemCollectionSourceGenerationContext.Default.NginxFileSystemArray); |             foreach (NginxFileSystem nginxFileSystem in nginxFileSystemCollection) | ||||||
|                 if (nginxFileSystemCollection is null) |                 files.Add(_FileShareRepository.Append(checkDirectory, nginxFileSystem.Name).AbsoluteUri); | ||||||
|                     continue; |  | ||||||
|                 foreach (NginxFileSystem nginxFileSystem in nginxFileSystemCollection) |  | ||||||
|                 { |  | ||||||
|                     if (!nginxFileSystem.Name.EndsWith(".pdsf")) |  | ||||||
|                         continue; |  | ||||||
|                     file = Path.Combine(directory, nginxFileSystem.Name); |  | ||||||
|                     files.Add(file); |  | ||||||
|                 } |  | ||||||
|                 if (files.Count != 0) |  | ||||||
|                     break; |  | ||||||
|             } |  | ||||||
|             if (files.Count != 0) |             if (files.Count != 0) | ||||||
|                 break; |                 break; | ||||||
|         } |         } | ||||||
|  | |||||||
							
								
								
									
										96
									
								
								Server/Views/Export/Index.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,96 @@ | |||||||
|  | @using OI.Metrology.Shared.ViewModels | ||||||
|  | @model OI.Metrology.Shared.ViewModels.Export | ||||||
|  | @{ | ||||||
|  |     ViewData["Title"] = "Export Data"; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | <style> | ||||||
|  |     td { | ||||||
|  |         padding-bottom: 2em; | ||||||
|  |         padding-right: 1em; | ||||||
|  |     } | ||||||
|  | </style> | ||||||
|  |  | ||||||
|  | <h3>Export Data</h3> | ||||||
|  |  | ||||||
|  | <hr /> | ||||||
|  |  | ||||||
|  | <form asp-controller="Export" asp-action="ExportData" method="post" class="form-inline"> | ||||||
|  |     <div class="form-group"> | ||||||
|  |         <label for="ToolType">Tool Type</label> | ||||||
|  |         <div class="form-control" id="ToolType" name="ToolType"></div> | ||||||
|  |         @Html.ValidationMessage("ToolType", new { @class = "text-danger" }) | ||||||
|  |     </div> | ||||||
|  |     <div class="form-group"> | ||||||
|  |         <label for="StartDate">Start Time</label> | ||||||
|  |         <div class="form-control mb-2 mr-sm-2" id="StartDateControl"></div> | ||||||
|  |         <div class="form-control mb-2 mr-sm-2" id="StartTimeControl"></div> | ||||||
|  |         @Html.ValidationMessage("StartDate", new { @class = "text-danger" }) | ||||||
|  |     </div> | ||||||
|  |     <div class="form-group"> | ||||||
|  |         <label for="EndDate">End Time</label> | ||||||
|  |         <div class="form-control mb-2 mr-sm-2" id="EndDateControl"></div> | ||||||
|  |         <div class="form-control mb-2 mr-sm-2" id="EndTimeControl"></div> | ||||||
|  |         @Html.ValidationMessage("EndDate", new { @class = "text-danger" }) | ||||||
|  |     </div> | ||||||
|  |     <div class="form-group"> | ||||||
|  |         <button type="submit" class="btn btn-primary">Export Data</button> | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     <div class="form-group"> | ||||||
|  |         @Html.ValidationMessage("Exception", new { @class = "text-danger" }) | ||||||
|  |     </div> | ||||||
|  |     <div asp-validation-summary="ModelOnly" class="text-danger"></div> | ||||||
|  |  | ||||||
|  | </form> | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  |  | ||||||
|  |     $(document).ready(function () { | ||||||
|  |          | ||||||
|  |         var apiUrl = "@ViewBag.ApiUrl"; | ||||||
|  |          | ||||||
|  |         $("#ToolType").igCombo({ | ||||||
|  |             dataSource: apiUrl + '/tooltypes', | ||||||
|  |             responseDataKey: "Results", | ||||||
|  |             textKey: "ToolTypeName", | ||||||
|  |             valueKey: "ID", | ||||||
|  |             mode: "dropdown", | ||||||
|  |             width: 150 | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         var startTime = new Date("@Model.StartTime.ToString("yyyy-MM-ddTHH:mm")"); | ||||||
|  |  | ||||||
|  |         $("#StartDateControl").igDatePicker({ | ||||||
|  |             dateInputFormat: "date", | ||||||
|  |             value: startTime, | ||||||
|  |             width: 125, | ||||||
|  |             inputName: "StartDate", | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         $("#StartTimeControl").igTimePicker({ | ||||||
|  |             dateInputFormat: "time", | ||||||
|  |             value: startTime, | ||||||
|  |             width: 110, | ||||||
|  |             inputName: "StartTime", | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         var endTime = new Date("@Model.EndTime.ToString("yyyy-MM-ddTHH:mm")"); | ||||||
|  |  | ||||||
|  |         $("#EndDateControl").igDatePicker({ | ||||||
|  |             dateInputFormat: "date", | ||||||
|  |             value: endTime, | ||||||
|  |             width: 125, | ||||||
|  |             inputName: "EndDate", | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         $("#EndTimeControl").igTimePicker({ | ||||||
|  |             dateInputFormat: "time", | ||||||
|  |             value: endTime, | ||||||
|  |             width: 110, | ||||||
|  |             inputName: "EndTime", | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  | </script> | ||||||
							
								
								
									
										28
									
								
								Server/Views/Pages/AwaitingDispo.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,28 @@ | |||||||
|  | @{ | ||||||
|  |     ViewData["Title"] = "Awaiting Disposition"; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | <h4>Awaiting Disposition</h4> | ||||||
|  |  | ||||||
|  | <div style="height: 450px;"> | ||||||
|  |     <table id="grid"></table> | ||||||
|  | </div> | ||||||
|  |  | ||||||
|  | <div class="row" style="margin-top: 10px; margin-bottom: 20px;"> | ||||||
|  |     <div class="col-xs-1"> | ||||||
|  |         <input type="button" id="OpenButton" value="Open" /> | ||||||
|  |     </div> | ||||||
|  |     <div class="col-xs-1"> | ||||||
|  |         <input type="button" id="RefreshButton" value="Refresh" /> | ||||||
|  |     </div> | ||||||
|  | </div> | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  |  | ||||||
|  |     $(document).ready(function () { | ||||||
|  |  | ||||||
|  |         initAwaitingDisposition("@ViewBag.ApiUrl"); | ||||||
|  |  | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  | </script> | ||||||
							
								
								
									
										3
									
								
								Server/Views/Pages/Home.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,3 @@ | |||||||
|  | @{ | ||||||
|  |     ViewData["Title"] = "Metrology Home Page"; | ||||||
|  | } | ||||||
							
								
								
									
										57
									
								
								Server/Views/Pages/RunHeaders.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,57 @@ | |||||||
|  | @{ | ||||||
|  |     ViewData["Title"] = "Run Headers"; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | <style> | ||||||
|  |     html, | ||||||
|  |     body { | ||||||
|  |         height: 100%; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     div.container-fluid { | ||||||
|  |         height: 90%; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #HeaderGrid, | ||||||
|  |     #FieldsGrid { | ||||||
|  |         font-size: 12px; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     .FieldTitle { | ||||||
|  |         font-weight: bold; | ||||||
|  |     } | ||||||
|  | </style> | ||||||
|  |  | ||||||
|  | <h4>Run Headers</h4> | ||||||
|  |  | ||||||
|  | <table> | ||||||
|  |     <tr> | ||||||
|  |         <td> | ||||||
|  |             <label for="ToolType">Tool Type:</label> | ||||||
|  |         </td> | ||||||
|  |         <td> | ||||||
|  |             <div id="ToolType"></div> | ||||||
|  |         </td> | ||||||
|  |     </tr> | ||||||
|  | </table> | ||||||
|  |  | ||||||
|  | <table width="100%" height="80%"> | ||||||
|  |     <tr> | ||||||
|  |         <td width="50%"> | ||||||
|  |             <table id="HeaderGrid"></table> | ||||||
|  |         </td> | ||||||
|  |         <td width="50%"> | ||||||
|  |             <table id="FieldsGrid"></table> | ||||||
|  |         </td> | ||||||
|  |     </tr> | ||||||
|  | </table> | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  |  | ||||||
|  |     $(document).ready(function () { | ||||||
|  |  | ||||||
|  |         initRunHeaders("@ViewBag.ApiUrl"); | ||||||
|  |  | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  | </script> | ||||||
							
								
								
									
										104
									
								
								Server/Views/Pages/RunInfo.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,104 @@ | |||||||
|  | @model OI.Metrology.Shared.ViewModels.RunInfo | ||||||
|  | @{ | ||||||
|  |     ViewData["Title"] = "Run Information"; | ||||||
|  | } | ||||||
|  | <style> | ||||||
|  |     #HeaderGridDiv, | ||||||
|  |     #DetailsGridDiv { | ||||||
|  |         font-size: 12px; | ||||||
|  |     } | ||||||
|  | </style> | ||||||
|  |  | ||||||
|  | <h4>Run Information</h4> | ||||||
|  |  | ||||||
|  | <form class="form-inline mb-4"> | ||||||
|  |     <div class="form-group"> | ||||||
|  |         <label for="ToolType">Tool Type</label> | ||||||
|  |         <div class="form-control" id="ToolType"></div> | ||||||
|  |     </div> | ||||||
|  |     <div class="form-group"> | ||||||
|  |         <label for="StartDate">Start Time</label> | ||||||
|  |         <div class="form-control mb-2 mr-sm-2" id="StartDate"></div> | ||||||
|  |         <div class="form-control mb-2 mr-sm-2" id="StartTime"></div> | ||||||
|  |     </div> | ||||||
|  |     <div class="form-group"> | ||||||
|  |         <label for="EndDate">End Time</label> | ||||||
|  |         <div class="form-control mb-2 mr-sm-2" id="EndDate"></div> | ||||||
|  |         <div class="form-control mb-2 mr-sm-2" id="EndTime"></div> | ||||||
|  |     </div>   | ||||||
|  |     <div class="form-group"> | ||||||
|  |         <input class="btn btn-primary" type="button" value="Load Headers" id="LoadHeadersButton" /> | ||||||
|  |     </div>   | ||||||
|  |     <div class="form-group"> | ||||||
|  |         <label class="form-check-label" for="chkAutoRefresh"> | ||||||
|  |             Auto-Refresh | ||||||
|  |         </label> | ||||||
|  |         <input class="form-check-input" type="checkbox" id="chkAutoRefresh"> | ||||||
|  |     </div> | ||||||
|  |     <div class="form-group"> | ||||||
|  |         <label class="form-check-label" for="chkCopyOnGet"> | ||||||
|  |             Copy-On-Get | ||||||
|  |         </label> | ||||||
|  |         <input class="form-check-input" type="checkbox" id="chkCopyOnGet"> | ||||||
|  |     </div> | ||||||
|  | </form> | ||||||
|  |  | ||||||
|  | <div style="height: 300px;" id="HeaderGridDiv"> | ||||||
|  |     <span id="ToolTypeID" hidden></span> | ||||||
|  |     <table id="HeaderGrid"></table> | ||||||
|  | </div> | ||||||
|  |  | ||||||
|  | <div class="row" style="margin-top: 10px; margin-bottom: 20px;"> | ||||||
|  |     <div class="col-xs-1"> | ||||||
|  |         <input type="button" class="btn" id="GetDataButton" value="Get Data" disabled /> | ||||||
|  |     </div> | ||||||
|  |     <div class="col-xs-1"> | ||||||
|  |         <input type="button" class="btn" id="ReviewButton" value="Review" disabled /> | ||||||
|  |     </div> | ||||||
|  |     <div class="col-xs-1"> | ||||||
|  |         <input type="button" class="btn" id="RecipeParametersButton" value="Parameters" disabled /> | ||||||
|  |     </div> | ||||||
|  |     <div class="col-xs-1"> | ||||||
|  |         <input type="button" class="btn" id="ViewButton" value="View" disabled /> | ||||||
|  |     </div> | ||||||
|  |     <div class="col-xs-1"> | ||||||
|  |         <input type="button" class="btn" id="PinButton" value="Pin" disabled /> | ||||||
|  |     </div> | ||||||
|  | </div> | ||||||
|  |  | ||||||
|  | <div id="DetailsDiv" hidden> | ||||||
|  |  | ||||||
|  |     <span id="HeaderId" hidden></span> | ||||||
|  |     <span id="HeaderAttachmentId" hidden></span> | ||||||
|  |     <div style="padding-bottom: 20px;" id="DetailsGridDiv"> | ||||||
|  |         <table id="DetailsGrid"></table> | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     <div id="ExportDiv" style="margin-top: 10px;" hidden> | ||||||
|  |         <input type="button" value="Send to OpenInsight" id="OIExportButton" /> | ||||||
|  |         <span id="OIExportResult" style="margin-left: 10px; font-weight: bold; color: #366b02;"></span> | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     <p style="margin-top: 20px;"> | ||||||
|  |         <iframe id="DataAttachmentFrame" style="height:900px; border-width:thin; margin-right: 10px;" hidden></iframe> | ||||||
|  |         <iframe id="HeaderAttachmentFrame" style="height:900px; border-width:thin;" hidden></iframe> | ||||||
|  |           | ||||||
|  |         <div id="DataAttachmentDiv" hidden> | ||||||
|  |             <canvas id="DataAttachmentCanvas"></canvas> | ||||||
|  |         </div> | ||||||
|  |         <div id="HeaderAttachmentDiv" hidden> | ||||||
|  |             <canvas id="HeaderAttachmentCanvas"></canvas> | ||||||
|  |         </div> | ||||||
|  |     </p> | ||||||
|  |  | ||||||
|  | </div> | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  |  | ||||||
|  |     $(document).ready(function () { | ||||||
|  |  | ||||||
|  |         initRunInfo("@ViewBag.ApiUrl", "@Model.ToolTypeID", "@Model.HeaderID", "@Model.HeaderAttachmentID"); | ||||||
|  |  | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  | </script> | ||||||
| @ -103,6 +103,6 @@ | |||||||
|         $("#runDataSheet5").click(function () { runDataSheet(5, $(this).val()) }); |         $("#runDataSheet5").click(function () { runDataSheet(5, $(this).val()) }); | ||||||
|         $("#runDataSheet6").click(function () { runDataSheet(6, $(this).val()) }); |         $("#runDataSheet6").click(function () { runDataSheet(6, $(this).val()) }); | ||||||
|         $("#restartButton").click(function () { restartButton() }); |         $("#restartButton").click(function () { restartButton() }); | ||||||
|         initWorkMaterial("@ViewBag.ApiUrl", ""); |         initWorkMaterial("@ViewBag.ApiUrl"); | ||||||
|     }); |     }); | ||||||
| </script> | </script> | ||||||
|  | |||||||
| @ -6,42 +6,36 @@ | |||||||
|     <meta name="viewport" content="width=device-width" /> |     <meta name="viewport" content="width=device-width" /> | ||||||
|     <title>@ViewBag.Title</title> |     <title>@ViewBag.Title</title> | ||||||
|  |  | ||||||
|     <script src="https://oi-metrology-viewer-prod.mes.infineon.com/js/modernizr-3.6.0-custom.js?no-cache=2024-06-18-10-54" |     <script src="~/js/modernizr-3.6.0-custom.js" type="text/javascript" asp-append-version="true"></script> | ||||||
|         type="text/javascript"></script> |  | ||||||
|  |  | ||||||
|     <link href="https://oi-metrology-viewer-prod.mes.infineon.com/styles/bootstrap.min.css?no-cache=2024-06-18-10-54" |     <link href="~/styles/bootstrap.min.css" rel="stylesheet" asp-append-version="true" /> | ||||||
|         rel="stylesheet" /> |     <link href="~/igniteui/css/themes/bootstrap3/default/infragistics.theme.css" rel="stylesheet" | ||||||
|     <link |         asp-append-version="true" /> | ||||||
|         href="https://oi-metrology-viewer-prod.mes.infineon.com/igniteui/css/themes/bootstrap3/default/infragistics.theme.css?no-cache=2024-06-18-10-54" |     <link href="~/igniteui/css/structure/infragistics.css" rel="stylesheet" asp-append-version="true" /> | ||||||
|         rel="stylesheet" /> |     <link href="~/styles/site.css" rel="stylesheet" asp-append-version="true" /> | ||||||
|     <link |  | ||||||
|         href="https://oi-metrology-viewer-prod.mes.infineon.com/igniteui/css/structure/infragistics.css?no-cache=2024-06-18-10-54" |  | ||||||
|         rel="stylesheet" /> |  | ||||||
|     <link href="https://oi-metrology-viewer-prod.mes.infineon.com/styles/site-server.css?no-cache=2024-06-18-10-54" |  | ||||||
|         rel="stylesheet" /> |  | ||||||
|     <link href="https://oi-metrology-viewer-prod.mes.infineon.com/styles/index.css?no-cache=2024-06-18-10-54" |  | ||||||
|         rel="stylesheet" /> |  | ||||||
|  |  | ||||||
|     <script src="https://oi-metrology-viewer-prod.mes.infineon.com/js/jquery-3.6.0.min.js?no-cache=2024-06-18-10-54" |     <script src="~/js/jquery-3.6.0.min.js" type="text/javascript" asp-append-version="true"></script> | ||||||
|         type="text/javascript"></script> |     <script src="~/js/jquery-ui.min.js" type="text/javascript" asp-append-version="true"></script> | ||||||
|     <script src="https://oi-metrology-viewer-prod.mes.infineon.com/js/jquery-ui.min.js?no-cache=2024-06-18-10-54" |     <script src="~/igniteui/js/infragistics.core.js" type="text/javascript" asp-append-version="true"></script> | ||||||
|         type="text/javascript"></script> |     <script src="~/igniteui/js/infragistics.lob.js" type="text/javascript" asp-append-version="true"></script> | ||||||
|     <script |     <script src="~/igniteui/js/infragistics.dv.js" type="text/javascript" asp-append-version="true"></script> | ||||||
|         src="https://oi-metrology-viewer-prod.mes.infineon.com/igniteui/js/infragistics.core.js?no-cache=2024-06-18-10-54" |  | ||||||
|         type="text/javascript"></script> |  | ||||||
|     <script |  | ||||||
|         src="https://oi-metrology-viewer-prod.mes.infineon.com/igniteui/js/infragistics.lob.js?no-cache=2024-06-18-10-54" |  | ||||||
|         type="text/javascript"></script> |  | ||||||
|     <script |  | ||||||
|         src="https://oi-metrology-viewer-prod.mes.infineon.com/igniteui/js/infragistics.dv.js?no-cache=2024-06-18-10-54" |  | ||||||
|         type="text/javascript"></script> |  | ||||||
|  |  | ||||||
|     <script src="https://oi-metrology-viewer-prod.mes.infineon.com/js/chart-4.3.0.min.js" type="module"></script> |     <script src="~/js/chart-4.3.0.min.js" type="module"></script> | ||||||
|  |  | ||||||
|     <script src="https://oi-metrology-viewer-prod.mes.infineon.com/js/common.js?no-cache=2024-06-18-10-54" |     <script src="~/js/common.js" type="text/javascript" asp-append-version="true"></script> | ||||||
|         type="text/javascript"></script> |     <script src="~/js/site.js" type="text/javascript" asp-append-version="true"></script> | ||||||
|     <script src="https://oi-metrology-viewer-prod.mes.infineon.com/js/site-server.js?no-cache=2024-06-18-10-54" |     <script> | ||||||
|         type="text/javascript"></script> |         $(document).ready(function () { | ||||||
|  |             if (location.pathname == "/") { | ||||||
|  |                 route = "/AwaitingDispo"; | ||||||
|  |             } | ||||||
|  |             else { | ||||||
|  |                 route = location.pathname; | ||||||
|  |             } | ||||||
|  |             $('ul.nav.navbar-nav').find('a[href="' + route + '"]') | ||||||
|  |                 .closest('li').addClass('alert-info'); | ||||||
|  |         }); | ||||||
|  |     </script> | ||||||
| </head> | </head> | ||||||
|  |  | ||||||
| <body> | <body> | ||||||
| @ -63,9 +57,7 @@ | |||||||
|                     <span class="icon-bar"></span> |                     <span class="icon-bar"></span> | ||||||
|                 </button> |                 </button> | ||||||
|                 <div class="navbar-brand"> |                 <div class="navbar-brand"> | ||||||
|                     <a href="https://oi-metrology-viewer-prod.mes.infineon.com"><img |                     <a href="/"><img src="~/images/IFX_LOGO_RGB.png" height="20" /></a> | ||||||
|                             src="https://oi-metrology-viewer-prod.mes.infineon.com/images/IFX_LOGO_RGB.png" |  | ||||||
|                             height="20" /></a> |  | ||||||
|                     OI Metrology Viewer |                     OI Metrology Viewer | ||||||
|                 </div> |                 </div> | ||||||
|             </div> |             </div> | ||||||
| @ -99,10 +91,8 @@ | |||||||
|  |  | ||||||
|     <div id="MessageModal"></div> |     <div id="MessageModal"></div> | ||||||
|  |  | ||||||
|     <script src="https://oi-metrology-viewer-prod.mes.infineon.com/js/bootstrap.min.js?no-cache=2024-06-18-10-54" |     <script src="~/js/bootstrap.min.js" type="text/javascript" asp-append-version="true"></script> | ||||||
|         type="text/javascript"></script> |     <script src="~/js/respond.min.js" type="text/javascript" asp-append-version="true"></script> | ||||||
|     <script src="https://oi-metrology-viewer-prod.mes.infineon.com/js/respond.min.js?no-cache=2024-06-18-10-54" |  | ||||||
|         type="text/javascript"></script> |  | ||||||
|     @RenderSection("scripts", required: false) |     @RenderSection("scripts", required: false) | ||||||
| </body> | </body> | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,198 +0,0 @@ | |||||||
| trigger: |  | ||||||
|   branches: |  | ||||||
|     include: |  | ||||||
|       - master |  | ||||||
|   paths: |  | ||||||
|     include: |  | ||||||
|       - Server |  | ||||||
|  |  | ||||||
| variables: |  | ||||||
|   runtime: 'win-x64' |  | ||||||
|   coreVersion: 'net8.0' |  | ||||||
|   nugetSource: 'https://artifactory.intra.infineon.com/artifactory/api/nuget/ngt-fi-package-main-vir/' |  | ||||||
|  |  | ||||||
| stages: |  | ||||||
|   - stage: Development |  | ||||||
|     displayName: Development |  | ||||||
|     pool: |  | ||||||
|       name: 'OpenInsight Metrology Viewer' |  | ||||||
|       demands: OpenInsight-Metrology-Viewer-Server-Development |  | ||||||
|     variables: |  | ||||||
|       ASPNETCORE_ENVIRONMENT: 'Development' |  | ||||||
|       assemblyTitle: 'OI.Metrology.Server' |  | ||||||
|       configuration: 'Debug' |  | ||||||
|       userSecretsId: 'b0a3891c-b775-422c-80ee-63a2f385045d' |  | ||||||
|     jobs: |  | ||||||
|       - job: DebugDotnet |  | ||||||
|         steps: |  | ||||||
|           - script: | |  | ||||||
|               echo Assembly Title: $(AssemblyTitle) |  | ||||||
|               echo Build Id: $(Build.BuildId) |  | ||||||
|               echo Build Reason: $(Build.Reason) |  | ||||||
|               echo Repo Id: $(Build.Repository.Id) |  | ||||||
|               echo Repo Name: $(Build.Repository.Name) |  | ||||||
|               echo Source Version: $(Build.SourceVersion) |  | ||||||
|               echo Configuration: $(Configuration) |  | ||||||
|               echo Core Version: $(CoreVersion) |  | ||||||
|               echo Nuget Source: $(NugetSource) |  | ||||||
|               echo Runtime: $(Runtime) |  | ||||||
|               echo UserSecretsId: $(UserSecretsId) |  | ||||||
|             displayName: 'Echo Check' |  | ||||||
|  |  | ||||||
|           - script: | |  | ||||||
|               dotnet user-secrets init |  | ||||||
|               dotnet user-secrets set BuildNumber $(Build.BuildId) |  | ||||||
|               dotnet user-secrets set GitCommit $(Build.SourceVersion) |  | ||||||
|               dotnet user-secrets list |  | ||||||
|             workingDirectory: Server |  | ||||||
|             displayName: 'App - Safe storage of app secrets' |  | ||||||
|  |  | ||||||
|           - script: dotnet build --configuration $(Configuration) --source $(NugetSource) |  | ||||||
|             workingDirectory: Server |  | ||||||
|             displayName: 'App - Build' |  | ||||||
|  |  | ||||||
|           - script: dotnet build --configuration $(Configuration) --source $(NugetSource) |  | ||||||
|             workingDirectory: Tests |  | ||||||
|             displayName: 'Tests - Build' |  | ||||||
|  |  | ||||||
|           - script: dotnet test --configuration $(Configuration) |  | ||||||
|             workingDirectory: Tests |  | ||||||
|             displayName: 'Tests - Test' |  | ||||||
|  |  | ||||||
|           - script: dotnet publish --configuration $(Configuration) --runtime $(Runtime) --self-contained |  | ||||||
|             workingDirectory: Server |  | ||||||
|             displayName: 'App - Publish' |  | ||||||
|  |  | ||||||
|           - script: dotnet publish --configuration $(Configuration) --runtime $(Runtime) -p:PublishAot=true |  | ||||||
|             workingDirectory: Server |  | ||||||
|             displayName: 'App - AOT Publish' |  | ||||||
|             enabled: false |  | ||||||
|  |  | ||||||
|           - task: CopyFiles@2 |  | ||||||
|             displayName: 'Copy Files to: D:\' |  | ||||||
|             inputs: |  | ||||||
|               Contents: '*' |  | ||||||
|               SourceFolder: 'Server\bin\$(Configuration)\$(CoreVersion)\$(Runtime)\publish' |  | ||||||
|               TargetFolder: 'D:\$(CoreVersion)\$(Runtime)\$(Build.Repository.Name)\$(Configuration)\$(Build.BuildId)\$(AssemblyTitle)' |  | ||||||
|               OverWrite: true |  | ||||||
|  |  | ||||||
|           - script: dotnet clean --configuration $(Configuration) |  | ||||||
|             workingDirectory: Tests |  | ||||||
|             displayName: 'Tests - Clean' |  | ||||||
|  |  | ||||||
|           - script: dotnet clean --configuration $(Configuration) |  | ||||||
|             workingDirectory: Server |  | ||||||
|  |  | ||||||
|           - script: C:/Windows/system32/inetsrv/appcmd.exe stop apppool /apppool.name:$(AssemblyTitle).$(Configuration) |  | ||||||
|             workingDirectory: Server |  | ||||||
|             displayName: 'Stop Pool' |  | ||||||
|             continueOnError: true |  | ||||||
|  |  | ||||||
|           - script: C:/Windows/system32/inetsrv/appcmd.exe stop site /site.name:$(AssemblyTitle).$(Configuration) |  | ||||||
|             workingDirectory: Server |  | ||||||
|             displayName: 'Stop Website' |  | ||||||
|             continueOnError: true |  | ||||||
|  |  | ||||||
|           - script: rmdir "D:\web-sites\$(AssemblyTitle).$(Configuration)" |  | ||||||
|             workingDirectory: Server |  | ||||||
|             displayName: 'Remove MKLink' |  | ||||||
|             continueOnError: true |  | ||||||
|  |  | ||||||
|           - script: mklink /J "D:\web-sites\$(AssemblyTitle).$(Configuration)" "D:\$(CoreVersion)\$(Runtime)\$(Build.Repository.Name)\$(Configuration)\$(Build.BuildId)\$(AssemblyTitle)" |  | ||||||
|             workingDirectory: Server |  | ||||||
|             displayName: 'Create MKLink' |  | ||||||
|  |  | ||||||
|           - script: mkdir "D:\web-sites\$(AssemblyTitle).$(Configuration)\$(AssemblyTitle).$(Configuration)" |  | ||||||
|             workingDirectory: Server |  | ||||||
|             displayName: 'Make Directory' |  | ||||||
|             continueOnError: true |  | ||||||
|  |  | ||||||
|           - script: (robocopy /E /IS /IT /IM "%USERPROFILE%/AppData/Roaming/Microsoft/UserSecrets/$(UserSecretsId)" "D:\$(CoreVersion)\$(Runtime)\$(Build.Repository.Name)\$(Configuration)\$(Build.BuildId)\$(AssemblyTitle)" secrets.json) ^& IF %ERRORLEVEL% LEQ 7 exit 0 |  | ||||||
|             workingDirectory: Server |  | ||||||
|             displayName: 'Replace User Secrets Id File' |  | ||||||
|  |  | ||||||
|           - script: (robocopy /E /IS /IT /IM "%USERPROFILE%/AppData/Roaming/Microsoft/UserSecrets/$(UserSecretsId)" "D:\$(CoreVersion)\$(Runtime)\$(Build.Repository.Name)\$(Configuration)\$(Build.BuildId)\$(AssemblyTitle)" web.config) ^& IF %ERRORLEVEL% LEQ 7 exit 0 |  | ||||||
|             workingDirectory: Server |  | ||||||
|             displayName: 'Replace Web Configuration File' |  | ||||||
|  |  | ||||||
|           - script: C:/Windows/system32/inetsrv/appcmd.exe start apppool /apppool.name:$(AssemblyTitle).$(Configuration) |  | ||||||
|             workingDirectory: Server |  | ||||||
|             displayName: 'Start Pool' |  | ||||||
|  |  | ||||||
|           - script: C:/Windows/system32/inetsrv/appcmd.exe start site /site.name:$(AssemblyTitle).$(Configuration) |  | ||||||
|             workingDirectory: Server |  | ||||||
|             displayName: 'Start Website' |  | ||||||
|  |  | ||||||
|   - stage: Release |  | ||||||
|     displayName: Release |  | ||||||
|     pool: |  | ||||||
|       name: 'OpenInsight Metrology Viewer' |  | ||||||
|       demands: OpenInsight-Metrology-Viewer-Server |  | ||||||
|     variables: |  | ||||||
|       ASPNETCORE_ENVIRONMENT: 'Production' |  | ||||||
|       assemblyTitle: 'OI.Metrology.Server' |  | ||||||
|       configuration: 'Release' |  | ||||||
|     jobs: |  | ||||||
|       - job: ReleaseDotnet |  | ||||||
|         steps: |  | ||||||
|           - script: | |  | ||||||
|               echo Assembly Title: $(AssemblyTitle) |  | ||||||
|               echo Build Id: $(Build.BuildId) |  | ||||||
|               echo Build Reason: $(Build.Reason) |  | ||||||
|               echo Repo Id: $(Build.Repository.Id) |  | ||||||
|               echo Repo Name: $(Build.Repository.Name) |  | ||||||
|               echo Source Version: $(Build.SourceVersion) |  | ||||||
|               echo Configuration: $(Configuration) |  | ||||||
|               echo Core Version: $(CoreVersion) |  | ||||||
|               echo Nuget Source: $(NugetSource) |  | ||||||
|               echo Runtime: $(Runtime) |  | ||||||
|             displayName: 'Echo Check' |  | ||||||
|  |  | ||||||
|           - script: | |  | ||||||
|               dotnet user-secrets init |  | ||||||
|               dotnet user-secrets set BuildNumber $(Build.BuildId) |  | ||||||
|               dotnet user-secrets set GitCommit $(Build.SourceVersion) |  | ||||||
|               dotnet user-secrets list |  | ||||||
|             workingDirectory: Server |  | ||||||
|             displayName: 'App - Safe storage of app secrets' |  | ||||||
|  |  | ||||||
|           - script: dotnet build --configuration $(Configuration) --source $(NugetSource) |  | ||||||
|             workingDirectory: Server |  | ||||||
|             displayName: 'App - Build' |  | ||||||
|  |  | ||||||
|           - script: dotnet build --configuration $(Configuration) --source $(NugetSource) |  | ||||||
|             workingDirectory: Tests |  | ||||||
|             displayName: 'Tests - Build' |  | ||||||
|  |  | ||||||
|           - script: dotnet test --configuration $(Configuration) |  | ||||||
|             workingDirectory: Tests |  | ||||||
|             displayName: 'Tests - Test' |  | ||||||
|  |  | ||||||
|           - script: dotnet publish --configuration $(Configuration) --runtime $(Runtime) --self-contained |  | ||||||
|             workingDirectory: Server |  | ||||||
|             displayName: 'App - Publish' |  | ||||||
|  |  | ||||||
|           - script: dotnet publish --configuration $(Configuration) --runtime $(Runtime) -p:PublishAot=true |  | ||||||
|             workingDirectory: Server |  | ||||||
|             displayName: 'App - AOT Publish' |  | ||||||
|             enabled: false |  | ||||||
|  |  | ||||||
|           - task: CopyFiles@2 |  | ||||||
|             displayName: 'Copy Files to: D:\' |  | ||||||
|             inputs: |  | ||||||
|               Contents: '*' |  | ||||||
|               SourceFolder: 'Server\bin\$(Configuration)\$(CoreVersion)\$(Runtime)\publish' |  | ||||||
|               TargetFolder: 'D:\$(CoreVersion)\$(Runtime)\$(Build.Repository.Name)\$(Configuration)\$(Build.BuildId)\$(AssemblyTitle)' |  | ||||||
|               OverWrite: true |  | ||||||
|  |  | ||||||
|           - script: dotnet clean --configuration $(Configuration) |  | ||||||
|             workingDirectory: Tests |  | ||||||
|             displayName: 'Tests - Clean' |  | ||||||
|  |  | ||||||
|           - script: dotnet clean --configuration $(Configuration) |  | ||||||
|             workingDirectory: Server |  | ||||||
|             displayName: 'App - Clean' |  | ||||||
|  |  | ||||||
|           - script: 'echo $(Build.SourceVersion)-$(Build.BuildId)>bin_x_x_\$(Configuration)\$(CoreVersion)\win-x64\$(Build.Repository.Name).txt' |  | ||||||
|             displayName: 'Force Fail' |  | ||||||
|             enabled: false |  | ||||||
| Before Width: | Height: | Size: 272 KiB After Width: | Height: | Size: 272 KiB | 
| Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB | 
| Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB | 
| Before Width: | Height: | Size: 210 B After Width: | Height: | Size: 210 B | 
| Before Width: | Height: | Size: 225 B After Width: | Height: | Size: 225 B | 
| Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB | 
| Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB | 
| Before Width: | Height: | Size: 418 B After Width: | Height: | Size: 418 B | 
| Before Width: | Height: | Size: 985 B After Width: | Height: | Size: 985 B | 
| Before Width: | Height: | Size: 964 B After Width: | Height: | Size: 964 B | 
| Before Width: | Height: | Size: 486 B After Width: | Height: | Size: 486 B | 
| Before Width: | Height: | Size: 483 B After Width: | Height: | Size: 483 B | 
| Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB | 
| Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 6.0 KiB | 
| Before Width: | Height: | Size: 999 B After Width: | Height: | Size: 999 B | 
| Before Width: | Height: | Size: 993 B After Width: | Height: | Size: 993 B | 
| Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB | 
| Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB | 
| Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB | 
| Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB | 
| Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB | 
| Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB | 
| Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB | 
| Before Width: | Height: | Size: 986 B After Width: | Height: | Size: 986 B | 
| Before Width: | Height: | Size: 1011 B After Width: | Height: | Size: 1011 B | 
| Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB | 
| Before Width: | Height: | Size: 1009 B After Width: | Height: | Size: 1009 B | 
| Before Width: | Height: | Size: 1017 B After Width: | Height: | Size: 1017 B | 
| Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB | 
| Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB | 
| Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB | 
| Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB | 
| Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB | 
| Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB | 
| Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB | 
| Before Width: | Height: | Size: 1010 B After Width: | Height: | Size: 1010 B | 
| Before Width: | Height: | Size: 1006 B After Width: | Height: | Size: 1006 B | 
| Before Width: | Height: | Size: 995 B After Width: | Height: | Size: 995 B | 
| Before Width: | Height: | Size: 1010 B After Width: | Height: | Size: 1010 B | 
| Before Width: | Height: | Size: 1006 B After Width: | Height: | Size: 1006 B | 
| Before Width: | Height: | Size: 976 B After Width: | Height: | Size: 976 B | 
| Before Width: | Height: | Size: 958 B After Width: | Height: | Size: 958 B | 
| Before Width: | Height: | Size: 965 B After Width: | Height: | Size: 965 B | 
| Before Width: | Height: | Size: 965 B After Width: | Height: | Size: 965 B | 
| Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB | 
| Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB | 
| Before Width: | Height: | Size: 980 B After Width: | Height: | Size: 980 B | 
| Before Width: | Height: | Size: 1016 B After Width: | Height: | Size: 1016 B | 
| Before Width: | Height: | Size: 1013 B After Width: | Height: | Size: 1013 B | 
| Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB | 
| Before Width: | Height: | Size: 978 B After Width: | Height: | Size: 978 B | 
| Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB | 
| Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB | 
| Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB | 
| Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |