Skip to content

Commit 9fa1b06

Browse files
authored
Merge pull request #127 from cesmii/CO5/Develop
Co5/develop --> Develop
2 parents bce369d + 0957799 commit 9fa1b06

File tree

11 files changed

+280
-27
lines changed

11 files changed

+280
-27
lines changed

.github/workflows/frontend-publish-azure.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,16 @@ env:
3131
BUILD_OUTPUT_DIRECTORY: './frontend/build'
3232
WORKING_DIRECTORY: 'frontend'
3333
# set this to the node version to use
34-
NODE_VERSION: '14.17.3'
34+
NODE_VERSION: '16.x'
3535

3636
jobs:
3737
Build-and-Deploy-FrontEnd:
3838
name: 'Job: Build and Deploy React frontend'
3939
runs-on: ubuntu-latest
4040
steps:
41-
- uses: actions/checkout@v2
41+
- uses: actions/checkout@v4
4242
- name: Use Node.js ${{ env.NODE_VERSION }}
43-
uses: actions/setup-node@v1
43+
uses: actions/setup-node@v4
4444
with:
4545
node-version: ${{ env.NODE_VERSION }}
4646
- name: 'Build React Code - npm install, build'

.github/workflows/frontend-publish-stage-azure.yml

+5-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ on:
2424
push:
2525
branches:
2626
- develop
27+
- CO5/Develop
28+
- PLY/Develop
2729

2830
env:
2931
# set this to your application's name
@@ -32,16 +34,16 @@ env:
3234
BUILD_OUTPUT_DIRECTORY: './frontend/build'
3335
WORKING_DIRECTORY: 'frontend'
3436
# set this to the node version to use
35-
NODE_VERSION: '14.17.3'
37+
NODE_VERSION: '16.x'
3638

3739
jobs:
3840
Build-and-Deploy-FrontEnd:
3941
name: 'Job: Build and Deploy React frontend'
4042
runs-on: ubuntu-latest
4143
steps:
42-
- uses: actions/checkout@v2
44+
- uses: actions/checkout@v4
4345
- name: Use Node.js ${{ env.NODE_VERSION }}
44-
uses: actions/setup-node@v1
46+
uses: actions/setup-node@v4
4547
with:
4648
node-version: ${{ env.NODE_VERSION }}
4749
- name: 'Build React Code - npm install, build'

.github/workflows/sonar-cloud-scan-stage.yml

+7-5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ on:
1010
push:
1111
branches:
1212
- develop
13+
- CO5/Develop
14+
- PLY/Develop
1315

1416
env:
1517
# set this to the organization name, project key in Sonar
@@ -44,20 +46,20 @@ jobs:
4446
steps:
4547
#Set up Java which is needed for SonarScan post processing step
4648
- name: Setup Java JDK
47-
uses: actions/setup-java@v3.4.0
49+
uses: actions/setup-java@v4.2.1
4850
with:
4951
distribution: 'microsoft' # See 'Supported distributions' for available options
50-
java-version: '11'
52+
java-version: '17'
5153

52-
- uses: actions/checkout@v2
54+
- uses: actions/checkout@v4
5355
with:
5456
# Shallow clones should be disabled for a better relevancy of analysis
5557
fetch-depth: 0
5658
submodules: true
5759

5860
# Speed-up analysis by caching the scanner workspace
5961
- name: SonarScan - Cache SonarCloud workspace
60-
uses: actions/cache@v1
62+
uses: actions/cache@v4
6163
with:
6264
path: ~\.sonar\cache
6365
key: ${{ runner.os }}-sonar-cache
@@ -66,7 +68,7 @@ jobs:
6668
# Speed-up analysis by caching the scanner installation
6769
- name: SonarScan - Cache SonarCloud scanner
6870
id: cache-sonar-scanner
69-
uses: actions/cache@v1
71+
uses: actions/cache@v4
7072
with:
7173
path: ${{env.SONAR_TOOL_PATH}}
7274
key: ${{ runner.os }}-sonar-scanner

.github/workflows/sonar-cloud-scan.yml

