From 7c120c78bd72efe1b0b9b61296e1f86ef2d84299 Mon Sep 17 00:00:00 2001 From: Jostein Taklo Date: Mon, 19 Aug 2024 12:41:21 +0200 Subject: [PATCH] feat: remove order and islegacy flag (#704) Co-authored-by: Jossilainen --- .changeset/pr-704-2022804484.md | 9 + .../OnboardApp/OnboardAppCommand.cs | 7 +- .../UpdateOnboardedAppCommand.cs | 6 +- .../CreatePortal/CreatePortalCommand.cs | 7 +- .../UpdatePortal/UpdatePortalCommand.cs | 6 +- .../Queries/OnboardedApps/OnboardedAppDto.cs | 2 - .../Portals/GetPortals/GetPortalsQuery.cs | 1 - .../Queries/Portals/PortalDto.cs | 3 +- .../Entities/OnboardedApp.cs | 23 +- .../Entities/Portal.cs | 7 +- ...alAndIsLegacyFromOnboardedApps.Designer.cs | 323 ++++++++++++++++++ ...rFromPortalAndIsLegacyFromOnboardedApps.cs | 51 +++ ...jectExecutionPortalContextModelSnapshot.cs | 11 +- .../OnboardedApp/ApiOnboardAppRequest.cs | 7 +- .../OnboardedApp/ApiOnboardedApp.cs | 4 - .../ApiUpdateOnboardedAppRequest.cs | 8 +- .../Portal/ApiCreatePortalRequest.cs | 6 +- .../ViewModels/Portal/ApiPortal.cs | 2 - .../Portal/ApiUpdatePortalRequest.cs | 6 +- .../Data/OnboardedAppsData.cs | 12 +- .../Data/PortalData.cs | 6 +- .../IntegrationTests/AssertHelpers.cs | 2 - .../OnboardedAppControllerTests.cs | 14 +- .../IntegrationTests/PortalControllerTests.cs | 8 +- 24 files changed, 417 insertions(+), 114 deletions(-) create mode 100644 .changeset/pr-704-2022804484.md create mode 100644 backend/src/Equinor.ProjectExecutionPortal.Infrastructure/Migrations/20240815131013_RemoveOrderFromPortalAndIsLegacyFromOnboardedApps.Designer.cs create mode 100644 backend/src/Equinor.ProjectExecutionPortal.Infrastructure/Migrations/20240815131013_RemoveOrderFromPortalAndIsLegacyFromOnboardedApps.cs diff --git a/.changeset/pr-704-2022804484.md b/.changeset/pr-704-2022804484.md new file mode 100644 index 000000000..d8fd9657e --- /dev/null +++ b/.changeset/pr-704-2022804484.md @@ -0,0 +1,9 @@ + +--- +"fusion-project-portal": patch +--- +Order and IsLegacy is removed from Onboarded apps. Order is removed from Portal. + + +> [!IMPORTANT] +> This change requires database migration. diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/OnboardedApps/OnboardApp/OnboardAppCommand.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/OnboardedApps/OnboardApp/OnboardAppCommand.cs index 386b885da..470e2ab95 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/OnboardedApps/OnboardApp/OnboardAppCommand.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/OnboardedApps/OnboardApp/OnboardAppCommand.cs @@ -10,15 +10,13 @@ namespace Equinor.ProjectExecutionPortal.Application.Commands.OnboardedApps.Onbo public class OnboardAppCommand : IRequest { - public OnboardAppCommand(string appKey, bool isLegacy, IList? contextTypes) + public OnboardAppCommand(string appKey, IList? contextTypes) { AppKey = appKey; - IsLegacy = isLegacy; ContextTypes = contextTypes; } public string AppKey { get; } - public bool IsLegacy { get; } public IList? ContextTypes { get; set; } public class Handler : IRequestHandler @@ -50,7 +48,7 @@ public async Task Handle(OnboardAppCommand command, CancellationToken canc throw new InvalidActionException($"Onboarded app: {command.AppKey} is already onboarded"); } - var onboardedApp = new OnboardedApp(command.AppKey, 0, command.IsLegacy); + var onboardedApp = new OnboardedApp(command.AppKey); try { @@ -61,7 +59,6 @@ public async Task Handle(OnboardAppCommand command, CancellationToken canc throw new InvalidOperationException(ex.Message); } - _readWriteContext.Set().Add(onboardedApp); await _readWriteContext.SaveChangesAsync(cancellationToken); diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/OnboardedApps/UpdateOnboardedApp/UpdateOnboardedAppCommand.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/OnboardedApps/UpdateOnboardedApp/UpdateOnboardedAppCommand.cs index c537e59d8..bc2c94675 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/OnboardedApps/UpdateOnboardedApp/UpdateOnboardedAppCommand.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/OnboardedApps/UpdateOnboardedApp/UpdateOnboardedAppCommand.cs @@ -9,15 +9,13 @@ namespace Equinor.ProjectExecutionPortal.Application.Commands.OnboardedApps.Upda public class UpdateOnboardedAppCommand : IRequest { - public UpdateOnboardedAppCommand(string appKey, bool isLegacy, IList? contextTypes) + public UpdateOnboardedAppCommand(string appKey, IList? contextTypes) { AppKey = appKey; - IsLegacy = isLegacy; ContextTypes = contextTypes; } public string AppKey { get; } - public bool IsLegacy { get; } public IList? ContextTypes { get; set; } public class Handler : IRequestHandler @@ -42,8 +40,6 @@ public async Task Handle(UpdateOnboardedAppCommand command, CancellationTo throw new NotFoundException("App is not onboarded", command.AppKey); } - entity.Update(command.IsLegacy); - try { entity.AddContextTypes(await _contextTypeService.GetContextTypesByContextTypeKey(command.ContextTypes, cancellationToken)); diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/CreatePortal/CreatePortalCommand.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/CreatePortal/CreatePortalCommand.cs index 77dff862b..5a047035e 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/CreatePortal/CreatePortalCommand.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/CreatePortal/CreatePortalCommand.cs @@ -1,6 +1,5 @@ using Equinor.ProjectExecutionPortal.Application.Helpers; using Equinor.ProjectExecutionPortal.Application.Services.ContextTypeService; -using Equinor.ProjectExecutionPortal.Domain.Common.Exceptions; using Equinor.ProjectExecutionPortal.Domain.Entities; using Equinor.ProjectExecutionPortal.Infrastructure; using MediatR; @@ -9,13 +8,12 @@ namespace Equinor.ProjectExecutionPortal.Application.Commands.Portals.CreatePort public class CreatePortalCommand : IRequest { - public CreatePortalCommand(string name, string shortName, string subText, string? description, int order, string icon, IList contextTypes) + public CreatePortalCommand(string name, string shortName, string subText, string? description, string icon, IList contextTypes) { Name = name; ShortName = shortName; SubText = subText; Description = description; - Order = order; Icon = icon; ContextTypes = contextTypes; } @@ -24,7 +22,6 @@ public CreatePortalCommand(string name, string shortName, string subText, string public string ShortName { get; set; } public string SubText { get; set; } public string? Description { get; set; } - public int Order { get; set; } public string Icon { get; set; } public IList ContextTypes { get; set; } @@ -43,7 +40,7 @@ public async Task Handle(CreatePortalCommand command, CancellationToken ca { var slug = SlugHelper.Sluggify(command.Name); - var portal = new Portal(slug, command.Name, command.ShortName, command.SubText, command.Description, command.Order, command.Icon); + var portal = new Portal(slug, command.Name, command.ShortName, command.SubText, command.Description, command.Icon); portal.AddContextTypes(await _contextTypeService.GetContextTypesByContextTypeKey(command.ContextTypes, cancellationToken)); diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/UpdatePortal/UpdatePortalCommand.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/UpdatePortal/UpdatePortalCommand.cs index 87f3905fa..5fa890bd2 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/UpdatePortal/UpdatePortalCommand.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Commands/Portals/UpdatePortal/UpdatePortalCommand.cs @@ -10,14 +10,13 @@ namespace Equinor.ProjectExecutionPortal.Application.Commands.Portals.UpdatePort public class UpdatePortalCommand : IRequest { - public UpdatePortalCommand(Guid id, string name, string shortName, string subText, string? description, int order, string icon, IList? contextTypes) + public UpdatePortalCommand(Guid id, string name, string shortName, string subText, string? description, string icon, IList? contextTypes) { Id = id; Name = name; ShortName = shortName; SubText = subText; Description = description; - Order = order; Icon = icon; ContextTypes = contextTypes; } @@ -27,7 +26,6 @@ public UpdatePortalCommand(Guid id, string name, string shortName, string subTex public string ShortName { get; } public string SubText { get; } public string? Description { get; set; } - public int Order { get; } public string Icon { get; } public IList? ContextTypes { get; set; } @@ -55,7 +53,7 @@ public async Task Handle(UpdatePortalCommand command, CancellationToken ca var slug = SlugHelper.Sluggify(command.Name); - entity.Update(slug, command.Name, command.ShortName, command.SubText, command.Description, command.Order, command.Icon); + entity.Update(slug, command.Name, command.ShortName, command.SubText, command.Description, command.Icon); entity.AddContextTypes(await _contextTypeService.GetContextTypesByContextTypeKey(command.ContextTypes, cancellationToken)); diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/OnboardedApps/OnboardedAppDto.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/OnboardedApps/OnboardedAppDto.cs index 265593aa3..7aad27559 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/OnboardedApps/OnboardedAppDto.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/OnboardedApps/OnboardedAppDto.cs @@ -14,8 +14,6 @@ public class OnboardedAppDto : IMapFrom { public Guid Id { get; set; } public string AppKey { get; set; } - public int Order { get; set; } - public bool IsLegacy { get; set; } public FusionPortalAppInformation? AppInformation { get; set; } public IList ContextTypes { get; set; } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortals/GetPortalsQuery.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortals/GetPortalsQuery.cs index c9286f053..0a9cea133 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortals/GetPortalsQuery.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/GetPortals/GetPortalsQuery.cs @@ -26,7 +26,6 @@ public Handler(IReadWriteContext context, IMapper mapper) public async Task> Handle(GetPortalsQuery request, CancellationToken cancellationToken) { var entities = await _context.Set() - .OrderBy(x => x.Order) .AsNoTracking() .Include(x => x.ContextTypes) .ToListAsync(cancellationToken); diff --git a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/PortalDto.cs b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/PortalDto.cs index ef90fce21..9d5cf0f1c 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/PortalDto.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Application/Queries/Portals/PortalDto.cs @@ -11,9 +11,8 @@ public class PortalDto : IMapFrom public string ShortName { get; set; } public string SubText { get; set; } public string? Description { get; set; } - public int Order { get; set; } public string Icon { get; set; } - public IList ContextTypes { get; set; } + public IList ContextTypes { get; set; } public List Apps { get; set; } } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Domain/Entities/OnboardedApp.cs b/backend/src/Equinor.ProjectExecutionPortal.Domain/Entities/OnboardedApp.cs index 9722c98da..b8df6b70d 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Domain/Entities/OnboardedApp.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Domain/Entities/OnboardedApp.cs @@ -5,43 +5,24 @@ namespace Equinor.ProjectExecutionPortal.Domain.Entities; /// /// An onboarded app is an app that is ready for use for the project portal. -/// These apps can then be added to Work Surfaces /// public class OnboardedApp : AuditableEntityBase, ICreationAuditable, IModificationAuditable { public const int AppKeyLengthMax = 200; private readonly List _contextTypes = new(); - public OnboardedApp(string appKey, int order, bool isLegacy) + public OnboardedApp(string appKey) { AppKey = appKey; - Order = order; - IsLegacy = isLegacy; } /// - /// AppKey referes to the app's unique ID in the Fusion Portal + /// AppKey refers to the app's unique ID in the Fusion Portal /// public string AppKey { get; set; } - /// - /// For ordering apps, not used per now - /// - public int Order { get; set; } - - /// - /// This flag is used for conditional rendering of legacy apps on the client application - /// - public bool IsLegacy { get; set; } - - public IReadOnlyCollection ContextTypes => _contextTypes.AsReadOnly(); - public void Update(bool isLegacy) - { - IsLegacy = isLegacy; - } - public void AddContextTypes(IList contextTypes) { _contextTypes.Clear(); diff --git a/backend/src/Equinor.ProjectExecutionPortal.Domain/Entities/Portal.cs b/backend/src/Equinor.ProjectExecutionPortal.Domain/Entities/Portal.cs index aa39aa329..93da45021 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Domain/Entities/Portal.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Domain/Entities/Portal.cs @@ -17,14 +17,13 @@ public class Portal : AuditableEntityBase, ICreationAuditable, IModificationAudi private readonly List _apps = new(); private readonly List _contextTypes = new(); - public Portal(string key, string name, string shortName, string subText, string? description, int order, string icon) + public Portal(string key, string name, string shortName, string subText, string? description, string icon) { Key = key; Name = name; ShortName = shortName; SubText = subText; Description = description; - Order = order; Icon = icon; } @@ -33,20 +32,18 @@ public Portal(string key, string name, string shortName, string subText, string? public string ShortName { get; set; } public string SubText { get; set; } public string? Description { get; set; } - public int Order { get; set; } public string Icon { get; set; } public IReadOnlyCollection Apps => _apps.AsReadOnly(); public IReadOnlyCollection ContextTypes => _contextTypes.AsReadOnly(); - public void Update(string key, string name, string shortName, string subText, string? description, int order, string icon) + public void Update(string key, string name, string shortName, string subText, string? description, string icon) { Key = key; Name = name; ShortName = shortName; SubText = subText; Description = description; - Order = order; Icon = icon; } diff --git a/backend/src/Equinor.ProjectExecutionPortal.Infrastructure/Migrations/20240815131013_RemoveOrderFromPortalAndIsLegacyFromOnboardedApps.Designer.cs b/backend/src/Equinor.ProjectExecutionPortal.Infrastructure/Migrations/20240815131013_RemoveOrderFromPortalAndIsLegacyFromOnboardedApps.Designer.cs new file mode 100644 index 000000000..e569b4a22 --- /dev/null +++ b/backend/src/Equinor.ProjectExecutionPortal.Infrastructure/Migrations/20240815131013_RemoveOrderFromPortalAndIsLegacyFromOnboardedApps.Designer.cs @@ -0,0 +1,323 @@ +// +using System; +using Equinor.ProjectExecutionPortal.Infrastructure; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Equinor.ProjectExecutionPortal.Infrastructure.Migrations +{ + [DbContext(typeof(ProjectExecutionPortalContext))] + [Migration("20240815131013_RemoveOrderFromPortalAndIsLegacyFromOnboardedApps")] + partial class RemoveOrderFromPortalAndIsLegacyFromOnboardedApps + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("ContextTypeOnboardedApp", b => + { + b.Property("ContextTypesId") + .HasColumnType("uniqueidentifier"); + + b.Property("OnboardedAppsId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("ContextTypesId", "OnboardedAppsId"); + + b.HasIndex("OnboardedAppsId"); + + b.ToTable("OnboardedAppContextTypes", (string)null); + }); + + modelBuilder.Entity("ContextTypePortal", b => + { + b.Property("ContextTypesId") + .HasColumnType("uniqueidentifier"); + + b.Property("PortalsId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("ContextTypesId", "PortalsId"); + + b.HasIndex("PortalsId"); + + b.ToTable("PortalContextTypes", (string)null); + }); + + modelBuilder.Entity("Equinor.ProjectExecutionPortal.Domain.Entities.ContextType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ContextTypeKey") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("CreatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("CreatedByAzureOid") + .HasColumnType("uniqueidentifier"); + + b.Property("ModifiedAtUtc") + .HasColumnType("datetime2"); + + b.Property("ModifiedByAzureOid") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("ContextTypeKey") + .IsUnique(); + + b.ToTable("ContextTypes"); + }); + + modelBuilder.Entity("Equinor.ProjectExecutionPortal.Domain.Entities.OnboardedApp", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AppKey") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("CreatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("CreatedByAzureOid") + .HasColumnType("uniqueidentifier"); + + b.Property("ModifiedAtUtc") + .HasColumnType("datetime2"); + + b.Property("ModifiedByAzureOid") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("AppKey") + .IsUnique(); + + b.ToTable("OnboardedApps"); + }); + + modelBuilder.Entity("Equinor.ProjectExecutionPortal.Domain.Entities.OnboardedContext", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("CreatedByAzureOid") + .HasColumnType("uniqueidentifier"); + + b.Property("Description") + .HasMaxLength(4000) + .HasColumnType("nvarchar(4000)"); + + b.Property("ExternalId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ModifiedAtUtc") + .HasColumnType("datetime2"); + + b.Property("ModifiedByAzureOid") + .HasColumnType("uniqueidentifier"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("ExternalId") + .IsUnique(); + + b.ToTable("OnboardedContexts"); + }); + + modelBuilder.Entity("Equinor.ProjectExecutionPortal.Domain.Entities.Portal", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("CreatedByAzureOid") + .HasColumnType("uniqueidentifier"); + + b.Property("Description") + .HasMaxLength(4000) + .HasColumnType("nvarchar(4000)"); + + b.Property("Icon") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ModifiedAtUtc") + .HasColumnType("datetime2"); + + b.Property("ModifiedByAzureOid") + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ShortName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("SubText") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("Key") + .IsUnique(); + + b.ToTable("Portals"); + }); + + modelBuilder.Entity("Equinor.ProjectExecutionPortal.Domain.Entities.PortalApp", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedAtUtc") + .HasColumnType("datetime2"); + + b.Property("CreatedByAzureOid") + .HasColumnType("uniqueidentifier"); + + b.Property("IsHidden") + .HasColumnType("bit"); + + b.Property("ModifiedAtUtc") + .HasColumnType("datetime2"); + + b.Property("ModifiedByAzureOid") + .HasColumnType("uniqueidentifier"); + + b.Property("OnboardedAppId") + .HasColumnType("uniqueidentifier"); + + b.Property("OnboardedContextId") + .HasColumnType("uniqueidentifier"); + + b.Property("PortalId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("OnboardedAppId"); + + b.HasIndex("OnboardedContextId"); + + b.HasIndex("PortalId"); + + b.ToTable("PortalApps"); + }); + + modelBuilder.Entity("ContextTypeOnboardedApp", b => + { + b.HasOne("Equinor.ProjectExecutionPortal.Domain.Entities.ContextType", null) + .WithMany() + .HasForeignKey("ContextTypesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Equinor.ProjectExecutionPortal.Domain.Entities.OnboardedApp", null) + .WithMany() + .HasForeignKey("OnboardedAppsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ContextTypePortal", b => + { + b.HasOne("Equinor.ProjectExecutionPortal.Domain.Entities.ContextType", null) + .WithMany() + .HasForeignKey("ContextTypesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Equinor.ProjectExecutionPortal.Domain.Entities.Portal", null) + .WithMany() + .HasForeignKey("PortalsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Equinor.ProjectExecutionPortal.Domain.Entities.PortalApp", b => + { + b.HasOne("Equinor.ProjectExecutionPortal.Domain.Entities.OnboardedApp", "OnboardedApp") + .WithMany() + .HasForeignKey("OnboardedAppId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Equinor.ProjectExecutionPortal.Domain.Entities.OnboardedContext", "OnboardedContext") + .WithMany("Apps") + .HasForeignKey("OnboardedContextId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Equinor.ProjectExecutionPortal.Domain.Entities.Portal", "Portal") + .WithMany("Apps") + .HasForeignKey("PortalId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("OnboardedApp"); + + b.Navigation("OnboardedContext"); + + b.Navigation("Portal"); + }); + + modelBuilder.Entity("Equinor.ProjectExecutionPortal.Domain.Entities.OnboardedContext", b => + { + b.Navigation("Apps"); + }); + + modelBuilder.Entity("Equinor.ProjectExecutionPortal.Domain.Entities.Portal", b => + { + b.Navigation("Apps"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/backend/src/Equinor.ProjectExecutionPortal.Infrastructure/Migrations/20240815131013_RemoveOrderFromPortalAndIsLegacyFromOnboardedApps.cs b/backend/src/Equinor.ProjectExecutionPortal.Infrastructure/Migrations/20240815131013_RemoveOrderFromPortalAndIsLegacyFromOnboardedApps.cs new file mode 100644 index 000000000..7ea330d88 --- /dev/null +++ b/backend/src/Equinor.ProjectExecutionPortal.Infrastructure/Migrations/20240815131013_RemoveOrderFromPortalAndIsLegacyFromOnboardedApps.cs @@ -0,0 +1,51 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Equinor.ProjectExecutionPortal.Infrastructure.Migrations +{ + /// + public partial class RemoveOrderFromPortalAndIsLegacyFromOnboardedApps : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Order", + table: "Portals"); + + migrationBuilder.DropColumn( + name: "IsLegacy", + table: "OnboardedApps"); + + migrationBuilder.DropColumn( + name: "Order", + table: "OnboardedApps"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Order", + table: "Portals", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "IsLegacy", + table: "OnboardedApps", + type: "bit", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "Order", + table: "OnboardedApps", + type: "int", + nullable: false, + defaultValue: 0); + } + } +} diff --git a/backend/src/Equinor.ProjectExecutionPortal.Infrastructure/Migrations/ProjectExecutionPortalContextModelSnapshot.cs b/backend/src/Equinor.ProjectExecutionPortal.Infrastructure/Migrations/ProjectExecutionPortalContextModelSnapshot.cs index 7e4ca0671..49a500c8c 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.Infrastructure/Migrations/ProjectExecutionPortalContextModelSnapshot.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.Infrastructure/Migrations/ProjectExecutionPortalContextModelSnapshot.cs @@ -17,7 +17,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "8.0.4") + .HasAnnotation("ProductVersion", "8.0.7") .HasAnnotation("Relational:MaxIdentifierLength", 128); SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); @@ -100,18 +100,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("CreatedByAzureOid") .HasColumnType("uniqueidentifier"); - b.Property("IsLegacy") - .HasColumnType("bit"); - b.Property("ModifiedAtUtc") .HasColumnType("datetime2"); b.Property("ModifiedByAzureOid") .HasColumnType("uniqueidentifier"); - b.Property("Order") - .HasColumnType("int"); - b.HasKey("Id"); b.HasIndex("AppKey") @@ -196,9 +190,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasMaxLength(200) .HasColumnType("nvarchar(200)"); - b.Property("Order") - .HasColumnType("int"); - b.Property("ShortName") .IsRequired() .HasMaxLength(50) diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/OnboardedApp/ApiOnboardAppRequest.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/OnboardedApp/ApiOnboardAppRequest.cs index a09e42849..502c065bd 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/OnboardedApp/ApiOnboardAppRequest.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/OnboardedApp/ApiOnboardAppRequest.cs @@ -6,12 +6,11 @@ namespace Equinor.ProjectExecutionPortal.WebApi.ViewModels.OnboardedApp public class ApiOnboardAppRequest { public string AppKey { get; set; } = null!; - public bool IsLegacy { get; set; } public IList? ContextTypes { get; set; } public OnboardAppCommand ToCommand() { - return new OnboardAppCommand(AppKey, IsLegacy, ContextTypes); + return new OnboardAppCommand(AppKey, ContextTypes); } public class OnboardAppRequestValidator : AbstractValidator @@ -22,10 +21,6 @@ public OnboardAppRequestValidator() .NotEmpty() .NotContainScriptTag() .WithMessage("AppKey is required"); - - RuleFor(x => x.IsLegacy) - .NotNull() - .WithMessage("IsLegacy is required"); } } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/OnboardedApp/ApiOnboardedApp.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/OnboardedApp/ApiOnboardedApp.cs index 7c1ef041d..5abe1f52a 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/OnboardedApp/ApiOnboardedApp.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/OnboardedApp/ApiOnboardedApp.cs @@ -12,8 +12,6 @@ public ApiOnboardedApp(OnboardedAppDto onboardedAppDto) { Id = onboardedAppDto.Id; AppKey = onboardedAppDto.AppKey; - Order = onboardedAppDto.Order; - IsLegacy = onboardedAppDto.IsLegacy; Name = onboardedAppDto.AppInformation?.Name; Description = onboardedAppDto.AppInformation?.Description; Contexts = onboardedAppDto.ContextTypes.Select(x => new ApiContextType(x)).ToList(); @@ -22,8 +20,6 @@ public ApiOnboardedApp(OnboardedAppDto onboardedAppDto) public Guid Id { get; set; } public string AppKey { get; set; } = null!; - public int Order { get; set; } - public bool IsLegacy { get; set; } public string? Name { get; set; } public string? Description { get; set; } public IList Contexts { get; set; } diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/OnboardedApp/ApiUpdateOnboardedAppRequest.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/OnboardedApp/ApiUpdateOnboardedAppRequest.cs index bcfc7f6a8..894649014 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/OnboardedApp/ApiUpdateOnboardedAppRequest.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/OnboardedApp/ApiUpdateOnboardedAppRequest.cs @@ -1,26 +1,22 @@ using Equinor.ProjectExecutionPortal.Application.Commands.OnboardedApps.UpdateOnboardedApp; -using Equinor.ProjectExecutionPortal.Application.Queries.OnboardedContexts.GetOnboardedContext; using FluentValidation; namespace Equinor.ProjectExecutionPortal.WebApi.ViewModels.OnboardedApp { public class ApiUpdateOnboardedAppRequest { - public bool IsLegacy { get; set; } public IList? ContextTypes { get; set; } public UpdateOnboardedAppCommand ToCommand(string appKey) { - return new UpdateOnboardedAppCommand(appKey, IsLegacy, ContextTypes); + return new UpdateOnboardedAppCommand(appKey, ContextTypes); } public class ApiUpdateOnboardedAppRequestValidator : AbstractValidator { public ApiUpdateOnboardedAppRequestValidator() { - RuleFor(x => x.IsLegacy) - .NotNull() - .WithMessage("IsLegacy is required"); + } } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/Portal/ApiCreatePortalRequest.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/Portal/ApiCreatePortalRequest.cs index fe9761b6f..d2c926784 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/Portal/ApiCreatePortalRequest.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/Portal/ApiCreatePortalRequest.cs @@ -10,13 +10,12 @@ public class ApiCreatePortalRequest public string ShortName { get; set; } = null!; public string Subtext { get; set; } = null!; public string? Description { get; set; } - public int Order { get; set; } public string Icon { get; set; } = null!; public IList? ContextTypes { get; set; } public CreatePortalCommand ToCommand() { - return new CreatePortalCommand(Name, ShortName, Subtext, Description, Order, Icon, ContextTypes); + return new CreatePortalCommand(Name, ShortName, Subtext, Description, Icon, ContextTypes); } public class CreatePortalRequestValidator : AbstractValidator @@ -42,9 +41,6 @@ public CreatePortalRequestValidator() .NotContainScriptTag() .MaximumLength(Domain.Entities.Portal.DescriptionLengthMax); - RuleFor(x => x.Order) - .NotEmpty() - .WithMessage("Order required"); } } } diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/Portal/ApiPortal.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/Portal/ApiPortal.cs index bf805356c..9b0486db5 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/Portal/ApiPortal.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/Portal/ApiPortal.cs @@ -16,7 +16,6 @@ public ApiPortal(PortalDto portalDto) ShortName = portalDto.ShortName; Subtext = portalDto.SubText; Description = portalDto.Description; - Order = portalDto.Order; Icon = portalDto.Icon; Contexts = portalDto.ContextTypes.Select(x => new ApiContextType(x)).ToList(); Apps = portalDto.Apps.Select(x => new ApiPortalApp(x)).ToList(); @@ -28,7 +27,6 @@ public ApiPortal(PortalDto portalDto) public string ShortName { get; set; } = null!; public string Subtext { get; set; } = null!; public string? Description { get; set; } - public int Order { get; set; } public string Icon { get; set; } = null!; public IList Contexts { get; set; } public List Apps { get; set; } = null!; diff --git a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/Portal/ApiUpdatePortalRequest.cs b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/Portal/ApiUpdatePortalRequest.cs index 62f33876b..80badb11f 100644 --- a/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/Portal/ApiUpdatePortalRequest.cs +++ b/backend/src/Equinor.ProjectExecutionPortal.WebApi/ViewModels/Portal/ApiUpdatePortalRequest.cs @@ -9,13 +9,12 @@ public class ApiUpdatePortalRequest public string ShortName { get; set; } = null!; public string Subtext { get; set; } = null!; public string? Description { get; set; } - public int Order { get; set; } public string Icon { get; set; } = null!; public IList? ContextTypes { get; set; } public UpdatePortalCommand ToCommand(Guid id) { - return new UpdatePortalCommand(id, Name, ShortName, Subtext, Description, Order, Icon, ContextTypes); + return new UpdatePortalCommand(id, Name, ShortName, Subtext, Description, Icon, ContextTypes); } public class UpdatePortalRequestValidator : AbstractValidator @@ -41,9 +40,6 @@ public UpdatePortalRequestValidator() .NotContainScriptTag() .MaximumLength(Domain.Entities.Portal.DescriptionLengthMax); - RuleFor(x => x.Order) - .NotEmpty() - .WithMessage("Order required"); } } } diff --git a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/OnboardedAppsData.cs b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/OnboardedAppsData.cs index 2e64352c0..6d4d04001 100644 --- a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/OnboardedAppsData.cs +++ b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/OnboardedAppsData.cs @@ -6,12 +6,12 @@ internal class OnboardedAppsData { public class InitialSeedData { - public static OnboardedApp MeetingsApp = new("meetings", 0, false); - public static OnboardedApp ReviewsApp = new("reviews", 1, false); - public static OnboardedApp TasksApp = new("tasks", 2, false); - public static OnboardedApp OrgChartApp = new("one-equinor", 3, false); - public static OnboardedApp HandoverGardenApp = new("handover-garden", 4, false); - public static OnboardedApp WorkOrderGardenApp = new("workorder-garden", 5, false); + public static OnboardedApp MeetingsApp = new("meetings"); + public static OnboardedApp ReviewsApp = new("reviews"); + public static OnboardedApp TasksApp = new("tasks"); + public static OnboardedApp OrgChartApp = new("one-equinor"); + public static OnboardedApp HandoverGardenApp = new("handover-garden"); + public static OnboardedApp WorkOrderGardenApp = new("workorder-garden"); } } } diff --git a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/PortalData.cs b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/PortalData.cs index 1d34a10a1..3c2f78c0d 100644 --- a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/PortalData.cs +++ b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/Data/PortalData.cs @@ -6,9 +6,9 @@ internal class PortalData { public class InitialSeedData { - public static Portal Portal1 = new("portfolio-management", "Portfolio Management", "< DG 3", "Here you can find all the tools that you need", "A description", 0, ""); - public static Portal Portal2 = new("project-execution", "Project Execution", "DG 3 - DG 4", "Go to this phase to work with projects that are beyond DG3", "A description", 1, ""); - public static Portal Portal3 = new("another-phase", "Another phase", "DG X", "Some other sub text", "A description", 2, ""); + public static Portal Portal1 = new("portfolio-management", "Portfolio Management", "< DG 3", "Here you can find all the tools that you need", "A description",""); + public static Portal Portal2 = new("project-execution", "Project Execution", "DG 3 - DG 4", "Go to this phase to work with projects that are beyond DG3", "A description", ""); + public static Portal Portal3 = new("another-phase", "Another phase", "DG X", "Some other sub text", "A description", ""); } } } diff --git a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/AssertHelpers.cs b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/AssertHelpers.cs index aaf8e0805..c0541ae4f 100644 --- a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/AssertHelpers.cs +++ b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/AssertHelpers.cs @@ -18,7 +18,6 @@ public static void AssertPortalValues(ApiPortal? portal) Assert.IsNotNull(portal.Name); Assert.IsNotNull(portal.Icon); Assert.IsNotNull(portal.Key); - Assert.IsNotNull(portal.Order); Assert.IsNotNull(portal.ShortName); Assert.IsNotNull(portal.Subtext); Assert.IsNotNull(portal.Description); @@ -45,7 +44,6 @@ public static void AssertOnboardedAppValues(ApiOnboardedApp? app) } Assert.IsNotNull(app.AppKey); - Assert.IsNotNull(app.IsLegacy); } } } diff --git a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/OnboardedAppControllerTests.cs b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/OnboardedAppControllerTests.cs index 8c809513c..a05a952ae 100644 --- a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/OnboardedAppControllerTests.cs +++ b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/OnboardedAppControllerTests.cs @@ -92,7 +92,6 @@ public async Task Add_Valid_OnboardedApp_AsAdministratorUser_ShouldReturnOk() var payload = new ApiOnboardAppRequest { AppKey = "test-app", - IsLegacy = false, ContextTypes = new List() {"ProjectMaster"} }; @@ -116,7 +115,6 @@ public async Task Add_Valid_OnboardedApp_AsAuthenticatedUser_ShouldReturnForbidd var payload = new ApiOnboardAppRequest { AppKey = "test-app", - IsLegacy = false }; // Act @@ -133,7 +131,6 @@ public async Task Add_Valid_OnboardedApp_AsAnonymousUser_ShouldReturnUnauthorize var payload = new ApiOnboardAppRequest { AppKey = "test-app", - IsLegacy = false }; // Act @@ -150,8 +147,7 @@ public async Task Add_Invalid_OnboardedApp_AsAdministratorUser_ShouldThrowExepti // Arrange var payload = new ApiOnboardAppRequest { - AppKey = "i-do-not-exist-in-fusion", - IsLegacy = false + AppKey = "i-do-not-exist-in-fusion" }; // Act @@ -167,8 +163,7 @@ public async Task Add_Duplicate_OnboardedApp_AsAdministratorUser_ShouldThrowExce // Arrange var payload = new ApiOnboardAppRequest { - AppKey = OnboardedAppsData.InitialSeedData.OrgChartApp.AppKey, - IsLegacy = false + AppKey = OnboardedAppsData.InitialSeedData.OrgChartApp.AppKey }; // Act @@ -187,9 +182,8 @@ public async Task Update_OnboardedApp_AsAdministratorUser_ShouldReturnOk() var payload = new ApiUpdateOnboardedAppRequest { - IsLegacy = false, ContextTypes = new List() {} - + }; // Act @@ -201,7 +195,6 @@ public async Task Update_OnboardedApp_AsAdministratorUser_ShouldReturnOk() Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); Assert.AreEqual(theOneToUpdate.AppKey, theOneAfterUpdate.AppKey); - Assert.AreEqual(theOneToUpdate.IsLegacy, theOneAfterUpdate.IsLegacy); Assert.AreEqual(theOneToUpdate.Contexts.Count, theOneAfterUpdate.Contexts.Count); } @@ -239,7 +232,6 @@ public async Task Remove_OnboardedApp_AsAdministratorUser_ShouldReturnOk() var payload = new ApiOnboardAppRequest { AppKey = "app-to-be-removed", - IsLegacy = false, ContextTypes = new List() { "ProjectMaster" } }; diff --git a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/PortalControllerTests.cs b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/PortalControllerTests.cs index 7631dd460..a966a012b 100644 --- a/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/PortalControllerTests.cs +++ b/backend/src/tests/Equinor.ProjectExecutionPortal.Tests.WebApi/IntegrationTests/PortalControllerTests.cs @@ -39,7 +39,7 @@ public async Task Get_Portal_AsAuthenticatedUser_ShouldReturnOk() { // Arrange var portals = await AssertGetAllPortals(UserType.Authenticated, HttpStatusCode.OK); - var portalToTest = portals?.Single(x => x.Order == 1); + var portalToTest = portals?.FirstOrDefault(); // Act & Assert await AssertGetPortal(portalToTest!.Id, UserType.Authenticated, HttpStatusCode.OK); @@ -70,7 +70,7 @@ public async Task Get_OnlyGlobalAppsForPortal_WithoutContext_AsAuthenticatedUser { // Arrange var portals = await AssertGetAllPortals(UserType.Authenticated, HttpStatusCode.OK); - var portalToTest = portals?.Single(x => x.Order == 1); + var portalToTest = portals?.FirstOrDefault(); // Act var apps = await AssertGetAppsForPortal(portalToTest!.Id, null, null, UserType.Authenticated, HttpStatusCode.OK); @@ -87,7 +87,7 @@ public async Task Get_BothGlobalAndContextAppsForPortal_WithValidContext_AsAuthe { // Arrange var portals = await AssertGetAllPortals(UserType.Authenticated, HttpStatusCode.OK); - var portalToTest = portals?.Single(x => x.Order == 1); + var portalToTest = portals?.FirstOrDefault(); // Act var apps = await AssertGetAppsForPortal(portalToTest!.Id, FusionContextData.InitialSeedData.JcaContextExternalId, FusionContextData.InitialSeedData.ContextType,UserType.Authenticated, HttpStatusCode.OK); @@ -104,7 +104,7 @@ public async Task Get_BothGlobalAndContextAppsForPortal_WithInvalidContext_AsAut { // Arrange var portals = await AssertGetAllPortals(UserType.Authenticated, HttpStatusCode.OK); - var portalToTest = portals?.Single(x => x.Order == 1); + var portalToTest = portals?.FirstOrDefault(); // Act var apps = await AssertGetAppsForPortal(portalToTest!.Id, FusionContextData.InitialSeedData.InvalidContextExternalId, FusionContextData.InitialSeedData.ContextType,UserType.Authenticated, HttpStatusCode.OK);