diff --git a/.github/workflows/backend-publish-azure.yml b/.github/workflows/backend-publish-azure.yml
index 821a363b..92e407fa 100644
--- a/.github/workflows/backend-publish-azure.yml
+++ b/.github/workflows/backend-publish-azure.yml
@@ -42,14 +42,14 @@ env:
jobs:
build:
- name: Build and Deploy .NET5 Web API
+ name: Build and Deploy .NET6 Web API
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
submodules: true
- name: Set up dotnet Core ${{ env.NETCORE_VERSION }}
- uses: actions/setup-dotnet@v1
+ uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.NETCORE_VERSION }}
- name: Restore dependencies (${{env.SOLUTION_FILE}})
diff --git a/.github/workflows/backend-publish-stage-azure.yml b/.github/workflows/backend-publish-stage-azure.yml
index 1adca9bc..12356fd1 100644
--- a/.github/workflows/backend-publish-stage-azure.yml
+++ b/.github/workflows/backend-publish-stage-azure.yml
@@ -25,6 +25,7 @@ on:
branches:
- develop
- CO5/Develop
+ - PLY/Develop
env:
# set this to your application's name
@@ -47,11 +48,11 @@ jobs:
name: Build and Deploy .NET6 Web API
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
submodules: true
- name: Set up dotnet Core ${{ env.NETCORE_VERSION }}
- uses: actions/setup-dotnet@v1
+ uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.NETCORE_VERSION }}
- name: Restore dependencies (${{env.SOLUTION_FILE}})
diff --git a/.github/workflows/frontend-publish-azure.yml b/.github/workflows/frontend-publish-azure.yml
index f0bd3d81..ac368522 100644
--- a/.github/workflows/frontend-publish-azure.yml
+++ b/.github/workflows/frontend-publish-azure.yml
@@ -38,9 +38,9 @@ jobs:
name: 'Job: Build and Deploy React frontend'
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
- name: Use Node.js ${{ env.NODE_VERSION }}
- uses: actions/setup-node@v1
+ uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 'Build React Code - npm install, build'
diff --git a/.github/workflows/frontend-publish-stage-azure.yml b/.github/workflows/frontend-publish-stage-azure.yml
index 8e31b531..861870be 100644
--- a/.github/workflows/frontend-publish-stage-azure.yml
+++ b/.github/workflows/frontend-publish-stage-azure.yml
@@ -25,6 +25,7 @@ on:
branches:
- develop
- CO5/Develop
+ - PLY/Develop
env:
# set this to your application's name
@@ -40,9 +41,9 @@ jobs:
name: 'Job: Build and Deploy React frontend'
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
- name: Use Node.js ${{ env.NODE_VERSION }}
- uses: actions/setup-node@v1
+ uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: 'Build React Code - npm install, build'
diff --git a/.github/workflows/sonar-cloud-scan-stage.yml b/.github/workflows/sonar-cloud-scan-stage.yml
index e74c3e4d..a63577bf 100644
--- a/.github/workflows/sonar-cloud-scan-stage.yml
+++ b/.github/workflows/sonar-cloud-scan-stage.yml
@@ -11,6 +11,7 @@ on:
branches:
- develop
- CO5/Develop
+ - PLY/Develop
env:
# set this to the organization name, project key in Sonar
@@ -45,12 +46,12 @@ jobs:
steps:
#Set up Java which is needed for SonarScan post processing step
- name: Setup Java JDK
- uses: actions/setup-java@v3.4.0
+ uses: actions/setup-java@v4.2.1
with:
distribution: 'microsoft' # See 'Supported distributions' for available options
- java-version: '11'
+ java-version: '17'
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
with:
# Shallow clones should be disabled for a better relevancy of analysis
fetch-depth: 0
@@ -58,7 +59,7 @@ jobs:
# Speed-up analysis by caching the scanner workspace
- name: SonarScan - Cache SonarCloud workspace
- uses: actions/cache@v1
+ uses: actions/cache@v4
with:
path: ~\.sonar\cache
key: ${{ runner.os }}-sonar-cache
@@ -67,7 +68,7 @@ jobs:
# Speed-up analysis by caching the scanner installation
- name: SonarScan - Cache SonarCloud scanner
id: cache-sonar-scanner
- uses: actions/cache@v1
+ uses: actions/cache@v4
with:
path: ${{env.SONAR_TOOL_PATH}}
key: ${{ runner.os }}-sonar-scanner
diff --git a/.github/workflows/sonar-cloud-scan.yml b/.github/workflows/sonar-cloud-scan.yml
index 7afa1910..9a6c0dcc 100644
--- a/.github/workflows/sonar-cloud-scan.yml
+++ b/.github/workflows/sonar-cloud-scan.yml
@@ -44,12 +44,12 @@ jobs:
steps:
#Set up Java which is needed for SonarScan post processing step
- name: Setup Java JDK
- uses: actions/setup-java@v3.4.0
+ uses: actions/setup-java@v4.2.1
with:
distribution: 'microsoft' # See 'Supported distributions' for available options
- java-version: '11'
+ java-version: '17'
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
with:
# # Shallow clones should be disabled for a better relevancy of analysis
# fetch-depth: 0
@@ -57,7 +57,7 @@ jobs:
# Speed-up analysis by caching the scanner workspace
- name: SonarScan - Cache SonarCloud workspace
- uses: actions/cache@v1
+ uses: actions/cache@v4
with:
path: ~\.sonar\cache
key: ${{ runner.os }}-sonar-cache
@@ -66,7 +66,7 @@ jobs:
# Speed-up analysis by caching the scanner installation
- name: SonarScan - Cache SonarCloud scanner
id: cache-sonar-scanner
- uses: actions/cache@v1
+ uses: actions/cache@v4
with:
path: ${{env.SONAR_TOOL_PATH}}
key: ${{ runner.os }}-sonar-scanner
@@ -85,4 +85,4 @@ jobs:
- name: Build (${{env.SOLUTION_FILE}})
run: dotnet build ${{env.SOLUTION_DIRECTORY}}/${{env.SOLUTION_FILE}} --configuration ${{ env.BUILD_CONFIGURATION }} --no-restore
- name: SonarScan - End (${{env.SONAR_PROJECT_KEY}})
- run: ${{env.SONAR_TOOL_PATH}}\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_ACCESS_TOKEN }}"
\ No newline at end of file
+ run: ${{env.SONAR_TOOL_PATH}}\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_ACCESS_TOKEN }}"
diff --git a/.github/workflows/tests-in-browser.yml b/.github/workflows/tests-in-browser.yml
deleted file mode 100644
index 55745fc4..00000000
--- a/.github/workflows/tests-in-browser.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-# Add to main branch to allow to be seen in other branches.
-# CESMII Profile Designer - Setup and test Profile Designer Web Page using Selenium Tests
-#
-# For more samples to get started with GitHub Action workflows to deploy to Azure, refer to https://github.com/Azure/actions-workflow-samples
-name: Test|In Browser|Profile Designer
-on:
- #manually trigger deploy
- workflow_dispatch:
- # Trigger the workflow on push
- #push:
- # branches:
- # - develop
- # - main
- #pull_request:
- # branches:
- # - develop
- # - main
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 9c29cbce..945f615b 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -10,11 +10,13 @@ on:
branches:
- develop
- CO5/Develop
+ - PLY/Develop
- main
pull_request:
branches:
- develop
- CO5/Develop
+ - PLY/Develop
- main
env:
@@ -34,11 +36,11 @@ jobs:
name: Build and Test .NET6 Web API
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
with:
submodules: true
- name: Set up dotnet Core ${{ env.NETCORE_VERSION }}
- uses: actions/setup-dotnet@v1
+ uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.NETCORE_VERSION }}
diff --git a/README.md b/README.md
index 07cd194a..754e9580 100644
--- a/README.md
+++ b/README.md
@@ -2,10 +2,10 @@
Prerequisites
-
- Install node.js (version > 10.16) - https://nodejs.org/en/
+Install node.js (version > 18.17) - https://nodejs.org/en/
-
- Install npm (version > 5.6) - https://www.npmjs.com/ (note I just upgraded to 7.17 => npm install -g npm)
+Install npm (version > 8.5.4) - https://www.npmjs.com/ (npm install -g npm)
-
React - https://reactjs.org/ - First time React users, install React using create-react-app from a node.js command prompt, a tool that installs all of the dependencies to build and run a full React.js application.
diff --git a/api/CESMII.ProfileDesigner.OpcUa/OpcUaImporter.cs b/api/CESMII.ProfileDesigner.OpcUa/OpcUaImporter.cs
index b5e4387f..538519f5 100644
--- a/api/CESMII.ProfileDesigner.OpcUa/OpcUaImporter.cs
+++ b/api/CESMII.ProfileDesigner.OpcUa/OpcUaImporter.cs
@@ -646,7 +646,7 @@ public async System.Threading.Tasks.Task>>>(searchDataJson);
- var comparer = new SearchInputs.Comparer();
- _searchData = sd.ToDictionary(kv => kv.Key, kv => kv.Value, comparer);
- _lastSavedCount = _searchData.Count;
- }
- }
- else
- {
- _wrapper = wrapper;
- recording = true;
- }
- }
- public Task> GetManyAsync(List identifiers)
- {
- return null;
- }
-
- record SearchInputs
- {
- public string[] Keywords { get; set; }
- public string Cursor { get; set; }
- public bool PageBackwards { get; set; }
- public int? Limit { get; set; }
-
- internal class Comparer : IEqualityComparer
- {
- bool IEqualityComparer.Equals(SearchInputs x, SearchInputs y)
- {
- return x == y ||
- (x.Cursor == y.Cursor
- && x.Limit == y.Limit
- && (x.Keywords == y.Keywords
- || ( x.Keywords != null
- && y.Keywords != null
- && x.Keywords.SequenceEqual(y.Keywords)
- )
- )
- );
- }
-
- int IEqualityComparer.GetHashCode(SearchInputs obj)
- {
- if (obj == null) return 0;
- unchecked
- {
- return obj.Cursor?.GetHashCode() ?? 0 + obj.Limit.GetHashCode() + obj.Keywords?.Aggregate(0, (s, k) =>
- {
- unchecked
- {
- return s + k.GetHashCode();
- }
- }) ?? 0;
- }
- }
- }
- }
- static Dictionary> _searchData = new Dictionary>(new SearchInputs.Comparer());
- static int _lastSavedCount = 0;
- private bool disposedValue;
-
- public OnResolveNodeSets OnResolveNodeSets { get; set; }
- public OnNodeSet OnDownloadNodeSet { get; set; }
- public OnNodeSet OnNodeSetFound { get; set; }
- public OnNodeSet OnNodeSetNotFound { get; set; }
-
- public async Task> SearchAsync(int? limit, string cursor, bool pageBackwards, List keywords, List exclude, bool noTotalCount)
- {
- var inputs = new SearchInputs
- {
- Keywords = keywords?.ToArray(),
- Cursor = cursor,
- PageBackwards = pageBackwards,
- Limit = limit,
- };
- if (_wrapper != null)
- {
- var result = await _wrapper.SearchAsync(limit, cursor, pageBackwards, keywords, exclude, noTotalCount);
-
- if (!_searchData.ContainsKey(inputs))
- {
- _searchData.Add(inputs, result);
- }
- return result;
- }
- if (_searchData.TryGetValue(inputs, out var data))
- {
- return data;
- }
- throw new Exception($"Request not in mock data: {inputs}");
- }
-
-
- public Task DownloadAsync(string id)
- {
- throw new System.NotImplementedException();
- }
-
- public Task> ResolveNodeSetsAsync(List missingModels)
- {
- return Task.FromResult(new List().AsEnumerable());
- }
-
-
- public Task GetAsync(string modelUri, DateTime? publicationDate, bool exactMatch)
- {
- return Task.FromResult(null);
- }
-
-
- protected virtual void Dispose(bool disposing)
- {
- if (!disposedValue)
- {
- if (disposing)
- {
- // dispose managed state (managed objects)
- }
-
- // free unmanaged resources (unmanaged objects) and override finalizer
- // set large fields to null
- if (recording && _searchData.Any() && _searchData.Count != _lastSavedCount)
- {
- try
- {
- var toSave = _searchData.ToList();
- File.WriteAllText(strSearchDataFile, JsonConvert.SerializeObject(toSave));
- _lastSavedCount = toSave.Count;
- }
- catch (Exception)
- {
- // ignore
- }
- }
- disposedValue = true;
- }
- }
-
- ~CloudLibMock()
- {
- // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
- Dispose(disposing: false);
- }
-
- public void Dispose()
- {
- // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
- Dispose(disposing: true);
- GC.SuppressFinalize(this);
- }
-
- public Task UploadAsync(UANameSpace uaNamespace)
- {
- throw new NotImplementedException();
- }
-
- public Task> GetNodeSetsPendingApprovalAsync(int? limit, string cursor, bool pageBackwards, bool noTotalCount = false, UAProperty prop = null)
- {
- throw new NotImplementedException();
- }
- public Task UpdateApprovalStatusAsync(string nodeSetId, string newStatus, string statusInfo, UAProperty additionalProperty = null)
- {
- throw new NotImplementedException();
- }
-
- public Task GetAsync(string identifier)
- {
- throw new NotImplementedException();
- }
-
- }
-}
+using CESMII.OpcUa.NodeSetImporter;
+using CESMII.Common.CloudLibClient;
+using Newtonsoft.Json;
+using Opc.Ua.Cloud.Library.Client;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace CESMII.ProfileDesigner.Api.Tests
+{
+ public class CloudLibMock : ICloudLibWrapper, IDisposable
+ {
+ private readonly ICloudLibWrapper _wrapper;
+ static bool recording = false;
+ const string strSearchDataFile = "CloudLibMock/Searchdata.json";
+ public CloudLibMock()
+ {
+ }
+
+ public CloudLibMock(CloudLibWrapper wrapper)
+ {
+ if (!recording && File.Exists(strSearchDataFile))
+ {
+ if (_searchData?.Any() != true)
+ {
+ var searchDataJson = File.ReadAllText(strSearchDataFile);
+ var sd = JsonConvert.DeserializeObject
>>>(searchDataJson);
+ var comparer = new SearchInputs.Comparer();
+ _searchData = sd.ToDictionary(kv => kv.Key, kv => kv.Value, comparer);
+ _lastSavedCount = _searchData.Count;
+ }
+ }
+ else
+ {
+ _wrapper = wrapper;
+ recording = true;
+ }
+ }
+ public Task> GetManyAsync(List identifiers)
+ {
+ return null;
+ }
+
+ record SearchInputs
+ {
+ public string[] Keywords { get; set; }
+ public string Cursor { get; set; }
+ public bool PageBackwards { get; set; }
+ public int? Limit { get; set; }
+
+ internal class Comparer : IEqualityComparer
+ {
+ bool IEqualityComparer.Equals(SearchInputs x, SearchInputs y)
+ {
+ return x == y ||
+ (x.Cursor == y.Cursor
+ && x.Limit == y.Limit
+ && (x.Keywords == y.Keywords
+ || ( x.Keywords != null
+ && y.Keywords != null
+ && x.Keywords.SequenceEqual(y.Keywords)
+ )
+ )
+ );
+ }
+
+ int IEqualityComparer.GetHashCode(SearchInputs obj)
+ {
+ if (obj == null) return 0;
+ unchecked
+ {
+ return obj.Cursor?.GetHashCode() ?? 0 + obj.Limit.GetHashCode() + obj.Keywords?.Aggregate(0, (s, k) =>
+ {
+ unchecked
+ {
+ return s + k.GetHashCode();
+ }
+ }) ?? 0;
+ }
+ }
+ }
+ }
+ static Dictionary> _searchData = new Dictionary>(new SearchInputs.Comparer());
+ static int _lastSavedCount = 0;
+ private bool disposedValue;
+
+ public OnResolveNodeSets OnResolveNodeSets { get; set; }
+ public OnNodeSet OnDownloadNodeSet { get; set; }
+ public OnNodeSet OnNodeSetFound { get; set; }
+ public OnNodeSet OnNodeSetNotFound { get; set; }
+
+ public async Task> SearchAsync(int? limit, string cursor, bool pageBackwards, List keywords, List exclude, bool noTotalCount, object? order)
+ {
+ var inputs = new SearchInputs
+ {
+ Keywords = keywords?.ToArray(),
+ Cursor = cursor,
+ PageBackwards = pageBackwards,
+ Limit = limit,
+ };
+ if (_wrapper != null)
+ {
+ var result = await _wrapper.SearchAsync(limit, cursor, pageBackwards, keywords, exclude, noTotalCount, order);
+
+ if (!_searchData.ContainsKey(inputs))
+ {
+ _searchData.Add(inputs, result);
+ }
+ return result;
+ }
+ if (_searchData.TryGetValue(inputs, out var data))
+ {
+ return data;
+ }
+ throw new Exception($"Request not in mock data: {inputs}");
+ }
+
+ public async Task> SearchAsync(int? limit, string cursor, bool pageBackwards, List keywords, List exclude, bool noTotalCount)
+ {
+ var inputs = new SearchInputs
+ {
+ Keywords = keywords?.ToArray(),
+ Cursor = cursor,
+ PageBackwards = pageBackwards,
+ Limit = limit,
+ };
+ if (_wrapper != null)
+ {
+ var result = await _wrapper.SearchAsync(limit, cursor, pageBackwards, keywords, exclude, noTotalCount);
+
+ if (!_searchData.ContainsKey(inputs))
+ {
+ _searchData.Add(inputs, result);
+ }
+ return result;
+ }
+ if (_searchData.TryGetValue(inputs, out var data))
+ {
+ return data;
+ }
+ throw new Exception($"Request not in mock data: {inputs}");
+ }
+
+
+ public Task DownloadAsync(string id)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public Task> ResolveNodeSetsAsync(List missingModels)
+ {
+ return Task.FromResult(new List().AsEnumerable());
+ }
+
+
+ public Task GetAsync(string modelUri, DateTime? publicationDate, bool exactMatch)
+ {
+ return Task.FromResult(null);
+ }
+
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposedValue)
+ {
+ if (disposing)
+ {
+ // dispose managed state (managed objects)
+ }
+
+ // free unmanaged resources (unmanaged objects) and override finalizer
+ // set large fields to null
+ if (recording && _searchData.Any() && _searchData.Count != _lastSavedCount)
+ {
+ try
+ {
+ var toSave = _searchData.ToList();
+ File.WriteAllText(strSearchDataFile, JsonConvert.SerializeObject(toSave));
+ _lastSavedCount = toSave.Count;
+ }
+ catch (Exception)
+ {
+ // ignore
+ }
+ }
+ disposedValue = true;
+ }
+ }
+
+ ~CloudLibMock()
+ {
+ // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
+ Dispose(disposing: false);
+ }
+
+ public void Dispose()
+ {
+ // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
+
+ public Task UploadAsync(UANameSpace uaNamespace)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task> GetNodeSetsPendingApprovalAsync(int? limit, string cursor, bool pageBackwards, bool noTotalCount = false, UAProperty prop = null)
+ {
+ throw new NotImplementedException();
+ }
+ public Task UpdateApprovalStatusAsync(string nodeSetId, string newStatus, string statusInfo, UAProperty additionalProperty = null)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task GetAsync(string identifier)
+ {
+ throw new NotImplementedException();
+ }
+
+ }
+}
diff --git a/common b/common
index fc95d1e4..0eb7c7e4 160000
--- a/common
+++ b/common
@@ -1 +1 @@
-Subproject commit fc95d1e44ea15f8a867ae7f61861d6ac6c54be62
+Subproject commit 0eb7c7e4a91b1d1b08d412d300385a0cd034fe42