+6-6
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,20 @@ jobs:
4444
steps:
4545
#Set up Java which is needed for SonarScan post processing step
4646
- name: Setup Java JDK
47-
uses: actions/setup-java@v3.4.0
47+
uses: actions/setup-java@v4.2.1
4848
with:
4949
distribution: 'microsoft' # See 'Supported distributions' for available options
50-
java-version: '11'
50+
java-version: '17'
5151

52-
- uses: actions/checkout@v2
52+
- uses: actions/checkout@v4
5353
with:
5454
# # Shallow clones should be disabled for a better relevancy of analysis
5555
# fetch-depth: 0
5656
submodules: true
5757

5858
# Speed-up analysis by caching the scanner workspace
5959
- name: SonarScan - Cache SonarCloud workspace
60-
uses: actions/cache@v1
60+
uses: actions/cache@v4
6161
with:
6262
path: ~\.sonar\cache
6363
key: ${{ runner.os }}-sonar-cache
@@ -66,7 +66,7 @@ jobs:
6666
# Speed-up analysis by caching the scanner installation
6767
- name: SonarScan - Cache SonarCloud scanner
6868
id: cache-sonar-scanner
69-
uses: actions/cache@v1
69+
uses: actions/cache@v4
7070
with:
7171
path: ${{env.SONAR_TOOL_PATH}}
7272
key: ${{ runner.os }}-sonar-scanner
@@ -85,4 +85,4 @@ jobs:
8585
- name: Build (${{env.SOLUTION_FILE}})
8686
run: dotnet build ${{env.SOLUTION_DIRECTORY}}/${{env.SOLUTION_FILE}} --configuration ${{ env.BUILD_CONFIGURATION }} --no-restore
8787
- name: SonarScan - End (${{env.SONAR_PROJECT_KEY}})
88-
run: ${{env.SONAR_TOOL_PATH}}\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_ACCESS_TOKEN }}"
88+
run: ${{env.SONAR_TOOL_PATH}}\dotnet-sonarscanner end /d:sonar.login="${{ secrets.SONAR_ACCESS_TOKEN }}"

README.md

+56
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,59 @@ Install npm (version > 8.5.4) - https://www.npmjs.com/ (npm install -g npm)
8282
</p>
8383
</li>
8484
</ol>
85+
<p>
86+
## Directories
87+
- \api - This contains a .NET web API back end for profile designer. Within this solution, the OPC translations will occur, database connections will occur, etc.
88+
- \frontend - This contains the REACT front end for profile designer.
89+
- \SampleNodeSets - This contains nodesets that we use to import into system. Any OPC UA compliant nodeset is permitted. These are stored just for convenience while developing within the system.
90+
- \sql - This contains the SQL script used to generate the DB structure and insert required lookup data as well as some sample users.
91+
92+
## How to Build
93+
- Clone the repo from GIT.
94+
95+
If you have an older clone that is missing the common submodule:
96+
```ps
97+
cd c:\sources\cesmii\profiledesigner
98+
git submodule add https://github.com/cesmii/cesmii-common
99+
```
100+
101+
- **Build/Run the front end:**
102+
```powershell
103+
cd \frontend
104+
npm install
105+
npm run start
106+
```
107+
- Verify the site is running in a browser: http://localhost:3000
108+
109+
> **Note**
110+
>
111+
> The ENV files in the root React folder point to the base URL for the web API.
112+
> Login: The login process was intentionally simple. Use cesmii/cesmii to login.
113+
114+
115+
- **Build/Run the back end API (.NET 6 Solution):**
116+
- Standard .NET build and run.
117+
118+
- **PostgreSql DB**
119+
See above for initial install instructions.
120+
- Run pgAdmin
121+
- Create local DB (see AppSettings.json for database name.)
122+
- Open the Query Tool (Tools menu)
123+
- Open the CESMII-Profile-Designer\sql\CESMII.ProfileDesigner.DB.sql file
124+
- Create the cesmii role/login and the database (comment out everything except the create role and create database sections and run the script)
125+
- Open a query tool on the newly created database and run the rest of the script
126+
- Change the password on the cesmii login to match the one in the appsettings.development.json file.
127+
128+
## Run Profile Designer, Market Place and Cloud Library locally
129+
130+
### Profile Designer: Front End port 3002, API port 5004
131+
132+
1. Add a frontend/.env.development file with the following entries/content:
133+
```
134+
REACT_APP_BASE_API_URL=https://localhost:5004/api
135+
PORT=3002
136+
```
137+
138+
2. Change
139+
140+
</p>

api/CESMII.ProfileDesigner.Api/Controllers/AuthController.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -239,4 +239,4 @@ public IActionResult QueryCurrentOrganization()
239239
}
240240

241241
}
242-
}
242+
}

api/CESMII.ProfileDesigner.DAL/LookupDataTypeDAL.cs

+11-6
Original file line numberDiff line numberDiff line change
@@ -53,20 +53,25 @@ ProfileTypeDefinitionDAL _profileTypeDefinitionDAL
5353
}
5454
public override LookupDataType CheckForExisting(LookupDataTypeModel model, UserToken userToken, bool cacheOnly = false)
5555
{
56-
var entityResult = base.FindByCondition(userToken, dt =>
57-
(
58-
(model.ID != 0 && model.ID != null && dt.ID == model.ID)
56+
//2024-08-12
57+
//Issue - FIX - must also consider owner id match unless match comes from a core nodeset (/ua or /ua/di).
58+
// We were having scenario if user 1 imports a nodeset A and then user 2 imports the same nodeset A, some of the attribute
59+
// custom type of user 1's nodeset are getting assigned to user B.
60+
var matches = base.FindByCondition(userToken, dt =>
61+
((model.ID != 0 && model.ID != null && dt.ID == model.ID)
5962
|| ( dt.Name == model.Name && dt.Code == model.Code
6063
&& (( (model.CustomTypeId ?? 0) != 0&& (dt.CustomTypeId ?? 0) != 0 && dt.CustomTypeId == model.CustomTypeId)
6164
|| (model.CustomType != null &&
6265
dt.CustomType.Profile.Namespace == model.CustomType.Profile.Namespace
6366
&& dt.CustomType.Profile.PublishDate == model.CustomType.Profile.PublishDate
6467
&& dt.CustomType.Profile.Version == model.CustomType.Profile.Version
6568
&& dt.CustomType.OpcNodeId == model.CustomType.OpcNodeId
66-
))))
69+
)))) &&
70+
(dt.CustomType == null || !dt.CustomType.OwnerId.HasValue || dt.CustomType.OwnerId.Value == userToken.UserId)
6771
, cacheOnly);
68-
var entity = entityResult?.FirstOrDefault();
69-
return entity;
72+
73+
var result = matches?.FirstOrDefault();
74+
return result;
7075
}
7176

7277
public override async Task<int?> UpdateAsync(LookupDataTypeModel model, UserToken userToken)

api/CESMII.ProfileDesigner.DAL/ProfileTypeDefinitionDAL.cs

+18-2
Original file line numberDiff line numberDiff line change
@@ -1302,6 +1302,7 @@ public async Task UpgradeToProfileAsync(ProfileModel profileModel,
13021302

13031303
// Parent
13041304
var profileTypes = _repo.GetAll().Where(pt => pt.Profile.Namespace != existingProfile.Namespace && pt.Parent.Profile == existingProfile).ToList();
1305+
_logger.Info($"Upgrade Info || Parent || profileTypes count: {profileTypes.Count()}");
13051306
foreach (var profileType in profileTypes)
13061307
{
13071308
var newParent = _repo.GetAll().FirstOrDefault(pt => pt.Profile == profile && pt.OpcNodeId == profileType.Parent.OpcNodeId);
@@ -1315,6 +1316,7 @@ public async Task UpgradeToProfileAsync(ProfileModel profileModel,
13151316

13161317
// InstanceParent
13171318
profileTypes = _repo.GetAll().Where(pt => pt.Profile.Namespace != existingProfile.Namespace && pt.InstanceParent.Profile == existingProfile).ToList();
1319+
_logger.Info($"Upgrade Info || Instance Parent || profileTypes count: {profileTypes.Count()}");
13181320
foreach (var profileType in profileTypes)
13191321
{
13201322
var newInstanceParent = _repo.GetAll().FirstOrDefault(pt => pt.Profile == profile && pt.OpcNodeId == profileType.InstanceParent.OpcNodeId);
@@ -1328,6 +1330,7 @@ public async Task UpgradeToProfileAsync(ProfileModel profileModel,
13281330

13291331
// VariableDataTypeId
13301332
profileTypes = _repo.GetAll().Where(pt => pt.Profile.Namespace != existingProfile.Namespace && pt.VariableDataType.Profile == existingProfile).ToList();
1333+
_logger.Info($"Upgrade Info || Variable Data Type || profileTypes count: {profileTypes.Count()}");
13311334
foreach (var profileType in profileTypes)
13321335
{
13331336
var newVariableType = _repo.GetAll().FirstOrDefault(pt => pt.Profile == profile && pt.OpcNodeId == profileType.VariableDataType.OpcNodeId);
@@ -1344,6 +1347,7 @@ public async Task UpgradeToProfileAsync(ProfileModel profileModel,
13441347
// data type id
13451348
var attributes = _repo.GetAll().Where(pt => pt.Profile.Namespace != existingProfile.Namespace)
13461349
.SelectMany(pt => pt.Attributes).Where(a => a.DataType.CustomType.Profile == existingProfile).ToList();
1350+
_logger.Info($"Upgrade Info || Profile Attributes || count: {attributes.Count()}");
13471351
foreach (var attribute in attributes)
13481352
{
13491353
var newCustomDataType = _repo.GetAll().FirstOrDefault(pt => pt.Profile == profile && pt.OpcNodeId == attribute.DataType.CustomType.OpcNodeId);
@@ -1359,6 +1363,7 @@ public async Task UpgradeToProfileAsync(ProfileModel profileModel,
13591363
// variable type definition id
13601364
attributes = _repo.GetAll().Where(pt => pt.Profile.Namespace != existingProfile.Namespace)
13611365
.SelectMany(pt => pt.Attributes).Where(a => a.VariableTypeDefinition.Profile == existingProfile).ToList();
1366+
_logger.Info($"Upgrade Info || Variable Type Definition Attributes || count: {attributes.Count()}");
13621367
foreach (var attribute in attributes)
13631368
{
13641369
var newVariableType = _repo.GetAll().FirstOrDefault(pt => pt.Profile == profile && pt.OpcNodeId == attribute.VariableTypeDefinition.OpcNodeId);
@@ -1374,6 +1379,7 @@ public async Task UpgradeToProfileAsync(ProfileModel profileModel,
13741379
// composition
13751380
var compositions = _repo.GetAll().Where(pt => pt.Profile.Namespace != existingProfile.Namespace)
13761381
.SelectMany(pt => pt.Compositions).Where(c => c.Composition.Profile == existingProfile).ToList();
1382+
_logger.Info($"Upgrade Info || Compositions || count: {compositions.Count()}");
13771383
foreach (var composition in compositions)
13781384
{
13791385
var newComposition = _repo.GetAll().FirstOrDefault(pt => pt.Profile == profile && pt.OpcNodeId == composition.Composition.OpcNodeId);
@@ -1390,6 +1396,7 @@ public async Task UpgradeToProfileAsync(ProfileModel profileModel,
13901396
// interface_id
13911397
var interfaces = _repo.GetAll().Where(pt => pt.Profile.Namespace != existingProfile.Namespace)
13921398
.SelectMany(pt => pt.Interfaces).Where(itf => itf.Interface.Profile == existingProfile).ToList();
1399+
_logger.Info($"Upgrade Info || Interfaces || count: {interfaces.Count()}");
13931400
foreach (var itf in interfaces)
13941401
{
13951402
var newInterface = _repo.GetAll().FirstOrDefault(pt => pt.Profile == profile && pt.OpcNodeId == itf.Interface.OpcNodeId);
@@ -1404,6 +1411,7 @@ public async Task UpgradeToProfileAsync(ProfileModel profileModel,
14041411
// Move over user analytics
14051412
{
14061413
var ptAnalyticsRecords = ptAnalyticsRepo.GetAll().Where(pta => pta.ProfileTypeDefinition.Profile == existingProfile).ToList();
1414+
_logger.Info($"Upgrade Info || Analytics || count: {ptAnalyticsRecords.Count()}");
14071415
foreach (var ptAnalyticsRecord in ptAnalyticsRecords)
14081416
{
14091417
var ptaNew = ptAnalyticsRepo.GetAll().Where(pta => pta.ProfileTypeDefinition.Profile == profile && pta.ProfileTypeDefinition.OpcNodeId == ptAnalyticsRecord.ProfileTypeDefinition.OpcNodeId).FirstOrDefault();
@@ -1423,17 +1431,22 @@ public async Task UpgradeToProfileAsync(ProfileModel profileModel,
14231431
// Move over user favorites
14241432
{
14251433
var ptFavoritesRecords = ptFavoritesRepo.GetAll().Where(pta => pta.ProfileTypeDefinition.Profile == existingProfile).ToList();
1434+
_logger.Info($"Upgrade Info || Favorites || count: {ptFavoritesRecords.Count()}");
14261435
foreach (var ptFavoritesRecord in ptFavoritesRecords)
14271436
{
14281437
var ptfNew = ptFavoritesRepo.GetAll().Where(pta => pta.ProfileTypeDefinition.Profile == profile && pta.ProfileTypeDefinition.OpcNodeId == ptFavoritesRecord.ProfileTypeDefinition.OpcNodeId).FirstOrDefault();
1429-
ptfNew.IsFavorite = ptFavoritesRecord.IsFavorite;
1430-
ptFavoritesRepo.Update(ptfNew);
1438+
if (ptfNew != null)
1439+
{
1440+
ptfNew.IsFavorite = ptFavoritesRecord.IsFavorite;
1441+
ptFavoritesRepo.Update(ptfNew);
1442+
}
14311443
}
14321444
}
14331445
// Move over data type rank
14341446
// TODO actually migrate this: it is currently just a read-only view at the Repo/EF level so the Add/Update calls are commented out
14351447
{
14361448
var allDataTypeRanks = dtRankRepo.GetAll().ToList();
1449+
_logger.Info($"Upgrade Info || Data Type Rank || count: {allDataTypeRanks.Count()}");
14371450
foreach (var dtRank in allDataTypeRanks)
14381451
{
14391452
if (dtRank.CustomTypeId == null)
@@ -1481,8 +1494,11 @@ public async Task UpgradeToProfileAsync(ProfileModel profileModel,
14811494
}
14821495
}
14831496

1497+
_logger.Info($"Upgrade Info || SaveChangesAsync...start");
14841498
await _repo.SaveChangesAsync();
1499+
_logger.Info($"Upgrade Info || SaveChangesAsync...complete");
14851500
await _repo.CommitTransactionAsync();
1501+
_logger.Info($"Upgrade Info || CommitTransactionAsync...complete");
14861502
}
14871503
if (deleteUpgradedProfiles)
14881504
{

api/CESMII.ProfileDesigner.OpcUa/OpcUaImporter.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,7 @@ public async System.Threading.Tasks.Task<Dictionary<string, ProfileTypeDefinitio
643643
string exportedNodeSetXml;
644644
using (MemoryStream ms = new())
645645
{
646-
using (StreamWriter writer = new(ms, Encoding.UTF8))
646+
using (StreamWriter writer = new(ms, new UTF8Encoding(false)))
647647
{
648648
try
649649
{

frontend/src/components/OnLoginHandler.js

+1
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ export const onAADLogin = (setLoadingProps) => {
117117
//get current search criteria data
118118
setLoadingProps({
119119
loginStatusCode: 200,
120+
refreshLookupData: true,
120121
refreshSearchCriteria: true,
121122
refreshProfileSearchCriteria: true,
122123
refreshCloudLibImporterSearchCriteria: true,

0 commit comments

Comments
 (0)