diff --git a/backend/webapi.tests/Features/Parties/Demographics.cs b/backend/webapi.tests/Features/Parties/Demographics.cs index 364d65d5c..1c055f67d 100644 --- a/backend/webapi.tests/Features/Parties/Demographics.cs +++ b/backend/webapi.tests/Features/Parties/Demographics.cs @@ -9,7 +9,7 @@ namespace PidpTests.Features.Parties; public class DemographicsTests : InMemoryDbTest { [Fact] - public async void UpdatePartyDemographics_NewParty_PropertiesUpdatedNoDomainEvent() + public async Task UpdatePartyDemographics_NewParty_PropertiesUpdatedDomainEvent() { var party = this.TestDb.HasAParty(party => { @@ -19,7 +19,7 @@ public async void UpdatePartyDemographics_NewParty_PropertiesUpdatedNoDomainEven var command = new Command { Id = party.Id, - Email = "pidp.test@goh.com", + Email = "pidp.test@email.com", Phone = "5555555555", PreferredFirstName = "PFirst", PreferredMiddleName = "PMid", @@ -36,11 +36,14 @@ public async void UpdatePartyDemographics_NewParty_PropertiesUpdatedNoDomainEven Assert.Equal(command.PreferredMiddleName, updatedParty.PreferredMiddleName); Assert.Equal(command.PreferredLastName, updatedParty.PreferredLastName); - Assert.Empty(this.PublishedEvents.OfType()); + Assert.Single(this.PublishedEvents.OfType()); + var emailEvent = this.PublishedEvents.OfType().Single(); + Assert.Equal(party.Id, emailEvent.PartyId); + Assert.Equal(command.Email, emailEvent.NewEmail); } [Fact] - public async void UpdatePartyDemographics_ExistingParty_PropertiesUpdatedDomainEvent() + public async Task UpdatePartyDemographics_ExistingParty_PropertiesUpdatedDomainEvent() { var party = this.TestDb.HasAParty(party => { @@ -79,7 +82,7 @@ public async void UpdatePartyDemographics_ExistingParty_PropertiesUpdatedDomainE } [Fact] - public async void UpdatePartyDemographics_ExistingParty_TrimPreferredNames() + public async Task UpdatePartyDemographics_ExistingParty_TrimPreferredNames() { var party = this.TestDb.HasAParty(party => { @@ -114,7 +117,7 @@ public async void UpdatePartyDemographics_ExistingParty_TrimPreferredNames() } [Fact] - public async void UpdatePartyDemographics_ExistingPartySameEmail_NoDomainEvent() + public async Task UpdatePartyDemographics_ExistingPartySameEmail_NoDomainEvent() { var party = this.TestDb.HasAParty(party => party.Email = "existing@email.com"); var command = new Command diff --git a/backend/webapi.tests/Features/ThirdPartyIntegrations/EndorsementData.cs b/backend/webapi.tests/Features/ThirdPartyIntegrations/EndorsementData.cs index b8b5858fe..b08ec8822 100644 --- a/backend/webapi.tests/Features/ThirdPartyIntegrations/EndorsementData.cs +++ b/backend/webapi.tests/Features/ThirdPartyIntegrations/EndorsementData.cs @@ -17,9 +17,9 @@ public class EndorsementDataTests : InMemoryDbTest && record.StatusReasonCode == result.StatusReasonCode; [Fact] - public async void GetEndorsementData_NoParty_404() + public async Task GetEndorsementData_NoParty_404() { - this.TestDb.Has(APartyWith(id: 1, hpdid: "hpdid")); + this.TestDb.Has(APartyWith(id: 1, hpdid: "hpdid@bcsc")); var query = new EndorsementData.Query { Hpdid = "NoMatch" }; var handler = this.MockDependenciesFor(); @@ -29,33 +29,24 @@ public async void GetEndorsementData_NoParty_404() } [Fact] - public async void GetEndorsementData_NoEndorsements_Empty() + public async Task GetEndorsementData_NoEndorsements_Empty() { - this.TestDb.Has(APartyWith(id: 1, hpdid: "hpdid")); + this.TestDb.Has(APartyWith(id: 1, hpdid: "hpdid@bcsc")); var query = new EndorsementData.Query { Hpdid = "hpdid" }; var handler = this.MockDependenciesFor(); var result = await handler.HandleAsync(query); Assert.True(result.IsSuccess); - Assert.Equal(new List(), result.Value); + Assert.Equal([], result.Value); } [Fact] - public async void GetEndorsementData_OneEndorsementNotActive_Empty() + public async Task GetEndorsementData_OneEndorsementNotActive_Empty() { - var expectedHpdid = "expected"; - this.TestDb.Has(APartyWith(id: 1, hpdid: "hpdid")); - this.TestDb.Has(APartyWith(id: 2, hpdid: expectedHpdid)); - this.TestDb.Has(new Endorsement - { - Active = false, - EndorsementRelationships = new[] - { - new EndorsementRelationship { PartyId = 1 }, - new EndorsementRelationship { PartyId = 2 } - } - }); + this.TestDb.Has(APartyWith(id: 1, hpdid: "hpdid@bcsc")); + this.TestDb.Has(APartyWith(id: 2, hpdid: "anotherHpdid@bcsc")); + this.TestDb.Has(AnEndorsementBetween(1, 2, isActive: false)); var query = new EndorsementData.Query { Hpdid = "hpdid" }; var handler = this.MockDependenciesFor(); @@ -68,21 +59,12 @@ public async void GetEndorsementData_OneEndorsementNotActive_Empty() [Theory] [InlineData("hpdid")] [InlineData("hpdid@bcsc")] - public async void GetEndorsementData_OneEndorsementNoCpn_MatchingHpdidEmptyLicences(string partyHpdid) + public async Task GetEndorsementData_OneEndorsementNoCpn_MatchingHpdidEmptyLicences(string hpdidQuery) { - var expectedHpdid = "expected"; - this.TestDb.Has(APartyWith(id: 1, hpdid: partyHpdid)); - this.TestDb.Has(APartyWith(id: 2, hpdid: expectedHpdid)); - this.TestDb.Has(new Endorsement - { - Active = true, - EndorsementRelationships = new[] - { - new EndorsementRelationship { PartyId = 1 }, - new EndorsementRelationship { PartyId = 2 } - } - }); - var query = new EndorsementData.Query { Hpdid = "hpdid" }; // Should match either "hpdid" or "hpdid@bcsc" (the actual form for HPDID we get from Keycloak) + this.TestDb.Has(APartyWith(id: 1, hpdid: "hpdid@bcsc")); + var otherParty = this.TestDb.Has(APartyWith(id: 2, hpdid: "anotherHpdid@bcsc")); + this.TestDb.Has(AnEndorsementBetween(1, 2)); + var query = new EndorsementData.Query { Hpdid = hpdidQuery }; // Should match either "hpdid" or "hpdid@bcsc" (the actual form for HPDID we get from Keycloak and save in our database) var handler = this.MockDependenciesFor(); var result = await handler.HandleAsync(query); @@ -91,15 +73,14 @@ public async void GetEndorsementData_OneEndorsementNoCpn_MatchingHpdidEmptyLicen Assert.Single(result.Value); var model = result.Value.Single(); - Assert.Equal(expectedHpdid, model.Hpdid); + AssertBasicInfoMatches(otherParty, model); Assert.NotNull(model.Licences); Assert.Empty(model.Licences); } [Fact] - public async void GetEndorsementData_OneEndorsementWithCpn_MatchingHpdidWithLicences() + public async Task GetEndorsementData_OneEndorsementWithCpn_MatchingHpdidWithLicences() { - var expectedHpdid = "expected"; var expectedCpn = "cpn"; var expectedPlrRecords = new[] { @@ -118,17 +99,9 @@ public async void GetEndorsementData_OneEndorsementWithCpn_MatchingHpdidWithLice StatusReasonCode = "StatusReasonCode2" } }; - this.TestDb.Has(APartyWith(id: 1, hpdid: "hpdid")); - this.TestDb.Has(APartyWith(id: 2, hpdid: expectedHpdid, cpn: expectedCpn)); - this.TestDb.Has(new Endorsement - { - Active = true, - EndorsementRelationships = new[] - { - new EndorsementRelationship { PartyId = 1 }, - new EndorsementRelationship { PartyId = 2 } - } - }); + this.TestDb.Has(APartyWith(id: 1, hpdid: "hpdid@bcsc")); + var otherParty = this.TestDb.Has(APartyWith(id: 2, hpdid: "otherHpdid@bcsc", cpn: expectedCpn)); + this.TestDb.Has(AnEndorsementBetween(1, 2)); var query = new EndorsementData.Query { Hpdid = "hpdid" }; var client = A.Fake(); A.CallTo(() => client.GetRecordsAsync(expectedCpn)) @@ -141,62 +114,42 @@ public async void GetEndorsementData_OneEndorsementWithCpn_MatchingHpdidWithLice Assert.Single(result.Value); var model = result.Value.Single(); - Assert.Equal(expectedHpdid, model.Hpdid); + AssertBasicInfoMatches(otherParty, model); Assert.NotNull(model.Licences); AssertThat.CollectionsAreEquivalent(expectedPlrRecords, model.Licences, RecordModelPredicate); } [Fact] - public async void GetEndorsementData_TwoEndorsementsWithCpn_MatchingHpdidsWithLicences() + public async Task GetEndorsementData_TwoEndorsementsWithCpn_MatchingHpdidsWithLicences() { - var expectedHpdid1 = "expected1"; - var expectedHpdid2 = "expected2"; - var expectedCpn1 = "cpn"; - var expectedPlrRecords1 = new[] + var expectedCpn = "cpn"; + var expectedPlrRecords = new[] { new PlrRecord { - Cpn = expectedCpn1, + Cpn = expectedCpn, IdentifierType = "IdentifierType1", StatusCode = "StatusCode1", StatusReasonCode = "StatusReasonCode1" }, new PlrRecord { - Cpn = expectedCpn1, + Cpn = expectedCpn, IdentifierType = "IdentifierType2", StatusCode = "StatusCode2", StatusReasonCode = "StatusReasonCode2" } }; - this.TestDb.Has(APartyWith(id: 1, hpdid: "hpdid")); - this.TestDb.Has(APartyWith(id: 2, hpdid: expectedHpdid1, cpn: expectedCpn1)); - this.TestDb.Has(APartyWith(id: 3, hpdid: expectedHpdid2)); - this.TestDb.Has(new Endorsement - { - Active = true, - EndorsementRelationships = new[] - { - new EndorsementRelationship { PartyId = 1 }, - new EndorsementRelationship { PartyId = 2 } - } - }); - this.TestDb.Has(new Endorsement - { - Active = true, - EndorsementRelationships = new[] - { - new EndorsementRelationship { PartyId = 1 }, - new EndorsementRelationship { PartyId = 3 } - } - }); + this.TestDb.Has(APartyWith(id: 1, hpdid: "hpdid@bcsc")); + var licencedOtherParty = this.TestDb.Has(APartyWith(id: 2, hpdid: "otherHpdid@bcsc", cpn: expectedCpn)); + var unlicencedOtherParty = this.TestDb.Has(APartyWith(id: 3, hpdid: "otherHpdid2@bcsc")); + this.TestDb.Has(AnEndorsementBetween(1, 2)); + this.TestDb.Has(AnEndorsementBetween(1, 3)); var query = new EndorsementData.Query { Hpdid = "hpdid" }; var client = A.Fake(); - A.CallTo(() => client.GetRecordsAsync(expectedCpn1, null)) - .Returns(expectedPlrRecords1); - A.CallTo(() => client.GetRecordsAsync(expectedCpn1)) - .Returns(expectedPlrRecords1); + A.CallTo(() => client.GetRecordsAsync(expectedCpn, null)) + .Returns(expectedPlrRecords); var handler = this.MockDependenciesFor(client); var result = await handler.HandleAsync(query); @@ -204,13 +157,16 @@ public async void GetEndorsementData_TwoEndorsementsWithCpn_MatchingHpdidsWithLi Assert.True(result.IsSuccess); Assert.Equal(2, result.Value.Count); - var found = result.Value.SingleOrDefault(res => res.Hpdid == expectedHpdid1); + var found = result.Value.SingleOrDefault(res => res.Hpdid == licencedOtherParty.Credentials.Single().Hpdid); Assert.NotNull(found); - AssertThat.CollectionsAreEquivalent(expectedPlrRecords1, found!.Licences, RecordModelPredicate); + AssertBasicInfoMatches(licencedOtherParty, found); + AssertThat.CollectionsAreEquivalent(expectedPlrRecords, found.Licences, RecordModelPredicate); - found = result.Value.SingleOrDefault(res => res.Hpdid == expectedHpdid2); + found = result.Value.SingleOrDefault(res => res.Hpdid == unlicencedOtherParty.Credentials.Single().Hpdid); Assert.NotNull(found); - AssertThat.CollectionsAreEquivalent(Array.Empty(), found!.Licences, RecordModelPredicate); + AssertBasicInfoMatches(unlicencedOtherParty, found); + Assert.NotNull(found.Licences); + Assert.Empty(found.Licences); } public static Party APartyWith(int id, string hpdid, string? cpn = null) @@ -219,14 +175,38 @@ public static Party APartyWith(int id, string hpdid, string? cpn = null) { Id = id, Cpn = cpn, - Credentials = new List - { + FirstName = $"First{id}", + LastName = $"Last{id}", + Email = $"email@{id}.com", + Credentials = + [ new Credential { IdentityProvider = IdentityProviders.BCServicesCard, IdpId = hpdid } - } + ] }; } + + public static Endorsement AnEndorsementBetween(int partyId1, int partyId2, bool isActive = true) + { + return new Endorsement + { + Active = isActive, + EndorsementRelationships = + [ + new EndorsementRelationship { PartyId = partyId1 }, + new EndorsementRelationship { PartyId = partyId2 } + ] + }; + } + + private static void AssertBasicInfoMatches(Party expected, EndorsementData.Model actual) + { + Assert.Equal(expected.Credentials.Single().Hpdid, actual.Hpdid); + Assert.Equal(expected.FirstName, actual.FirstName); + Assert.Equal(expected.LastName, actual.LastName); + Assert.Equal(expected.Email, actual.Email); + } } diff --git a/backend/webapi.tests/Testing Extensions/ContextExtensions.cs b/backend/webapi.tests/Testing Extensions/ContextExtensions.cs index 6905e10e9..b53240a25 100644 --- a/backend/webapi.tests/Testing Extensions/ContextExtensions.cs +++ b/backend/webapi.tests/Testing Extensions/ContextExtensions.cs @@ -23,7 +23,7 @@ public static Party HasAParty(this PidpDbContext context, Action? config { var party = new Party(); config?.Invoke(party); - if (!party.Credentials.Any()) + if (party.Credentials.Count == 0) { party.Credentials.Add(new Credential { UserId = Guid.NewGuid() }); } diff --git a/backend/webapi/Features/Credentials/BCProvider.Create.cs b/backend/webapi/Features/Credentials/BCProvider.Create.cs index 1c3f8e043..e1e03c201 100644 --- a/backend/webapi/Features/Credentials/BCProvider.Create.cs +++ b/backend/webapi/Features/Credentials/BCProvider.Create.cs @@ -2,7 +2,6 @@ namespace Pidp.Features.Credentials; using DomainResults.Common; using FluentValidation; -using Flurl; using HybridModelBinding; using Microsoft.EntityFrameworkCore; using System.Text.Json.Serialization; @@ -38,33 +37,20 @@ public CommandValidator() } } - public class CommandHandler : ICommandHandler> + public class CommandHandler( + IBCProviderClient client, + IEmailService emailService, + IKeycloakAdministrationClient keycloakClient, + ILogger logger, + IPlrClient plrClient, + PidpDbContext context) : ICommandHandler> { - private readonly IBCProviderClient client; - private readonly IEmailService emailService; - private readonly IKeycloakAdministrationClient keycloakClient; - private readonly ILogger logger; - private readonly IPlrClient plrClient; - private readonly PidpDbContext context; - private readonly Url keycloakAdministrationUrl; - - public CommandHandler( - IBCProviderClient client, - IEmailService emailService, - IKeycloakAdministrationClient keycloakClient, - ILogger logger, - IPlrClient plrClient, - PidpConfiguration config, - PidpDbContext context) - { - this.client = client; - this.emailService = emailService; - this.keycloakClient = keycloakClient; - this.logger = logger; - this.plrClient = plrClient; - this.context = context; - this.keycloakAdministrationUrl = Url.Parse(config.Keycloak.AdministrationUrl); - } + private readonly IBCProviderClient client = client; + private readonly IEmailService emailService = emailService; + private readonly IKeycloakAdministrationClient keycloakClient = keycloakClient; + private readonly ILogger logger = logger; + private readonly IPlrClient plrClient = plrClient; + private readonly PidpDbContext context = context; public async Task> HandleAsync(Command command) { @@ -136,6 +122,7 @@ public async Task> HandleAsync(Command command) var userId = await this.CreateKeycloakUser(party.FirstName, party.LastName, createdUser.UserPrincipalName); if (userId == null) { + this.logger.LogKeycloakUserCreationError(command.PartyId, createdUser.UserPrincipalName); return DomainResult.Failed(); } await this.keycloakClient.UpdateUser(userId.Value, user => user.SetOpId(party.OpId!)); @@ -146,7 +133,7 @@ public async Task> HandleAsync(Command command) PartyId = command.PartyId, IdpId = createdUser.UserPrincipalName, IdentityProvider = IdentityProviders.BCProvider, - DomainEvents = new List { new CollegeLicenceUpdated(command.PartyId) } + DomainEvents = [new CollegeLicenceUpdated(command.PartyId)] }); await this.context.SaveChangesAsync(); @@ -162,7 +149,7 @@ public async Task> HandleAsync(Command command) Enabled = true, FirstName = firstName, LastName = lastName, - Username = this.GenerateMohKeycloakUsername(userPrincipalName) + Username = GenerateMohKeycloakUsername(userPrincipalName) }; return await this.keycloakClient.CreateUser(newUser); } @@ -171,19 +158,9 @@ public async Task> HandleAsync(Command command) /// The expected Ministry of Health Keycloak username for this user. The schema is {IdentityProviderIdentifier}@{IdentityProvider}. /// Most of our Credentials come to us from Keycloak and so the username is saved as-is in the column IdpId. /// However, we create BC Provider Credentials directly; so the User Principal Name is saved to the database without the suffix. - /// There are also two inconsistencies with how the MOH Keycloak handles BCP usernames: - /// 1. The username suffix is @bcp rather than @bcprovider_aad. - /// 2. This suffix is only added in Test and Production; there is no suffix at all for BCP Users in the Dev Keycloak. + /// Note that the username suffix for BC Provider is actually @bcp rather than @bcprovider_aad. /// - private string GenerateMohKeycloakUsername(string userPrincipalName) - { - if (this.keycloakAdministrationUrl.Host == "user-management-dev.api.hlth.gov.bc.ca") - { - return userPrincipalName; - } - - return userPrincipalName + "@bcp"; - } + private static string GenerateMohKeycloakUsername(string userPrincipalName) => userPrincipalName + "@bcp"; private async Task SendBCProviderCreationEmail(string partyEmail, string userPrincipalName) { @@ -207,6 +184,6 @@ public static partial class BCProviderCreateLoggingExtensions [LoggerMessage(2, LogLevel.Error, "Failed to create BC Provider for Party {partyId}, one or more requirements were not met. Party state: {state}.")] public static partial void LogInvalidState(this ILogger logger, int partyId, object state); - [LoggerMessage(3, LogLevel.Error, "Error when attempting to create a Keycloak User for Party {partyId} with username {username}.")] - public static partial void LogKeycloakUserCreationError(this ILogger logger, int partyId, string username); + [LoggerMessage(3, LogLevel.Error, "Error when attempting to create a Keycloak User for Party {partyId} from User Principal Name {userPrincipalName}.")] + public static partial void LogKeycloakUserCreationError(this ILogger logger, int partyId, string userPrincipalName); } diff --git a/backend/webapi/Features/Parties/Demographics.cs b/backend/webapi/Features/Parties/Demographics.cs index 3f09a1280..076bfdfd3 100644 --- a/backend/webapi/Features/Parties/Demographics.cs +++ b/backend/webapi/Features/Parties/Demographics.cs @@ -63,16 +63,10 @@ public CommandValidator() } } - public class QueryHandler : IQueryHandler + public class QueryHandler(IMapper mapper, PidpDbContext context) : IQueryHandler { - private readonly IMapper mapper; - private readonly PidpDbContext context; - - public QueryHandler(IMapper mapper, PidpDbContext context) - { - this.mapper = mapper; - this.context = context; - } + private readonly IMapper mapper = mapper; + private readonly PidpDbContext context = context; public async Task HandleAsync(Query query) { @@ -83,11 +77,9 @@ public async Task HandleAsync(Query query) } } - public class CommandHandler : ICommandHandler + public class CommandHandler(PidpDbContext context) : ICommandHandler { - private readonly PidpDbContext context; - - public CommandHandler(PidpDbContext context) => this.context = context; + private readonly PidpDbContext context = context; public async Task HandleAsync(Command command) { @@ -95,8 +87,7 @@ public async Task HandleAsync(Command command) .Include(party => party.Credentials) .SingleAsync(party => party.Id == command.Id); - if (party.Email != null - && party.Email != command.Email) + if (party.Email != command.Email) { party.DomainEvents.Add(new PartyEmailUpdated(party.Id, party.PrimaryUserId, command.Email!)); } @@ -111,11 +102,9 @@ public async Task HandleAsync(Command command) } } - public class PartyEmailUpdatedHandler : INotificationHandler + public class PartyEmailUpdatedHandler(IBus bus) : INotificationHandler { - private readonly IBus bus; - - public PartyEmailUpdatedHandler(IBus bus) => this.bus = bus; + private readonly IBus bus = bus; public async Task Handle(PartyEmailUpdated notification, CancellationToken cancellationToken) { @@ -126,24 +115,16 @@ public async Task Handle(PartyEmailUpdated notification, CancellationToken cance } } - public class PartyEmailUpdatedBcProviderConsumer : IConsumer + public class PartyEmailUpdatedBcProviderConsumer( + IBCProviderClient client, + PidpConfiguration config, + PidpDbContext context, + ILogger logger) : IConsumer { - private readonly IBCProviderClient client; - private readonly PidpDbContext context; - private readonly string bcProviderClientId; - private readonly ILogger logger; - - public PartyEmailUpdatedBcProviderConsumer( - IBCProviderClient client, - PidpConfiguration config, - PidpDbContext context, - ILogger logger) - { - this.client = client; - this.context = context; - this.bcProviderClientId = config.BCProviderClient.ClientId; - this.logger = logger; - } + private readonly IBCProviderClient client = client; + private readonly PidpDbContext context = context; + private readonly string bcProviderClientId = config.BCProviderClient.ClientId; + private readonly ILogger logger = logger; public async Task Consume(ConsumeContext context) { diff --git a/backend/webapi/Features/ThirdPartyIntegrations/EndorsementData.cs b/backend/webapi/Features/ThirdPartyIntegrations/EndorsementData.cs index 49263ed61..8f5b3ce29 100644 --- a/backend/webapi/Features/ThirdPartyIntegrations/EndorsementData.cs +++ b/backend/webapi/Features/ThirdPartyIntegrations/EndorsementData.cs @@ -5,8 +5,8 @@ namespace Pidp.Features.ThirdPartyIntegrations; using Microsoft.EntityFrameworkCore; using Pidp.Data; +using Pidp.Extensions; using Pidp.Infrastructure.HttpClients.Plr; -using Pidp.Models; // Currently used by DMFT public class EndorsementData @@ -18,8 +18,11 @@ public class Query : IQuery>> public class Model { - public string? Hpdid { get; set; } = string.Empty; - public List Licences { get; set; } = new(); + public string? Hpdid { get; set; } + public string FirstName { get; set; } = string.Empty; + public string LastName { get; set; } = string.Empty; + public string Email { get; set; } = string.Empty; + public List Licences { get; set; } = []; public class LicenceInformation { @@ -34,21 +37,19 @@ public class QueryValidator : AbstractValidator public QueryValidator() => this.RuleFor(x => x.Hpdid).NotEmpty(); } - public class QueryHandler : IQueryHandler>> + public class QueryHandler(IPlrClient client, PidpDbContext context) : IQueryHandler>> { - private readonly IPlrClient client; - private readonly PidpDbContext context; - - public QueryHandler(IPlrClient client, PidpDbContext context) - { - this.client = client; - this.context = context; - } + private readonly IPlrClient client = client; + private readonly PidpDbContext context = context; public async Task>> HandleAsync(Query query) { + query.Hpdid = query.Hpdid.EndsWith("@bcsc", StringComparison.Ordinal) + ? query.Hpdid + : $"{query.Hpdid}@bcsc"; + var partyId = await this.context.Credentials - .Where(credential => credential.Hpdid!.Replace("@bcsc", "") == query.Hpdid) + .Where(credential => credential.Hpdid == query.Hpdid) .Select(credential => credential.PartyId) .SingleOrDefaultAsync(); @@ -57,16 +58,16 @@ public async Task>> HandleAsync(Query query) return DomainResult.NotFound>(); } - var dtos = await this.context.Endorsements - .Where(endorsement => endorsement.Active - && endorsement.EndorsementRelationships.Any(relationship => relationship.PartyId == partyId)) - .SelectMany(endorsement => endorsement.EndorsementRelationships) - .Where(relationship => relationship.PartyId != partyId) - .Select(relationship => new Dto + var dtos = await this.context.ActiveEndorsingParties(partyId) + .Select(party => new { - BcscCredential = relationship.Party!.Credentials - .SingleOrDefault(credential => credential.IsBcServicesCard), - Cpn = relationship.Party!.Cpn + Hpdid = party.Credentials + .SingleOrDefault(credential => credential.IsBcServicesCard)! + .IdpId, + party.Cpn, + party.FirstName, + party.LastName, + party.Email }) .ToListAsync(); @@ -74,7 +75,10 @@ public async Task>> HandleAsync(Query query) return DomainResult.Success(dtos.Select(dto => new Model { - Hpdid = dto.BcscCredential?.IdpId, + Hpdid = dto.Hpdid, + FirstName = dto.FirstName, + LastName = dto.LastName, + Email = dto.Email!, Licences = licences? .Where(licence => licence.Cpn == dto.Cpn) .Select(licence => new Model.LicenceInformation @@ -83,15 +87,9 @@ public async Task>> HandleAsync(Query query) StatusCode = licence.StatusCode, StatusReasonCode = licence.StatusReasonCode }) - .ToList() ?? new() + .ToList() ?? [] }) .ToList()); } } - - private class Dto - { - public Credential? BcscCredential { get; set; } - public string? Cpn { get; set; } - } } diff --git a/charts/webapi/values.yaml b/charts/webapi/values.yaml index 79f48a3fb..2e235d629 100644 --- a/charts/webapi/values.yaml +++ b/charts/webapi/values.yaml @@ -78,11 +78,11 @@ ingress: resources: limits: - cpu: 100m - memory: 128Mi + cpu: 50m + memory: 200Mi requests: cpu: 15m - memory: 50Mi + memory: 150Mi autoscaling: enabled: false @@ -110,7 +110,7 @@ fluentbit: runAsUser: 1001 resources: limits: - cpu: 100m + cpu: 50m memory: 64Mi requests: cpu: 10m diff --git a/workspace/apps/pidp/src/app/features/access/pages/access-requests-page/access-requests.page.scss b/workspace/apps/pidp/src/app/features/access/pages/access-requests-page/access-requests.page.scss index 38fc650a6..8a380c2e5 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/access-requests-page/access-requests.page.scss +++ b/workspace/apps/pidp/src/app/features/access/pages/access-requests-page/access-requests.page.scss @@ -161,6 +161,7 @@ .content-header h1 { font-size: 40px; + line-height: 1.1; } .breadcrumb { @@ -208,6 +209,7 @@ .content-header h1 { font-size: 40px; + line-height: 1.1; } .content-header { diff --git a/workspace/apps/pidp/src/app/features/access/pages/bc-provider-application/bc-provider-application.page.html b/workspace/apps/pidp/src/app/features/access/pages/bc-provider-application/bc-provider-application.page.html index 533b61e23..9353109bd 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/bc-provider-application/bc-provider-application.page.html +++ b/workspace/apps/pidp/src/app/features/access/pages/bc-provider-application/bc-provider-application.page.html @@ -1,7 +1,7 @@
-

BC Provider account information

+

BC Provider account information

@@ -185,7 +185,7 @@

You get more out of OneHealthID when you sign in with BC Provider.

-
+
Let's get started
@@ -229,6 +229,11 @@

You get more out of OneHealthID when you sign in with BC Provider.

+
+ +

Create an account

diff --git a/workspace/apps/pidp/src/app/features/access/pages/bc-provider-application/bc-provider-application.page.scss b/workspace/apps/pidp/src/app/features/access/pages/bc-provider-application/bc-provider-application.page.scss index e704472e9..41b315373 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/bc-provider-application/bc-provider-application.page.scss +++ b/workspace/apps/pidp/src/app/features/access/pages/bc-provider-application/bc-provider-application.page.scss @@ -68,9 +68,16 @@ ol { --header-margin: unset; --avatar-size: 4rem; --content-padding: var(--gap); - --password-splash-display: none; + --password-splash-display: unset; +} +.viewport-medium { + --header-margin: var(--gap) 0 0; + --content-padding: var(--gap) 0; + --password-splash-display: unset; + --password-splash: { + flex: 1 + } } -.viewport-medium, .viewport-large { --header-margin: var(--gap) 0 0; --content-padding: var(--gap) 0; @@ -80,10 +87,11 @@ ol { .viewport-all { & header { margin: var(--header-margin); - & h2 { - margin: 0; - padding: calc(var(--gap) / 2) calc(var(--gap) * 2); - background-color: pidp.$grey-10; + & h1 { + color: #036; + font-size: 3.125rem; + font-weight: 700; + margin-bottom: 0; } } & .content { @@ -365,6 +373,12 @@ ol { & .help-link { font-size: 0.75rem; } + & .mobile-image{ + & img { + display: none; + } + } + } .viewport-all.dialog-box { padding: 24px; @@ -426,4 +440,25 @@ ol { } } } + & .mobile-image{ + & img { + display: block; + max-width: 100%; + height: auto; + position: relative !important; + } + } + & .form-card { + display: block !important; + } + & .password-splash { + & .password-splash-content { + & .text-box { + display: none !important; + } + & .image { + display: none !important; + } + } + } } diff --git a/workspace/apps/pidp/src/app/features/access/pages/bc-provider-application/bc-provider-application.page.ts b/workspace/apps/pidp/src/app/features/access/pages/bc-provider-application/bc-provider-application.page.ts index 6cf278c37..6638a5ab8 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/bc-provider-application/bc-provider-application.page.ts +++ b/workspace/apps/pidp/src/app/features/access/pages/bc-provider-application/bc-provider-application.page.ts @@ -41,9 +41,7 @@ import { faUser, faXmark, } from '@fortawesome/free-solid-svg-icons'; -import { DashboardStateModel, PidpStateName } from '@pidp/data-model'; import { - AppStateService, LOADING_OVERLAY_DEFAULT_MESSAGE, LoadingOverlayService, NavigationService, @@ -70,6 +68,11 @@ import { AuthRoutes } from '@app/features/auth/auth.routes'; import { IdentityProvider } from '@app/features/auth/enums/identity-provider.enum'; import { AuthService } from '@app/features/auth/services/auth.service'; import { StatusCode } from '@app/features/portal/enums/status-code.enum'; +import { + DashboardStateModel, + PidpStateName, +} from '@app/features/portal/models/state.model'; +import { AppStateService } from '@app/features/shell/services/app-state.service'; import { NeedHelpComponent } from '@app/shared/components/need-help/need-help.component'; import { DialogBcproviderCreateComponent } from '@app/shared/components/success-dialog/components/dialog-bcprovider-create.component'; import { SuccessDialogComponent } from '@app/shared/components/success-dialog/success-dialog.component'; diff --git a/workspace/apps/pidp/src/app/features/access/pages/bc-provider-application/bc-provider-application.route.ts b/workspace/apps/pidp/src/app/features/access/pages/bc-provider-application/bc-provider-application.route.ts index 1f8384c6b..16a5e35df 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/bc-provider-application/bc-provider-application.route.ts +++ b/workspace/apps/pidp/src/app/features/access/pages/bc-provider-application/bc-provider-application.route.ts @@ -1,7 +1,5 @@ import { Routes } from '@angular/router'; -import { setDashboardTitleGuard } from '@pidp/presentation'; - import { highAssuranceCredentialGuard } from '@app/features/auth/guards/high-assurance-credential.guard'; import { bcProviderCompletedResolver } from '@app/features/auth/resolvers/bc-provider-completed.resolver'; @@ -15,13 +13,7 @@ export const routes: Routes = [ bcProviderApplicationStatusCode: bcProviderApplicationResolver, hasCompletedBCProvider: bcProviderCompletedResolver, }, - canActivate: [setDashboardTitleGuard, highAssuranceCredentialGuard], + canActivate: [highAssuranceCredentialGuard], component: BcProviderApplicationPage, - data: { - setDashboardTitleGuard: { - titleText: 'BC Provider and OneHealthID', - titleDescriptionText: '', - }, - }, }, ]; diff --git a/workspace/apps/pidp/src/app/features/access/pages/bc-provider-edit/bc-provider-edit.page.html b/workspace/apps/pidp/src/app/features/access/pages/bc-provider-edit/bc-provider-edit.page.html index 556c7691e..734e7e9f7 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/bc-provider-edit/bc-provider-edit.page.html +++ b/workspace/apps/pidp/src/app/features/access/pages/bc-provider-edit/bc-provider-edit.page.html @@ -1,7 +1,7 @@
-

BC Provider Account Information

+

BC Provider Account Information

@@ -58,6 +58,11 @@

BC Provider Account Information

+
+ +

Password reset

Provided username

diff --git a/workspace/apps/pidp/src/app/features/access/pages/bc-provider-edit/bc-provider-edit.page.scss b/workspace/apps/pidp/src/app/features/access/pages/bc-provider-edit/bc-provider-edit.page.scss index ddc77c79d..7f18acfff 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/bc-provider-edit/bc-provider-edit.page.scss +++ b/workspace/apps/pidp/src/app/features/access/pages/bc-provider-edit/bc-provider-edit.page.scss @@ -19,13 +19,43 @@ margin-top: 20px; } } + & .mobile-image{ + & img { + display: block !important; + max-width: 100%; + height: auto; + position: relative !important; + } + } + & .form-card { + display: block !important; + } + & .password-splash { + & .password-splash-content { + & .text-box { + display: none !important; + } + & .image { + display: none !important; + } + } + } } .viewport-all { --header-margin: unset; --avatar-size: 4rem; --content-padding: var(--gap); - --password-splash-display: none; + --password-splash-display: unset; +} + +.viewport-medium { + --header-margin: var(--gap) 0 0; + --content-padding: var(--gap) 0; + --password-splash-display: unset; + --password-splash: { + flex: 1 + } } .viewport-medium, @@ -38,10 +68,11 @@ .viewport-all { & header { margin: var(--header-margin); - & h2 { - margin: 0; - padding: calc(var(--gap) / 2) calc(var(--gap) * 2); - background-color: pidp.$grey-10; + & h1 { + color: #036; + font-size: 3.125rem; + font-weight: 700; + margin-bottom: 0; } } & .content { @@ -198,6 +229,11 @@ margin-top: var(--gap); } } + & .mobile-image{ + & img { + display: none; + } + } } .viewport-all.dialog-box { padding: 24px; @@ -240,3 +276,13 @@ } } } + +.viewport-small, +.viewport-xsmall { + & header { + & h1 { + font-size: 40px; + line-height: 1.1; + } + } +} diff --git a/workspace/apps/pidp/src/app/features/access/pages/bc-provider-edit/bc-provider-edit.routes.ts b/workspace/apps/pidp/src/app/features/access/pages/bc-provider-edit/bc-provider-edit.routes.ts index 09d00f9e7..1bd5556c3 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/bc-provider-edit/bc-provider-edit.routes.ts +++ b/workspace/apps/pidp/src/app/features/access/pages/bc-provider-edit/bc-provider-edit.routes.ts @@ -1,7 +1,5 @@ import { Routes } from '@angular/router'; -import { setDashboardTitleGuard } from '@pidp/presentation'; - import { highAssuranceCredentialGuard } from '@app/features/auth/guards/high-assurance-credential.guard'; import { bcProviderEditResolver } from '@app/features/auth/resolvers/bc-provider-edit.resolver'; @@ -13,13 +11,7 @@ export const routes: Routes = [ resolve: { hasCompletedBCProvider: bcProviderEditResolver, }, - canActivate: [setDashboardTitleGuard, highAssuranceCredentialGuard], + canActivate: [highAssuranceCredentialGuard], component: BcProviderEditPage, - data: { - setDashboardTitleGuard: { - titleText: 'BC Provider and OneHealthID', - titleDescriptionText: '', - }, - }, }, ]; diff --git a/workspace/apps/pidp/src/app/features/access/pages/driver-fitness/driver-fitness-routing.routes.ts b/workspace/apps/pidp/src/app/features/access/pages/driver-fitness/driver-fitness-routing.routes.ts index 4c8007954..4e1a4309d 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/driver-fitness/driver-fitness-routing.routes.ts +++ b/workspace/apps/pidp/src/app/features/access/pages/driver-fitness/driver-fitness-routing.routes.ts @@ -1,7 +1,5 @@ import { Routes } from '@angular/router'; -import { setDashboardTitleGuard } from '@pidp/presentation'; - import { DriverFitnessPage } from './driver-fitness.page'; import { driverFitnessResolver } from './driver-fitness.resolver'; @@ -9,15 +7,8 @@ export const routes: Routes = [ { path: '', component: DriverFitnessPage, - canActivate: [setDashboardTitleGuard], resolve: { driverFitnessStatusCode: driverFitnessResolver, }, - data: { - setDashboardTitleGuard: { - titleText: 'Driver Fitness Practitioner Portal Application', - titleDescriptionText: '', - }, - }, }, ]; diff --git a/workspace/apps/pidp/src/app/features/access/pages/driver-fitness/driver-fitness.page.html b/workspace/apps/pidp/src/app/features/access/pages/driver-fitness/driver-fitness.page.html index 33892f90e..703318070 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/driver-fitness/driver-fitness.page.html +++ b/workspace/apps/pidp/src/app/features/access/pages/driver-fitness/driver-fitness.page.html @@ -1,6 +1,6 @@
-

Enrolment

+

Enrolment

diff --git a/workspace/apps/pidp/src/app/features/access/pages/driver-fitness/driver-fitness.page.scss b/workspace/apps/pidp/src/app/features/access/pages/driver-fitness/driver-fitness.page.scss index cabba6280..c38286793 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/driver-fitness/driver-fitness.page.scss +++ b/workspace/apps/pidp/src/app/features/access/pages/driver-fitness/driver-fitness.page.scss @@ -33,9 +33,14 @@ span { .viewport-all { &.box { padding: var(--header-padding) 0 var(--header-padding) var(--header-padding); + h1 { + color: #036; + font-size: 3.125rem; + font-weight: 700; + margin-bottom: 0; + } & .title { - background-color: pidp.$bcgov-color-background-grey; - padding: 9px 24px; + padding: 1rem 0; } } & .content { @@ -109,3 +114,13 @@ span { padding-left: 0; } } + +.viewport-small, +.viewport-xsmall { + & header { + & h1 { + font-size: 40px; + line-height: 1.1; + } + } +} diff --git a/workspace/apps/pidp/src/app/features/access/pages/driver-fitness/driver-fitness.page.ts b/workspace/apps/pidp/src/app/features/access/pages/driver-fitness/driver-fitness.page.ts index 2dd394938..0cadbee23 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/driver-fitness/driver-fitness.page.ts +++ b/workspace/apps/pidp/src/app/features/access/pages/driver-fitness/driver-fitness.page.ts @@ -7,7 +7,6 @@ import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { catchError, noop, of, tap } from 'rxjs'; import { - ApplicationService, LOADING_OVERLAY_DEFAULT_MESSAGE, LoadingOverlayService, } from '@pidp/presentation'; @@ -21,6 +20,7 @@ import { import { PartyService } from '@app/core/party/party.service'; import { LoggerService } from '@app/core/services/logger.service'; import { StatusCode } from '@app/features/portal/enums/status-code.enum'; +import { ApplicationService } from '@app/features/shell/services/application.service'; import { EnrolmentErrorComponent } from '../../components/enrolment-error/enrolment-error.component'; import { DriverFitnessResource } from './driver-fitness-resource.service'; diff --git a/workspace/apps/pidp/src/app/features/access/pages/hcim-account-transfer/hcim-account-transfer-routing.routes.ts b/workspace/apps/pidp/src/app/features/access/pages/hcim-account-transfer/hcim-account-transfer-routing.routes.ts index 655888777..1826366d9 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/hcim-account-transfer/hcim-account-transfer-routing.routes.ts +++ b/workspace/apps/pidp/src/app/features/access/pages/hcim-account-transfer/hcim-account-transfer-routing.routes.ts @@ -1,7 +1,5 @@ import { Routes } from '@angular/router'; -import { setDashboardTitleGuard } from '@pidp/presentation'; - import { HcimAccountTransferPage } from './hcim-account-transfer.page'; import { hcimAccountTransferResolver } from './hcim-account-transfer.resolver'; @@ -9,7 +7,6 @@ export const routes: Routes = [ { path: '', component: HcimAccountTransferPage, - canActivate: [setDashboardTitleGuard], resolve: { hcimAccountTransferStatusCode: hcimAccountTransferResolver, }, @@ -18,11 +15,6 @@ export const routes: Routes = [ routes: { root: '../../', }, - setDashboardTitleGuard: { - titleText: 'Welcome to OneHealthID Service', - titleDescriptionText: - 'Complete your profile to gain access to the systems you are eligible for', - }, }, }, ]; diff --git a/workspace/apps/pidp/src/app/features/access/pages/hcim-account-transfer/hcim-account-transfer.page.html b/workspace/apps/pidp/src/app/features/access/pages/hcim-account-transfer/hcim-account-transfer.page.html index f69f7d750..599aab8f1 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/hcim-account-transfer/hcim-account-transfer.page.html +++ b/workspace/apps/pidp/src/app/features/access/pages/hcim-account-transfer/hcim-account-transfer.page.html @@ -1,6 +1,6 @@ -
+
- {{ title }} +

{{ title }}

diff --git a/workspace/apps/pidp/src/app/features/access/pages/hcim-account-transfer/hcim-account-transfer.page.scss b/workspace/apps/pidp/src/app/features/access/pages/hcim-account-transfer/hcim-account-transfer.page.scss index 881c85e8c..98d25c46f 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/hcim-account-transfer/hcim-account-transfer.page.scss +++ b/workspace/apps/pidp/src/app/features/access/pages/hcim-account-transfer/hcim-account-transfer.page.scss @@ -1,3 +1,19 @@ .viewport-all { padding: 1.25rem 0.75rem; + + h1 { + color: #036; + font-size: 3.125rem; + font-weight: 700; + margin-bottom: 0; + padding: 2rem 0; + } +} + +.viewport-small, +.viewport-xsmall { + h1 { + font-size: 40px; + line-height: 1.1; + } } diff --git a/workspace/apps/pidp/src/app/features/access/pages/hcim-account-transfer/hcim-account-transfer.page.ts b/workspace/apps/pidp/src/app/features/access/pages/hcim-account-transfer/hcim-account-transfer.page.ts index 207d4b609..4504e7a37 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/hcim-account-transfer/hcim-account-transfer.page.ts +++ b/workspace/apps/pidp/src/app/features/access/pages/hcim-account-transfer/hcim-account-transfer.page.ts @@ -13,6 +13,7 @@ import { AlertComponent, AlertContentDirective, AnchorDirective, + InjectViewportCssClassDirective, PageComponent, PageFooterActionDirective, PageFooterComponent, @@ -58,6 +59,7 @@ import { AlertComponent, AlertContentDirective, AnchorDirective, + InjectViewportCssClassDirective, MatButtonModule, MatFormFieldModule, MatInputModule, diff --git a/workspace/apps/pidp/src/app/features/access/pages/immsbc-eforms/immsbc-eforms-routing.routes.ts b/workspace/apps/pidp/src/app/features/access/pages/immsbc-eforms/immsbc-eforms-routing.routes.ts index bd8b80d5e..043ac53e0 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/immsbc-eforms/immsbc-eforms-routing.routes.ts +++ b/workspace/apps/pidp/src/app/features/access/pages/immsbc-eforms/immsbc-eforms-routing.routes.ts @@ -1,7 +1,5 @@ import { Routes } from '@angular/router'; -import { setDashboardTitleGuard } from '@pidp/presentation'; - import { ImmsBCEformsPage } from './immsbc-eforms.page'; import { immsBCEformsResolver } from './immsbc-eforms.resolver'; @@ -9,7 +7,6 @@ export const routes: Routes = [ { path: '', component: ImmsBCEformsPage, - canActivate: [setDashboardTitleGuard], resolve: { immsBCEformsStatusCode: immsBCEformsResolver, }, @@ -18,11 +15,6 @@ export const routes: Routes = [ routes: { root: '../../', }, - setDashboardTitleGuard: { - titleText: 'Welcome to OneHealthID Service', - titleDescriptionText: - 'Complete your profile to gain access to the systems you are eligible for', - }, }, }, ]; diff --git a/workspace/apps/pidp/src/app/features/access/pages/immsbc-eforms/immsbc-eforms.page.html b/workspace/apps/pidp/src/app/features/access/pages/immsbc-eforms/immsbc-eforms.page.html index 7cc4f5d38..6697ead91 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/immsbc-eforms/immsbc-eforms.page.html +++ b/workspace/apps/pidp/src/app/features/access/pages/immsbc-eforms/immsbc-eforms.page.html @@ -1,6 +1,6 @@ -
+
- {{ title }} +

{{ title }}

-

Thank you for enrolling for MS Teams access.

+

Thank you for enrolling for MS Teams access.

diff --git a/workspace/apps/pidp/src/app/features/access/pages/ms-teams-clinic-member/ms-teams-clinic-member.page.scss b/workspace/apps/pidp/src/app/features/access/pages/ms-teams-clinic-member/ms-teams-clinic-member.page.scss index af78ec419..7d5d223b9 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/ms-teams-clinic-member/ms-teams-clinic-member.page.scss +++ b/workspace/apps/pidp/src/app/features/access/pages/ms-teams-clinic-member/ms-teams-clinic-member.page.scss @@ -28,10 +28,12 @@ .viewport-all { & header { - & h2 { - margin: 0; - padding: calc(var(--gap) / 2) calc(var(--gap)); - background-color: pidp.$grey-10; + & h1 { + color: #036; + font-size: 3.125rem; + font-weight: 700; + margin-bottom: 0; + padding: 2rem 0; } } & .content { @@ -106,3 +108,13 @@ } } } + +.viewport-small, +.viewport-xsmall { + & header { + & h1 { + font-size: 40px; + line-height: 1.1; + } + } +} diff --git a/workspace/apps/pidp/src/app/features/access/pages/ms-teams-privacy-officer/ms-teams-privacy-officer-routing.routes.ts b/workspace/apps/pidp/src/app/features/access/pages/ms-teams-privacy-officer/ms-teams-privacy-officer-routing.routes.ts index 505acdef5..bbf856d77 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/ms-teams-privacy-officer/ms-teams-privacy-officer-routing.routes.ts +++ b/workspace/apps/pidp/src/app/features/access/pages/ms-teams-privacy-officer/ms-teams-privacy-officer-routing.routes.ts @@ -1,7 +1,5 @@ import { Routes } from '@angular/router'; -import { setDashboardTitleGuard } from '@pidp/presentation'; - import { MsTeamsPrivacyOfficerPage } from './ms-teams-privacy-officer.page'; import { msTeamsPrivacyOfficerResolver } from './ms-teams-privacy-officer.resolver'; @@ -12,13 +10,7 @@ export const routes: Routes = [ resolve: { msTeamsPrivacyOfficerStatusCode: msTeamsPrivacyOfficerResolver, }, - canActivate: [setDashboardTitleGuard], data: { - setDashboardTitleGuard: { - titleText: 'MS Teams Privacy Officer', - titleDescriptionText: - 'Here you can add your clinic information and access MS Teams', - }, title: 'OneHealthID Service', routes: { root: '../../', diff --git a/workspace/apps/pidp/src/app/features/access/pages/ms-teams-privacy-officer/ms-teams-privacy-officer.page.html b/workspace/apps/pidp/src/app/features/access/pages/ms-teams-privacy-officer/ms-teams-privacy-officer.page.html index 4137a51c7..7002527bb 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/ms-teams-privacy-officer/ms-teams-privacy-officer.page.html +++ b/workspace/apps/pidp/src/app/features/access/pages/ms-teams-privacy-officer/ms-teams-privacy-officer.page.html @@ -52,7 +52,7 @@

Endorsement

-

Welcome to your MS Teams enrolment application.

+

Welcome to your MS Teams enrolment application.

diff --git a/workspace/apps/pidp/src/app/features/access/pages/ms-teams-privacy-officer/ms-teams-privacy-officer.page.scss b/workspace/apps/pidp/src/app/features/access/pages/ms-teams-privacy-officer/ms-teams-privacy-officer.page.scss index 24f6de328..3d2d9463b 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/ms-teams-privacy-officer/ms-teams-privacy-officer.page.scss +++ b/workspace/apps/pidp/src/app/features/access/pages/ms-teams-privacy-officer/ms-teams-privacy-officer.page.scss @@ -47,9 +47,11 @@ .viewport-all { &.box { padding: var(--header-padding) 0 var(--header-padding) var(--header-padding); - & .title { - background-color: pidp.$bcgov-color-background-grey; - padding: 9px 24px; + h1 { + color: #036; + font-size: 3.125rem; + font-weight: 700; + margin-bottom: 0; } } & header { @@ -146,3 +148,23 @@ } } } + +.viewport-large, +.viewport-medium, +.viewport-small, +.viewport-xsmall { + & header { + & h1 { + line-height: 1.1; + } + } +} + +.viewport-small, +.viewport-xsmall { + & header { + & h1 { + font-size: 40px; + } + } +} diff --git a/workspace/apps/pidp/src/app/features/access/pages/prescription-refill-eforms/prescription-refill-eforms-routing.routes.ts b/workspace/apps/pidp/src/app/features/access/pages/prescription-refill-eforms/prescription-refill-eforms-routing.routes.ts index 7c97fa28d..840eeca22 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/prescription-refill-eforms/prescription-refill-eforms-routing.routes.ts +++ b/workspace/apps/pidp/src/app/features/access/pages/prescription-refill-eforms/prescription-refill-eforms-routing.routes.ts @@ -15,11 +15,6 @@ export const routes: Routes = [ routes: { root: '../../', }, - setDashboardTitleGuard: { - titleText: 'Welcome to OneHealthID Service', - titleDescriptionText: - 'Complete your profile to gain access to the systems you are eligible for', - }, }, }, ]; diff --git a/workspace/apps/pidp/src/app/features/access/pages/provider-reporting-portal/provider-reporting-portal-routing.routes.ts b/workspace/apps/pidp/src/app/features/access/pages/provider-reporting-portal/provider-reporting-portal-routing.routes.ts index 5e6a808fc..8360dd7f3 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/provider-reporting-portal/provider-reporting-portal-routing.routes.ts +++ b/workspace/apps/pidp/src/app/features/access/pages/provider-reporting-portal/provider-reporting-portal-routing.routes.ts @@ -15,11 +15,6 @@ export const routes: Routes = [ routes: { root: '../../', }, - setDashboardTitleGuard: { - titleText: 'Welcome to OneHealthID Service', - titleDescriptionText: - 'Complete your profile to gain access to the systems you are eligible for', - }, }, }, ]; diff --git a/workspace/apps/pidp/src/app/features/access/pages/provider-reporting-portal/provider-reporting-portal.page.html b/workspace/apps/pidp/src/app/features/access/pages/provider-reporting-portal/provider-reporting-portal.page.html index ec77d3045..d84ea4e77 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/provider-reporting-portal/provider-reporting-portal.page.html +++ b/workspace/apps/pidp/src/app/features/access/pages/provider-reporting-portal/provider-reporting-portal.page.html @@ -1,5 +1,6 @@ +
- {{ title }} +

{{ title }}

+
diff --git a/workspace/apps/pidp/src/app/features/access/pages/provider-reporting-portal/provider-reporting-portal.page.scss b/workspace/apps/pidp/src/app/features/access/pages/provider-reporting-portal/provider-reporting-portal.page.scss index e69de29bb..36b1c5699 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/provider-reporting-portal/provider-reporting-portal.page.scss +++ b/workspace/apps/pidp/src/app/features/access/pages/provider-reporting-portal/provider-reporting-portal.page.scss @@ -0,0 +1,18 @@ +.viewport-all { + padding: 1.25rem 0.75rem; + h1 { + color: #036; + font-size: 3.125rem; + font-weight: 700; + margin-bottom: 0; + padding: 2rem 0; + } +} + +.viewport-small, +.viewport-xsmall { + h1 { + font-size: 40px; + line-height: 1.1; + } +} diff --git a/workspace/apps/pidp/src/app/features/access/pages/provider-reporting-portal/provider-reporting-portal.page.ts b/workspace/apps/pidp/src/app/features/access/pages/provider-reporting-portal/provider-reporting-portal.page.ts index 528e04081..ce0d021c3 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/provider-reporting-portal/provider-reporting-portal.page.ts +++ b/workspace/apps/pidp/src/app/features/access/pages/provider-reporting-portal/provider-reporting-portal.page.ts @@ -10,6 +10,7 @@ import { AlertComponent, AlertContentDirective, AnchorDirective, + InjectViewportCssClassDirective, PageComponent, PageFooterActionDirective, PageFooterComponent, @@ -38,6 +39,7 @@ import { ProviderReportingPortalResource } from './provider-reporting-portal-res AlertContentDirective, AnchorDirective, EnrolmentErrorComponent, + InjectViewportCssClassDirective, MatButtonModule, NgIf, PageComponent, diff --git a/workspace/apps/pidp/src/app/features/access/pages/provincial-attachment-system/provincial-attachment-system-routing.routes.ts b/workspace/apps/pidp/src/app/features/access/pages/provincial-attachment-system/provincial-attachment-system-routing.routes.ts index 0f67aa057..2d8cca063 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/provincial-attachment-system/provincial-attachment-system-routing.routes.ts +++ b/workspace/apps/pidp/src/app/features/access/pages/provincial-attachment-system/provincial-attachment-system-routing.routes.ts @@ -1,7 +1,5 @@ import { Routes } from '@angular/router'; -import { setDashboardTitleGuard } from '@pidp/presentation'; - import { ProvincialAttachmentSystemPage } from './provincial-attachment-system.page'; import { provincialAttachmentSystemResolver } from './provincial-attachment-system.resolver'; @@ -9,15 +7,8 @@ export const routes: Routes = [ { path: '', component: ProvincialAttachmentSystemPage, - canActivate: [setDashboardTitleGuard], resolve: { provincialAttachmentSystemStatusCode: provincialAttachmentSystemResolver, }, - data: { - setDashboardTitleGuard: { - titleText: 'Provincial Attachment System', - titleDescriptionText: '', - }, - }, }, ]; diff --git a/workspace/apps/pidp/src/app/features/access/pages/provincial-attachment-system/provincial-attachment-system.page.html b/workspace/apps/pidp/src/app/features/access/pages/provincial-attachment-system/provincial-attachment-system.page.html index 14c1ebc17..0897e9695 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/provincial-attachment-system/provincial-attachment-system.page.html +++ b/workspace/apps/pidp/src/app/features/access/pages/provincial-attachment-system/provincial-attachment-system.page.html @@ -171,38 +171,53 @@

Enrol for Access

-
- doctor -
-
-

Provincial Attachment System

+
+
+ doctor +
+
+

Provincial Attachment System

+
+
+ +
+
-
- +
+ +
+ You will need BCProvider credential before logging in.
- +
diff --git a/workspace/apps/pidp/src/app/features/access/pages/provincial-attachment-system/provincial-attachment-system.page.scss b/workspace/apps/pidp/src/app/features/access/pages/provincial-attachment-system/provincial-attachment-system.page.scss index 549439cb0..51d76478d 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/provincial-attachment-system/provincial-attachment-system.page.scss +++ b/workspace/apps/pidp/src/app/features/access/pages/provincial-attachment-system/provincial-attachment-system.page.scss @@ -81,6 +81,11 @@ } .pas-button { height: 15rem; + background: linear-gradient( + 270deg, + rgba(0, 0, 0, 0) 0%, + rgba(158, 204, 211, 1) 100% + ); img { object-fit: cover; z-index: -2; @@ -91,7 +96,7 @@ } div.auth-card { - padding: 20px 0px 55px 50px; + padding: 23px 0px 7px 34px; } .card-container { @@ -116,7 +121,7 @@ .card-body { img.logo { - z-index: -1; + z-index: 0; -webkit-transform: none; transform: none; position: relative !important; @@ -128,11 +133,15 @@ .card-footer { button { + z-index: 1; padding: 10px 25px; } } } } + .pas-button-text { + font-size: smaller; + } } } } @@ -144,6 +153,7 @@ .content-header h1 { font-size: 40px; + line-height: 1.1; } .breadcrumb { @@ -153,6 +163,10 @@ display: flex !important; flex-direction: column !important; + .pas-step-label { + line-height: 1.1; + } + .pas-button { img.img-doctor { height: 15rem !important; @@ -204,6 +218,11 @@ .stepper-buttons { margin-top: 10px; + & button { + border: pidp.$bcgov-color-primary solid 2px; + color: pidp.$bcgov-color-primary; + font-weight: bold; + } & button:last-child { margin-left: 10px; diff --git a/workspace/apps/pidp/src/app/features/access/pages/provincial-attachment-system/provincial-attachment-system.page.ts b/workspace/apps/pidp/src/app/features/access/pages/provincial-attachment-system/provincial-attachment-system.page.ts index c8e6e1e35..df9d02d2f 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/provincial-attachment-system/provincial-attachment-system.page.ts +++ b/workspace/apps/pidp/src/app/features/access/pages/provincial-attachment-system/provincial-attachment-system.page.ts @@ -30,7 +30,6 @@ import { AuthService } from '@app/features/auth/services/auth.service'; import { StatusCode } from '@app/features/portal/enums/status-code.enum'; import { ProfileStatus } from '@app/features/portal/models/profile-status.model'; import { PortalResource } from '@app/features/portal/portal-resource.service'; -import { PortalService } from '@app/features/portal/portal.service'; import { BcProviderEditResource } from '../bc-provider-edit/bc-provider-edit-resource.service'; import { BcProviderEditInitialStateModel } from '../bc-provider-edit/bc-provider-edit.page'; @@ -92,7 +91,6 @@ export class ProvincialAttachmentSystemPage implements OnInit { private discoveryResource: DiscoveryResource, private navigationService: NavigationService, private portalResource: PortalResource, - private portalService: PortalService, private partyService: PartyService, private router: Router, private toastService: ToastService, @@ -127,74 +125,50 @@ export class ProvincialAttachmentSystemPage implements OnInit { this.partyService.partyId, ); - this.updateState(profileStatus$); - this.handlePasBannerStatus(profileStatus$); - this.handlePasStatus(profileStatus$); + this.handleStepperState(profileStatus$); } - private updateState(profileStatus$: Observable): void { - profileStatus$ - .pipe( - tap((profileStatus: ProfileStatus | null) => { - this.portalService.updateState(profileStatus); - }), - ) - .subscribe(); - } - - private handlePasBannerStatus( - profileStatus$: Observable, - ): void { - profileStatus$ - .pipe( - switchMap( - ( - profileStatus, - ): Observable => { - let selectedIndex = this.lastSelectedIndex; - this.hasCpn = profileStatus?.status.collegeCertification.hasCpn; - - this.bcProviderStatusCode = - profileStatus?.status.bcProvider.statusCode; - if (this.bcProviderStatusCode === StatusCode.COMPLETED) { - this.bcProvider$.next(true); - return this.bcProviderResource.get(this.partyService.partyId); - } else { - if (selectedIndex === this.lastSelectedIndex) { - // BCProvider step - selectedIndex = 0; - } - this.selectedIndex = selectedIndex; - return of(null); - } - }, - ), - tap((bcProviderObject: BcProviderEditInitialStateModel | null) => { - if (bcProviderObject) { - this.bcProviderUsername = bcProviderObject.bcProviderId; - } - }), - ) - .subscribe(); - } - - private handlePasStatus( + private handleStepperState( profileStatus$: Observable, ): void { + let selectedIndex = this.lastSelectedIndex; profileStatus$ .pipe( tap((profileStatus: ProfileStatus | null) => { - let selectedIndex = this.lastSelectedIndex; + this.hasCpn = profileStatus?.status.collegeCertification.hasCpn; this.pasStatusCode = profileStatus?.status.provincialAttachmentSystem.statusCode; + this.bcProviderStatusCode = + profileStatus?.status.bcProvider.statusCode; if (this.pasStatusCode === StatusCode.COMPLETED) { this.pas$.next(false); - } else if (selectedIndex === this.lastSelectedIndex) { + } else if ( + selectedIndex === this.lastSelectedIndex && + this.bcProviderStatusCode === StatusCode.COMPLETED + ) { // PAS step selectedIndex = 1; } this.selectedIndex = selectedIndex; }), + switchMap((): Observable => { + if (this.bcProviderStatusCode === StatusCode.COMPLETED) { + this.bcProvider$.next(true); + return this.bcProviderResource.get(this.partyService.partyId); + } else { + if (selectedIndex === this.lastSelectedIndex) { + // BCProvider step + selectedIndex = 0; + } + this.selectedIndex = selectedIndex; + return of(null); + } + }), + tap((bcProviderObject: BcProviderEditInitialStateModel | null) => { + if (bcProviderObject) { + this.bcProviderUsername = bcProviderObject.bcProviderId; + } + }), ) .subscribe(); } diff --git a/workspace/apps/pidp/src/app/features/access/pages/sa-eforms/sa-eforms-routing.routes.ts b/workspace/apps/pidp/src/app/features/access/pages/sa-eforms/sa-eforms-routing.routes.ts index 00932d94f..60bdc9a87 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/sa-eforms/sa-eforms-routing.routes.ts +++ b/workspace/apps/pidp/src/app/features/access/pages/sa-eforms/sa-eforms-routing.routes.ts @@ -1,7 +1,5 @@ import { Routes } from '@angular/router'; -import { setDashboardTitleGuard } from '@pidp/presentation'; - import { SaEformsPage } from './sa-eforms.page'; import { saEformsResolver } from './sa-eforms.resolver'; @@ -9,7 +7,6 @@ export const routes: Routes = [ { path: '', component: SaEformsPage, - canActivate: [setDashboardTitleGuard], resolve: { saEformsStatusCode: saEformsResolver, }, @@ -18,11 +15,6 @@ export const routes: Routes = [ routes: { root: '../../', }, - setDashboardTitleGuard: { - titleText: 'Welcome to OneHealthID Service', - titleDescriptionText: - 'Complete your profile to gain access to the systems you are eligible for', - }, }, }, ]; diff --git a/workspace/apps/pidp/src/app/features/access/pages/sa-eforms/sa-eforms.page.html b/workspace/apps/pidp/src/app/features/access/pages/sa-eforms/sa-eforms.page.html index 392c4a090..4c35b3027 100644 --- a/workspace/apps/pidp/src/app/features/access/pages/sa-eforms/sa-eforms.page.html +++ b/workspace/apps/pidp/src/app/features/access/pages/sa-eforms/sa-eforms.page.html @@ -1,6 +1,6 @@ -
+
- {{ title }} +

{{ title }}

Frequently asked questions

@@ -31,6 +32,7 @@

Frequently asked questions

@@ -53,6 +55,7 @@

Frequently asked questions

@@ -80,6 +83,7 @@

Frequently asked questions

@@ -95,7 +99,7 @@

Frequently asked questions

number of provincial health applications (backed by BC Services Card) and is aligned to policy.
The BCProvider credential is created during the enrolment process
- https://healthprovideridentityportal.gov.bc.ca/auth/login

@@ -103,6 +107,7 @@

Frequently asked questions

@@ -141,11 +146,15 @@

Frequently asked questions

For more information on the BC Services Card and Provider Location Registry, please refer to:
BCSC. https://www2.gov.bc.ca/gov/content/governments/government-id/bc-services-card
PLR. https://www2.gov.bc.ca/gov/content/health/practitioner-professional-resources/system-access/provider-location-registry-plr @@ -154,6 +163,7 @@

Frequently asked questions

@@ -179,13 +189,15 @@

Frequently asked questions

  • Microsoft. https://www.microsoft.com/en-ca/security/mobile-authenticator-app
  • OneHealthID Service. Enrolment process tool FAQ at
    - https://healthprovideridentityportal.gov.bc.ca/auth/login
  • @@ -194,6 +206,7 @@

    Frequently asked questions

    @@ -205,12 +218,13 @@

    Frequently asked questions

    View instructions to setup Multi-factor authentication - here. + here.

    @@ -261,9 +275,7 @@

    Frequently asked questions

    Still have questions?

    - +

    Additional support:

    Still have questions?

    - -
    Back to top
    +
    Back to top
    diff --git a/workspace/apps/pidp/src/app/features/faq/pages/help/help.page.scss b/workspace/apps/pidp/src/app/features/faq/pages/help/help.page.scss index 612b05632..d826b68e4 100644 --- a/workspace/apps/pidp/src/app/features/faq/pages/help/help.page.scss +++ b/workspace/apps/pidp/src/app/features/faq/pages/help/help.page.scss @@ -36,43 +36,25 @@ font-weight: 700; } + .mfa-link { + cursor: pointer; + } + .faq-item { - border-bottom: 1px solid #CCC; + border-bottom: 1px solid #ccc; margin-bottom: 10px; a { color: #0d6efd; text-decoration: underline; } - - ::ng-deep .mat-expansion-panel { - box-shadow: none; - - .mat-expansion-panel-header { - padding: 0; - line-height: 1.5; - } - - .mat-expansion-indicator, - .mat-expansion-indicator::after { - border-width: 0 3px 3px 0 !important; - - &::after { - color: #CCCCCC; - } - } - - .mat-expansion-panel-body { - padding: 0; - line-height: 1.5; - } - - } } .footer-cards { display: grid; - grid-template-columns: calc(49% - 15px) calc(17% - 15px) calc(17% - 15px) calc(17% - 15px); + grid-template-columns: calc(49% - 15px) calc(17% - 15px) calc(17% - 15px) calc( + 17% - 15px + ); gap: 20px; margin-top: 2rem; @@ -95,9 +77,8 @@ flex-direction: column; align-items: flex-start; gap: 5px; - border: 1px solid #CCC; - background: #F2F2F2; - + border: 1px solid #ccc; + background: #f2f2f2; h2 { color: #036; @@ -140,15 +121,15 @@ display: flex; flex-direction: column; width: 100%; - justify-content: start; + justify-content: flex-start; align-items: center; text-align: center; height: 11rem; padding: 2rem 1rem; border-radius: 4px; transition: background-color 0.3s ease; - border: 1px solid #CCC; - background: #FFF; + border: 1px solid #ccc; + background: #fff; box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25); color: var(--BC-gov-blue, #036); font-size: 0.8rem; @@ -174,25 +155,24 @@ } .back-to-top { - background-color: #38598A; - color: #FFFFFF; - width: 40PX; - height: 40PX; + background-color: #38598a; + color: #ffffff; + width: 40px; + height: 40px; border-radius: 50%; text-align: center; cursor: pointer; } .back-to-top-text { - color: #38598A; + color: #38598a; font-size: 13px; - word-wrap: break-word + word-wrap: break-word; } .back-to-top:hover { background-color: #003366; } - } .viewport-medium { @@ -212,35 +192,6 @@ .faq-item { margin-bottom: 20px; - - ::ng-deep .mat-expansion-panel { - - .mat-expansion-panel-header { - font-size: 0.75rem; - height: auto; - } - - .mat-expansion-panel-header-title { - margin-right: 2px; - } - - .mat-expansion-indicator, - .mat-expansion-indicator::after { - border-width: 0 2px 2px 0 !important; - padding: 3px !important; - margin-bottom: 5px; - - } - - .mat-expansion-panel-body { - - p:first-of-type { - padding-top: 5px; - } - - font-size: 0.75rem; - } - } } .footer-cards { @@ -257,9 +208,8 @@ flex-direction: column; align-items: flex-start; gap: 5px; - border: 1px solid #CCC; - background: #F2F2F2; - + border: 1px solid #ccc; + background: #f2f2f2; h2 { font-size: 30px; @@ -296,8 +246,8 @@ } .back-to-top { - width: 30PX; - height: 30PX; + width: 30px; + height: 30px; } .back-to-top-text { @@ -309,12 +259,10 @@ } } - - .viewport-small { .back-to-top { - width: 30PX; - height: 30PX; + width: 30px; + height: 30px; } .back-to-top-text { diff --git a/workspace/apps/pidp/src/app/features/faq/pages/help/help.page.ts b/workspace/apps/pidp/src/app/features/faq/pages/help/help.page.ts index dc02ed3b5..554829126 100644 --- a/workspace/apps/pidp/src/app/features/faq/pages/help/help.page.ts +++ b/workspace/apps/pidp/src/app/features/faq/pages/help/help.page.ts @@ -1,9 +1,13 @@ +import { NgIf } from '@angular/common'; import { Component, HostListener, Inject, OnInit, signal } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; +import { MatExpansionModule } from '@angular/material/expansion'; import { ActivatedRoute, Router } from '@angular/router'; -import {MatExpansionModule} from '@angular/material/expansion'; -import { InjectViewportCssClassDirective } from '@bcgov/shared/ui'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { faAngleRight, faArrowUp } from '@fortawesome/free-solid-svg-icons'; + +import { InjectViewportCssClassDirective } from '@bcgov/shared/ui'; import { AnchorDirective, PageComponent, @@ -16,11 +20,9 @@ import { import { APP_CONFIG, AppConfig } from '@app/app.config'; import { UtilsService } from '@app/core/services/utils.service'; -import { faAngleRight, faArrowUp } from '@fortawesome/free-solid-svg-icons'; -import { FaIconComponent } from '@fortawesome/angular-fontawesome'; -import { FaqRoutes } from '../../faq.routes'; import { Constants } from '@app/shared/constants'; -import { NgIf } from '@angular/common'; + +import { FaqRoutes } from '../../faq.routes'; @Component({ selector: 'app-help', @@ -48,6 +50,7 @@ export class HelpPage implements OnInit { public showBackToTopButton: boolean = false; public faArrowUp = faArrowUp; public faAngleRight = faAngleRight; + public applicationUrl: string; public constructor( @Inject(APP_CONFIG) private config: AppConfig, @@ -56,17 +59,22 @@ export class HelpPage implements OnInit { private utilsService: UtilsService, ) { this.providerIdentitySupport = this.config.emails.providerIdentitySupport; + this.applicationUrl = this.config.applicationUrl; } @HostListener('window:scroll', []) public onWindowScroll(): void { - const scrollPosition = window.scrollY || document.documentElement.scrollTop || document.body.scrollTop || 0; - this.showBackToTopButton = scrollPosition > Constants.scrollThreshold; - } + const scrollPosition = + window.scrollY || + document.documentElement.scrollTop || + document.body.scrollTop || + 0; + this.showBackToTopButton = scrollPosition > Constants.scrollThreshold; + } - public scrollToTop(): void { - window.scrollTo({ top: 0, behavior: 'smooth' }); -} + public scrollToTop(): void { + window.scrollTo({ top: 0, behavior: 'smooth' }); + } public onBack(): void { this.navigateToRoot(); diff --git a/workspace/apps/pidp/src/app/features/faq/pages/mfa-setup/mfa-setup-routing.routes.ts b/workspace/apps/pidp/src/app/features/faq/pages/mfa-setup/mfa-setup-routing.routes.ts index f8f4218e1..403275ce8 100644 --- a/workspace/apps/pidp/src/app/features/faq/pages/mfa-setup/mfa-setup-routing.routes.ts +++ b/workspace/apps/pidp/src/app/features/faq/pages/mfa-setup/mfa-setup-routing.routes.ts @@ -1,24 +1,16 @@ import { Routes } from '@angular/router'; -import { setDashboardTitleGuard } from '@pidp/presentation'; - import { MfaSetupPage } from './mfa-setup.page'; export const routes: Routes = [ { path: '', component: MfaSetupPage, - canActivate: [setDashboardTitleGuard], data: { title: 'OneHealthID Service', routes: { root: '../../', }, - setDashboardTitleGuard: { - titleText: 'Welcome to OneHealthID Service', - titleDescriptionText: - 'Complete your profile to gain access to the systems you are eligible for', - }, }, }, ]; diff --git a/workspace/apps/pidp/src/app/features/history/pages/signed-or-accepted-documents/signed-or-accepted-documents-routing.routes.ts b/workspace/apps/pidp/src/app/features/history/pages/signed-or-accepted-documents/signed-or-accepted-documents-routing.routes.ts index 4a2623f0e..a7bfc953f 100644 --- a/workspace/apps/pidp/src/app/features/history/pages/signed-or-accepted-documents/signed-or-accepted-documents-routing.routes.ts +++ b/workspace/apps/pidp/src/app/features/history/pages/signed-or-accepted-documents/signed-or-accepted-documents-routing.routes.ts @@ -1,24 +1,16 @@ import { Routes } from '@angular/router'; -import { setDashboardTitleGuard } from '@pidp/presentation'; - import { SignedOrAcceptedDocumentsPage } from './signed-or-accepted-documents.page'; export const routes: Routes = [ { path: '', component: SignedOrAcceptedDocumentsPage, - canActivate: [setDashboardTitleGuard], data: { title: 'OneHealthID Service', routes: { root: '../../', }, - setDashboardTitleGuard: { - titleText: 'Welcome to OneHealthID Service', - titleDescriptionText: - 'Complete your profile to gain access to the systems you are eligible for', - }, }, }, ]; diff --git a/workspace/apps/pidp/src/app/features/history/pages/transactions/transactions-routing.routes.ts b/workspace/apps/pidp/src/app/features/history/pages/transactions/transactions-routing.routes.ts index 513a94841..668189979 100644 --- a/workspace/apps/pidp/src/app/features/history/pages/transactions/transactions-routing.routes.ts +++ b/workspace/apps/pidp/src/app/features/history/pages/transactions/transactions-routing.routes.ts @@ -1,24 +1,16 @@ import { Routes } from '@angular/router'; -import { setDashboardTitleGuard } from '@pidp/presentation'; - import { TransactionsPage } from './transactions.page'; export const routes: Routes = [ { path: '', component: TransactionsPage, - canActivate: [setDashboardTitleGuard], data: { title: 'OneHealthID Service', routes: { root: '../../', }, - setDashboardTitleGuard: { - titleText: 'Welcome to OneHealthID Service', - titleDescriptionText: - 'Complete your profile to gain access to the systems you are eligible for', - }, }, }, ]; diff --git a/workspace/apps/pidp/src/app/features/history/pages/view-document/view-document-routing.routes.ts b/workspace/apps/pidp/src/app/features/history/pages/view-document/view-document-routing.routes.ts index 3745c5dd8..0bc4b37e1 100644 --- a/workspace/apps/pidp/src/app/features/history/pages/view-document/view-document-routing.routes.ts +++ b/workspace/apps/pidp/src/app/features/history/pages/view-document/view-document-routing.routes.ts @@ -1,21 +1,13 @@ import { Routes } from '@angular/router'; -import { setDashboardTitleGuard } from '@pidp/presentation'; - import { ViewDocumentPage } from './view-document.page'; export const routes: Routes = [ { path: '', component: ViewDocumentPage, - canActivate: [setDashboardTitleGuard], data: { title: 'OneHealthID Service', - setDashboardTitleGuard: { - titleText: 'Welcome to OneHealthID Service', - titleDescriptionText: - 'Complete your profile to gain access to the systems you are eligible for', - }, }, }, ]; diff --git a/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/components/endorsement-card/endorsement-card.component.html b/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/components/endorsement-card/endorsement-card.component.html index cc26f0437..f4b341fdd 100644 --- a/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/components/endorsement-card/endorsement-card.component.html +++ b/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/components/endorsement-card/endorsement-card.component.html @@ -1,47 +1,25 @@
    - account_circle + Account Icon
    -

    {{ nameText }}

    +
    +
    - {{ collegeText }} +

    + {{ collegeText }} +

    -
    - {{ noticeText }} -
    -
    - {{ createdOnText }} -
    -
    -
    - - {{ createdOnText }} - - {{ noticeText }} - +

    + Status: {{ noticeText }} +

    +

    + Label: {{ createdOnText }} +

    diff --git a/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/components/endorsement-card/endorsement-card.component.scss b/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/components/endorsement-card/endorsement-card.component.scss index c9e8e9241..d15a6881c 100644 --- a/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/components/endorsement-card/endorsement-card.component.scss +++ b/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/components/endorsement-card/endorsement-card.component.scss @@ -29,24 +29,36 @@ p { justify-content: space-between; border: solid 1px pidp.$grey-30; border-radius: 4px; + max-width: 23.3125rem; + padding: 1.25rem; + height: 100%; + & .content { margin-bottom: var(--gap); & .icon-box { padding: 0 var(--gap); - & mat-icon { - font-size: var(--icon-font-size); - height: var(--icon-font-size); - width: var(--icon-font-size); - } + border: 2px solid #fcba19; + border-radius: 50%; + width: 3.75rem; + height: 3.75rem; + margin-right: 1rem; } & h3 { margin: var(--gap) var(--gap) var(--gap) 0; - font-size: 1.25rem; + color: #036; + font-size: 1.125rem; + font-weight: 700; // Ensure long email addresses will wrap instead of making the card wider. word-break: break-all; } + } + & .second-row { + margin-bottom: 1.75rem; & .school-box { - padding-right: var(--gap); + color: #313132; + font-size: 1rem; + font-weight: 400; + line-height: 1.2rem; } & .extra-box-large { & .notice-box { @@ -88,23 +100,27 @@ p { } } & .actions { - padding: 0 var(--gap) var(--gap); display: flex; justify-content: space-between; - & button.cancel { - border-color: pidp.$bcgov-color-primary; - } + & button.cancel, & button.approve { - color: #fff; - border-color: pidp.$green; - background-color: pidp.$green; + color: #036; + gap: var(--gap); + border-radius: 0.25rem; + border: 2px solid #036; + background: #fff; + max-width: 8.25rem; + font-size: 1rem; + font-weight: 700; + letter-spacing: 0.0625rem; } } } // mobile layout .viewport-xsmall { + max-width: 25.3125rem; & .content { display: grid; grid-template-columns: auto 1fr; diff --git a/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/endorsements-routing.routes.ts b/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/endorsements-routing.routes.ts index da4ed1a54..e6a9ec748 100644 --- a/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/endorsements-routing.routes.ts +++ b/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/endorsements-routing.routes.ts @@ -1,7 +1,5 @@ import { Routes } from '@angular/router'; -import { setDashboardTitleGuard } from '@pidp/presentation'; - import { highAssuranceCredentialGuard } from '@app/features/auth/guards/high-assurance-credential.guard'; import { EndorsementsPage } from './endorsements.page'; @@ -10,12 +8,6 @@ export const routes: Routes = [ { path: '', component: EndorsementsPage, - canActivate: [setDashboardTitleGuard, highAssuranceCredentialGuard], - data: { - setDashboardTitleGuard: { - titleText: 'Welcome to your endorsements', - titleDescriptionText: '', - }, - }, + canActivate: [highAssuranceCredentialGuard], }, ]; diff --git a/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/endorsements.page.html b/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/endorsements.page.html index 484000130..75ee5b31f 100644 --- a/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/endorsements.page.html +++ b/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/endorsements.page.html @@ -1,9 +1,17 @@ -
    +
    +
    -

    Team Members

    +

    TEAM MEMBERS

    +

    Endorsements

    @@ -21,7 +29,7 @@

    Team Members

    access. In the future, licensed health care providers will be able to pick which systems to endorse (if any).

    -

    To send a OneHealthID access invitation:

    +

    To send a OneHealthID access invitation:

    1. Send your colleague a OneHealthID access invitation by email below @@ -31,7 +39,7 @@

      Team Members

      vouched for by you, allowing them to register for OneHealthID
    -

    To endorse a OneHealthID access invitation:

    +

    To endorse a OneHealthID access invitation:

    1. You may also see an Incoming Request to vouch for a colleague who @@ -146,7 +154,8 @@

      Team Members

    -

    Endorsement Request

    +

    PROCEDURE

    +

    Endorsement Request

    Enter the email of the person that you have a working relationship @@ -159,10 +168,8 @@

    Endorsement Request

    restart the process.

    - + Email + Required diff --git a/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/endorsements.page.scss b/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/endorsements.page.scss index c1af1cc09..21e2312d0 100644 --- a/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/endorsements.page.scss +++ b/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/endorsements.page.scss @@ -1,9 +1,6 @@ @use 'pidp-variables' as pidp; @import 'bootstrap/bootstrap-imports'; -* { - box-sizing: border-box; -} h2, label, p { @@ -11,13 +8,11 @@ p { } // Set gap depending on viewport. -.viewport-xsmall { - --gap: 1rem; -} +.viewport-xsmall, .viewport-large, .viewport-medium, .viewport-small { - --gap: 1.25rem; + --gap: 1rem; } // Use gap to set css. @@ -25,47 +20,52 @@ p { --box-padding: 0; --content-padding: 0 0 var(--gap); --care-team-text-padding: var(--gap) var(--gap) 0; - --tab-content-flex-direction: column; + --tab-content-flex-direction: row; --endorsement-request-item-padding: 0 var(--gap); - --endorsement-form-field-width: 100%; + --endorsement-form-field-width: 38.375rem; padding: 1.25rem 0.75rem; -} -.viewport-large { - --box-padding: calc(2 * var(--gap)) 0; - --content-padding: 0; - --care-team-text-padding: var(--gap) 0; - --tab-content-flex-direction: unset; - --endorsement-request-item-padding: unset; - --endorsement-form-field-width: 30rem; -} -.viewport-medium { - --box-padding: var(--gap) 0; - --content-padding: 0; - --care-team-text-padding: var(--gap) 0; - --tab-content-flex-direction: unset; - --endorsement-request-item-padding: unset; - --endorsement-form-field-width: 30rem; -} -.viewport-small { - --box-padding: 0 0 var(--gap); - --content-padding: 0 var(--gap); - --care-team-text-padding: var(--gap) 0; - --tab-content-flex-direction: unset; - --endorsement-request-item-padding: unset; - --endorsement-form-field-width: 30rem; -} -.viewport-all { - padding: var(--box-padding); + + .breadcrumb ul { + list-style: none; + top: 0; + right: 0; + padding: 0px; + } + + .breadcrumb fa-icon { + height: 12px; + padding-left: 5px; + padding-right: 5px; + } + + .breadcrumb ul li { + display: inline; + } + + .breadcrumb a, + .text-button { + text-decoration: none; + color: #1a5a96; + font-size: 12px; + font-weight: 400; + line-height: 27px; + word-wrap: break-word; + } + & .content { padding: var(--content-padding); & header { - display: flex; - align-items: center; - flex-wrap: nowrap; - padding: calc(var(--gap) / 2) var(--gap); - background-color: pidp.$page-header-background-color; - & h2 { - margin: 0; + & h3 { + color: #4493b5; + font-size: 1.5rem; + font-weight: 400; + margin-bottom: 0.5rem; + } + & h1 { + color: #036; + font-size: 3.125rem; + font-weight: 700; + margin-bottom: 0; } & mat-icon { margin-left: calc(var(--gap) / 2); @@ -73,10 +73,11 @@ p { } & .care-team { & .care-team-text { - padding: var(--care-team-text-padding); - & .large { - font-size: 1.25rem; - } + padding: var(--care-team-text-padding) 0; + color: #313132; + font-size: 1rem; + font-weight: 400; + line-height: 1.6875rem; } & .care-team-tabs { min-height: 10rem; @@ -85,6 +86,8 @@ p { display: flex; align-items: center; opacity: 1; + color: #000; + font-size: 1.125rem; & .badge { margin-left: 0.5rem; font-size: 0.5rem; @@ -100,41 +103,128 @@ p { } & .tab-content { padding: var(--gap); - display: flex; - flex-wrap: wrap; gap: var(--gap); - flex-direction: var(--tab-content-flex-direction); - - & .endorsement-card { - flex-basis: calc((100% - (var(--gap))) / 2); - - @include media-breakpoint-up(lg) { - flex-basis: calc((100% - (var(--gap))) / 3); - } - - display: flex; - } + display: grid; + grid-template-columns: calc(50% - 15px) calc(50% - 15px); } } & .endorsement-request { & header { margin: calc(2 * var(--gap)) 0 var(--gap); } - & p, - & h3 { - padding: var(--endorsement-request-item-padding); - } & mat-form-field { - padding: var(--endorsement-request-item-padding); - width: var(--endorsement-form-field-width); + max-width: var(--endorsement-form-field-width); + width: 100%; } } & .actions { - display: flex; - padding: var(--endorsement-request-item-padding); + margin-top: 2rem; + button { + border-radius: 0.25rem; + border: 2px solid #036; + font-size: 1rem; + font-weight: 700; + letter-spacing: 0.0625rem; + } & button:not(:first-of-type) { margin-left: var(--gap); } } } } +.viewport-large { + --tab-content-flex-direction: row; + & .content { + & .care-team { + & .tab-content { + grid-template-columns: calc(33% - 15px) calc(33% - 15px) calc( + 33% - 15px + ); + } + } + } +} + +.viewport-medium { + --tab-content-flex-direction: row; + & .content { + & .care-team { + & .tab-content { + grid-template-columns: calc(33% - 15px) calc(33% - 15px) calc( + 33% - 15px + ); + } + } + } +} +.viewport-small { + --gap: 1rem; + --font-size: 0.75rem; + --card-header-font-size: unset; + --card-header-line-height: unset; + --tab-content-flex-direction: column; + & .content { + & .care-team { + & .tab-label-box { + font-size: 1rem; + } + & .tab-content { + grid-template-columns: calc(50% - 15px) calc(50% - 15px); + } + } + } +} +.viewport-xsmall { + --gap: 1rem; + --font-size: 1rem; + --card-header-font-size: calc(2 * var(--font-size)); + --card-header-line-height: calc(var(--card-header-font-size) + 0.5rem); + --margin-bottom-style: 1.5rem; + padding: 1.25rem 0; + + .breadcrumb { + padding: 0 0.75rem; + } + + & .content { + padding: var(--content-padding); + & header { + padding: 0 0.75rem; + & h3 { + color: #4493b5; + font-size: 1.2rem; + font-weight: 400; + margin-bottom: 0.5rem; + } + & h1 { + color: #036; + font-size: 2rem; + font-weight: 700; + margin-bottom: 0; + } + } + & .care-team { + & .care-team-text { + padding: 0 0.75rem; + } + & .tab-content { + grid-template-columns: 100%; + } + } + + & .endorsement-request { + & header { + padding: 0 0.75rem; + } + p { + padding: 0 0.75rem; + } + & mat-form-field { + padding: 0 0.75rem; + } + } + & .actions { + padding: 0 0.75rem; + } + } +} diff --git a/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/endorsements.page.ts b/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/endorsements.page.ts index 9a1436420..1eefe9b3b 100644 --- a/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/endorsements.page.ts +++ b/workspace/apps/pidp/src/app/features/organization-info/pages/endorsements/endorsements.page.ts @@ -19,6 +19,7 @@ import { catchError, exhaustMap, map, + noop, of, switchMap, tap, @@ -26,6 +27,7 @@ import { import { FaIconComponent } from '@fortawesome/angular-fontawesome'; import { + faAngleRight, faArrowDown, faArrowUp, faUser, @@ -105,6 +107,7 @@ export class EndorsementsPage public faUserGroup = faUserGroup; public faArrowUp = faArrowUp; public faArrowDown = faArrowDown; + public faAngleRight = faAngleRight; public formState: EndorsementsFormState; public completed: boolean | null; @@ -140,6 +143,24 @@ export class EndorsementsPage public showTextLabels = false; public showIconLabels = true; + public popupData: DialogOptions = { + title: 'Endorsement requests', + bottomBorder: false, + titlePosition: 'center', + bodyTextPosition: 'center', + component: HtmlComponent, + data: { + content: + 'You are about to cancel this endorsement, would you like to proceed', + }, + imageSrc: '/assets/images/online-marketing-hIgeoQjS_iE-unsplash.jpg', + imageType: 'banner', + width: '31rem', + height: '24rem', + actionText: 'Continue', + actionTypePosition: 'center', + class: 'dialog-container', + }; public get recipientEmail(): FormControl { return this.formState.form.get('recipientEmail') as FormControl; @@ -161,38 +182,72 @@ export class EndorsementsPage public onApprove(requestId: number): void { this.loadingOverlayService.open(LOADING_OVERLAY_DEFAULT_MESSAGE); - this.resource - .approveEndorsementRequest(this.partyService.partyId, requestId) + const data: DialogOptions = this.popupData; + + data.data = { + content: + 'You are about to approve this endorsement, would you like to proceed', + }; + + this.dialog + .open(ConfirmDialogComponent, { data }) + .afterClosed() .pipe( - switchMap( - () => - (this.actionableEndorsementRequests$ = - this.getActionableEndorsementRequests(this.partyService.partyId)), - ), + exhaustMap((result) => { + this.loadingOverlayService.close(); + return result + ? this.resource + .approveEndorsementRequest(this.partyService.partyId, requestId) + .pipe( + switchMap( + () => + (this.actionableEndorsementRequests$ = + this.getActionableEndorsementRequests( + this.partyService.partyId, + )), + ), + ) + : EMPTY; + }), ) .subscribe(); } public onCancel(requestId: number): void { - this.resource - .declineEndorsementRequest(this.partyService.partyId, requestId) + const data: DialogOptions = this.popupData; + data.data = { + content: + 'You are about to cancel this endorsement, would you like to proceed', + }; + this.dialog + .open(ConfirmDialogComponent, { data }) + .afterClosed() .pipe( - switchMap( - () => - (this.actionableEndorsementRequests$ = - this.getActionableEndorsementRequests(this.partyService.partyId)), - ), + exhaustMap((result) => { + this.loadingOverlayService.close(); + return result + ? this.resource + .declineEndorsementRequest(this.partyService.partyId, requestId) + .pipe( + switchMap( + () => + (this.actionableEndorsementRequests$ = + this.getActionableEndorsementRequests( + this.partyService.partyId, + )), + ), + ) + : EMPTY; + }), ) .subscribe(); } public onCancelEndorsement(endorsementId: number): void { - const data: DialogOptions = { - title: 'Cancel Endorsement', - component: HtmlComponent, - data: { - content: 'Are you sure you want to cancel this Endorsement?', - }, + const data: DialogOptions = this.popupData; + data.data = { + content: + 'You are about to cancel this endorsement, would you like to proceed', }; this.dialog .open(ConfirmDialogComponent, { data }) @@ -262,9 +317,49 @@ export class EndorsementsPage protected performSubmission(): NoContent { const partyId = this.partyService.partyId; + const data: DialogOptions = { + title: 'Endorsement requests', + bottomBorder: false, + titlePosition: 'center', + bodyTextPosition: 'center', + component: HtmlComponent, + data: { + content: + "You are about to request an endorsement to

    " + + this.formState.json?.recipientEmail + + '

    would you like to proceed?', + }, + imageSrc: '/assets/images/online-marketing-hIgeoQjS_iE-unsplash.jpg', + imageType: 'banner', + width: '31rem', + height: '26rem', + actionText: 'Continue', + actionTypePosition: 'center', + class: 'dialog-container', + }; return partyId && this.formState.json - ? this.resource.createEndorsementRequest(partyId, this.formState.json) + ? this.dialog + .open(ConfirmDialogComponent, { data }) + .afterClosed() + .pipe( + exhaustMap((result) => { + this.loadingOverlayService.close(); + return result && partyId && this.formState.json + ? this.resource.createEndorsementRequest( + partyId, + this.formState.json, + ) + : EMPTY; + }), + catchError((error: HttpErrorResponse) => { + this.loadingOverlayService.close(); + if (error.status === HttpStatusCode.BadRequest) { + return of(noop()); + } + return of(noop()); + }), + ) : EMPTY; } diff --git a/workspace/libs/pidp/data-model/src/lib/models/state.model.ts b/workspace/apps/pidp/src/app/features/portal/models/state.model.ts similarity index 88% rename from workspace/libs/pidp/data-model/src/lib/models/state.model.ts rename to workspace/apps/pidp/src/app/features/portal/models/state.model.ts index 038cab86e..dbb8fd9ce 100644 --- a/workspace/libs/pidp/data-model/src/lib/models/state.model.ts +++ b/workspace/apps/pidp/src/app/features/portal/models/state.model.ts @@ -1,3 +1,5 @@ +import { AlertCode } from '../enums/alert-code.enum'; + export const PidpStateName = { dashboard: 'dashboard', }; @@ -10,6 +12,7 @@ export interface DashboardStateModel extends NamedState { userProfileFullNameText: string; userProfileCollegeNameText: string; collegeRoute: string; + alerts: AlertCode[]; } export const defaultDashboardState: DashboardStateModel = { stateName: PidpStateName.dashboard, @@ -18,6 +21,7 @@ export const defaultDashboardState: DashboardStateModel = { userProfileFullNameText: '', userProfileCollegeNameText: '', collegeRoute: '', + alerts: [], }; export interface ApplicationStateModel { all: NamedState[]; diff --git a/workspace/apps/pidp/src/app/features/portal/portal-routing.routes.ts b/workspace/apps/pidp/src/app/features/portal/portal-routing.routes.ts index 45bd88b12..3836cb5ee 100644 --- a/workspace/apps/pidp/src/app/features/portal/portal-routing.routes.ts +++ b/workspace/apps/pidp/src/app/features/portal/portal-routing.routes.ts @@ -1,21 +1,13 @@ import { Routes } from '@angular/router'; -import { setDashboardTitleGuard } from '@pidp/presentation'; - import { PortalPage } from './portal.page'; export const routes: Routes = [ { path: '', component: PortalPage, - canActivate: [setDashboardTitleGuard], data: { title: 'OneHealthID Service', - setDashboardTitleGuard: { - titleText: 'Welcome to OneHealthID Service', - titleDescriptionText: - 'Complete your profile to gain access to the systems you are eligible for', - }, }, }, ]; diff --git a/workspace/apps/pidp/src/app/features/portal/portal.page.html b/workspace/apps/pidp/src/app/features/portal/portal.page.html index f928bc668..f963c7319 100644 --- a/workspace/apps/pidp/src/app/features/portal/portal.page.html +++ b/workspace/apps/pidp/src/app/features/portal/portal.page.html @@ -16,7 +16,8 @@
    Welcome to the OneHealthID Service

    Linking Accounts

    Link different credentials together in OneHealthID

    - + READ MORE
    @@ -30,7 +31,8 @@
    Welcome to the OneHealthID Service

    Acquire Access

    Acquire healthcare system access for myself

    - + READ MORE
    @@ -44,9 +46,21 @@
    Welcome to the OneHealthID Service

    Grant Access

    Grant healthcare system access for others

    - - READ MORE - +
    diff --git a/workspace/apps/pidp/src/app/features/portal/portal.page.scss b/workspace/apps/pidp/src/app/features/portal/portal.page.scss index 256016350..8ee6101d9 100644 --- a/workspace/apps/pidp/src/app/features/portal/portal.page.scss +++ b/workspace/apps/pidp/src/app/features/portal/portal.page.scss @@ -143,6 +143,19 @@ padding-right: 3px; } +div.card-footer { + display: flex; + justify-content: space-between; + .content-with-alert { + display: flex; + align-items: center; + fa-icon { + color: red; + margin-right: 5px; + } + } +} + .back-to-top-container { position: fixed; bottom: 170px; @@ -327,10 +340,6 @@ text-decoration: none; } - .card-footer { - margin-top: 70%; - position: relative; - } .back-to-top-container { position: fixed; bottom: 100px; diff --git a/workspace/apps/pidp/src/app/features/portal/portal.page.spec.ts b/workspace/apps/pidp/src/app/features/portal/portal.page.spec.ts index 1560239f8..09298bb9c 100644 --- a/workspace/apps/pidp/src/app/features/portal/portal.page.spec.ts +++ b/workspace/apps/pidp/src/app/features/portal/portal.page.spec.ts @@ -1,31 +1,32 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { HttpClient } from '@angular/common/http'; +import { TestBed } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; + +import { provideAutoSpy } from 'jest-auto-spies'; + import { APP_CONFIG, APP_DI_CONFIG } from '@app/app.config'; + import { PortalPage } from './portal.page'; describe('PortalPage', () => { let component: PortalPage; - let fixture: ComponentFixture; - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [PortalPage, NoopAnimationsModule], + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [NoopAnimationsModule], providers: [ + PortalPage, { provide: APP_CONFIG, useValue: APP_DI_CONFIG, }, + provideAutoSpy(HttpClient), ], - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(PortalPage); - component = fixture.componentInstance; - fixture.detectChanges(); + }); + component = TestBed.inject(PortalPage); }); it('should create', () => { expect(component).toBeTruthy(); }); -}); \ No newline at end of file +}); diff --git a/workspace/apps/pidp/src/app/features/portal/portal.page.ts b/workspace/apps/pidp/src/app/features/portal/portal.page.ts index 056906c1e..61b2de425 100644 --- a/workspace/apps/pidp/src/app/features/portal/portal.page.ts +++ b/workspace/apps/pidp/src/app/features/portal/portal.page.ts @@ -1,18 +1,24 @@ import { STEPPER_GLOBAL_OPTIONS } from '@angular/cdk/stepper'; import { NgIf, NgOptimizedImage } from '@angular/common'; -import { Component, HostListener, Inject } from '@angular/core'; +import { Component, HostListener, OnInit } from '@angular/core'; import { Router } from '@angular/router'; +import { map } from 'rxjs'; + import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { faBell } from '@fortawesome/free-regular-svg-icons'; import { faArrowRight, faArrowUp } from '@fortawesome/free-solid-svg-icons'; import { InjectViewportCssClassDirective } from '@bcgov/shared/ui'; -import { APP_CONFIG, AppConfig } from '@app/app.config'; +import { PartyService } from '@app/core/party/party.service'; import { AccessRoutes } from '../access/access.routes'; import { OrganizationInfoRoutes } from '../organization-info/organization-info.routes'; import { ProfileRoutes } from '../profile/profile.routes'; +import { AlertCode } from './enums/alert-code.enum'; +import { ProfileStatus } from './models/profile-status.model'; +import { PortalResource } from './portal-resource.service'; @Component({ selector: 'app-portal', @@ -32,13 +38,20 @@ import { ProfileRoutes } from '../profile/profile.routes'; NgOptimizedImage, ], }) -export class PortalPage { +export class PortalPage implements OnInit { public faArrowRight = faArrowRight; public faArrowUp = faArrowUp; public showBackToTopButton: boolean = false; + public ProfileRoutes = ProfileRoutes; + public AccessRoutes = AccessRoutes; + public OrganizationInfoRoutes = OrganizationInfoRoutes; + public alerts: AlertCode[] = []; + public AlertCode = AlertCode; + public faBell = faBell; public constructor( - @Inject(APP_CONFIG) private config: AppConfig, + private partyService: PartyService, + private resource: PortalResource, private router: Router, ) {} @@ -52,26 +65,25 @@ export class PortalPage { const scrollThreshold = 200; this.showBackToTopButton = scrollPosition > scrollThreshold; } - + public scrollToTop(): void { window.scrollTo({ top: 0, behavior: 'smooth' }); } - - public navigateToAccountLinkingPage(): void { - this.router.navigateByUrl( - ProfileRoutes.routePath(ProfileRoutes.ACCOUNT_LINKING), - ); - } - public navigateToAccessPage(): void { - this.router.navigateByUrl( - AccessRoutes.routePath(AccessRoutes.ACCESS_REQUESTS), - ); + public navigateTo(path: string): void { + this.router.navigateByUrl(path); } - public navigateToEndorsements(): void { - this.router.navigateByUrl( - OrganizationInfoRoutes.routePath(OrganizationInfoRoutes.ENDORSEMENTS), - ); + public ngOnInit(): void { + const partyId = this.partyService.partyId; + this.resource + .getProfileStatus(partyId) + .pipe( + map( + (profileStatus: ProfileStatus | null) => + (this.alerts = profileStatus?.alerts ?? []), + ), + ) + .subscribe(); } } diff --git a/workspace/apps/pidp/src/app/features/portal/portal.service.ts b/workspace/apps/pidp/src/app/features/portal/portal.service.ts index 255645715..4c691c2b8 100644 --- a/workspace/apps/pidp/src/app/features/portal/portal.service.ts +++ b/workspace/apps/pidp/src/app/features/portal/portal.service.ts @@ -50,6 +50,12 @@ export class PortalService { * in the portal. */ private _alerts: ProfileStatusAlert[]; + /** + * @description + * List of HTTP response controlled alert messages for display + * in the College licence information page. + */ + private _licenceAlerts: ProfileStatusAlert[]; /** * @description * Whether all profile information has been completed, and @@ -67,6 +73,7 @@ export class PortalService { this.state$ = this._state$.asObservable(); this.accessState$ = this._accessState$.asObservable(); this._alerts = []; + this._licenceAlerts = []; this._completedProfile = false; } @@ -77,6 +84,10 @@ export class PortalService { return this._alerts; } + public get licenceAlerts(): ProfileStatusAlert[] { + return this._licenceAlerts; + } + public get hiddenSections(): PortalSectionStatusKey[] { const status = this._profileStatus?.status; @@ -97,6 +108,7 @@ export class PortalService { } this._profileStatus = profileStatus; this._alerts = this.getAlerts(profileStatus); + this._licenceAlerts = this.getLicenceAlerts(profileStatus); this._completedProfile = this.hasCompletedProfile(profileStatus); const builder = new PortalStateBuilder( @@ -115,6 +127,12 @@ export class PortalService { this.pasPanelExpanded$.next(expanded); } + private getLicenceAlerts(profileStatus: ProfileStatus): ProfileStatusAlert[] { + return this.getAlerts(profileStatus).filter( + (alert) => alert.content !== PendingEndorsementComponent, + ) as ProfileStatusAlert[]; + } + private getAlerts(profileStatus: ProfileStatus): ProfileStatusAlert[] { return profileStatus.alerts.map((alert) => { switch (alert) { diff --git a/workspace/apps/pidp/src/app/features/profile/pages/account-linking/account-linking-routing.routes.ts b/workspace/apps/pidp/src/app/features/profile/pages/account-linking/account-linking-routing.routes.ts index 2bf34e59d..bbefe2c95 100644 --- a/workspace/apps/pidp/src/app/features/profile/pages/account-linking/account-linking-routing.routes.ts +++ b/workspace/apps/pidp/src/app/features/profile/pages/account-linking/account-linking-routing.routes.ts @@ -1,7 +1,5 @@ import { Routes } from '@angular/router'; -import { setDashboardTitleGuard } from '@pidp/presentation'; - import { AccountLinkingPage } from './account-linking.page'; import { accountLinkingResolver } from './account-linking.resolver'; @@ -9,7 +7,6 @@ export const routes: Routes = [ { path: '', component: AccountLinkingPage, - canActivate: [setDashboardTitleGuard], resolve: { accountLinkingStatusCode: accountLinkingResolver, }, @@ -18,11 +15,6 @@ export const routes: Routes = [ routes: { root: '../../', }, - setDashboardTitleGuard: { - titleText: 'Welcome to OneHealthID Service', - titleDescriptionText: - 'Complete your profile to gain access to the systems you are eligible for', - }, }, }, ]; diff --git a/workspace/apps/pidp/src/app/features/profile/pages/account-linking/account-linking.page.scss b/workspace/apps/pidp/src/app/features/profile/pages/account-linking/account-linking.page.scss index 293cd2edf..a6ed3b55c 100644 --- a/workspace/apps/pidp/src/app/features/profile/pages/account-linking/account-linking.page.scss +++ b/workspace/apps/pidp/src/app/features/profile/pages/account-linking/account-linking.page.scss @@ -683,9 +683,3 @@ div.viewport-large { } } } - -::ng-deep .dialog-container { - mat-dialog-container { - padding: 0.5rem; - } -} diff --git a/workspace/apps/pidp/src/app/features/profile/pages/account-linking/account-linking.page.ts b/workspace/apps/pidp/src/app/features/profile/pages/account-linking/account-linking.page.ts index f8e9abf77..1f02ad69c 100644 --- a/workspace/apps/pidp/src/app/features/profile/pages/account-linking/account-linking.page.ts +++ b/workspace/apps/pidp/src/app/features/profile/pages/account-linking/account-linking.page.ts @@ -131,7 +131,7 @@ export class AccountLinkingPage implements OnInit, OnDestroy { height: '24rem', actionText: 'Continue', actionTypePosition: 'center', - class: 'dialog-container', + class: 'dialog-container dialog-padding', }; this.dialog .open(ConfirmDialogComponent, { data }) diff --git a/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-declaration/college-licence-declaration-routing.routes.ts b/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-declaration/college-licence-declaration-routing.routes.ts index ca473d959..c68ec7a98 100644 --- a/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-declaration/college-licence-declaration-routing.routes.ts +++ b/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-declaration/college-licence-declaration-routing.routes.ts @@ -1,7 +1,5 @@ import { Routes } from '@angular/router'; -import { setDashboardTitleGuard } from '@pidp/presentation'; - import { canDeactivateFormGuard } from '@app/core/guards/can-deactivate-form.guard'; import { highAssuranceCredentialGuard } from '@app/features/auth/guards/high-assurance-credential.guard'; import { collegeLicenceCompletedResolver } from '@app/features/auth/resolvers/college-licence-completed.resolver'; @@ -12,7 +10,7 @@ export const routes: Routes = [ { path: '', component: CollegeLicenceDeclarationPage, - canActivate: [setDashboardTitleGuard, highAssuranceCredentialGuard], + canActivate: [highAssuranceCredentialGuard], canDeactivate: [canDeactivateFormGuard], resolve: { hasCompletedDeclaration: collegeLicenceCompletedResolver, @@ -22,11 +20,6 @@ export const routes: Routes = [ routes: { root: '../../', }, - setDashboardTitleGuard: { - titleText: 'College Licence Information', - titleDescriptionText: - 'Provide the following information to complete your Provider Identity Profile', - }, }, }, ]; diff --git a/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-declaration/college-licence-declaration.page.ts b/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-declaration/college-licence-declaration.page.ts index 7814245f1..1715fade1 100644 --- a/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-declaration/college-licence-declaration.page.ts +++ b/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-declaration/college-licence-declaration.page.ts @@ -11,9 +11,7 @@ import { ActivatedRoute, Router } from '@angular/router'; import { EMPTY, Observable, catchError, of, tap } from 'rxjs'; -import { DashboardStateModel, PidpStateName } from '@pidp/data-model'; import { RegisteredCollege } from '@pidp/data-model'; -import { AppStateService } from '@pidp/presentation'; import { AlertComponent, @@ -28,7 +26,12 @@ import { } from '@app/core/classes/abstract-form-page.class'; import { PartyService } from '@app/core/party/party.service'; import { LoggerService } from '@app/core/services/logger.service'; +import { + DashboardStateModel, + PidpStateName, +} from '@app/features/portal/models/state.model'; import { ProfileRoutes } from '@app/features/profile/profile.routes'; +import { AppStateService } from '@app/features/shell/services/app-state.service'; import { LookupService } from '@app/modules/lookup/lookup.service'; import { CollegeLookup } from '@app/modules/lookup/lookup.types'; diff --git a/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-information/college-licence-information-routing.routes.ts b/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-information/college-licence-information-routing.routes.ts index 214c40aef..f05ebdeac 100644 --- a/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-information/college-licence-information-routing.routes.ts +++ b/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-information/college-licence-information-routing.routes.ts @@ -1,7 +1,5 @@ import { Routes } from '@angular/router'; -import { setDashboardTitleGuard } from '@pidp/presentation'; - import { highAssuranceCredentialGuard } from '@app/features/auth/guards/high-assurance-credential.guard'; import { collegeLicenceInfoResolver } from '@app/features/auth/resolvers/college-licence-info.resolver'; @@ -14,17 +12,12 @@ export const routes: Routes = [ resolve: { hasCpn: collegeLicenceInfoResolver, }, - canActivate: [setDashboardTitleGuard, highAssuranceCredentialGuard], + canActivate: [highAssuranceCredentialGuard], data: { title: 'OneHealthID Service', routes: { root: '../../', }, - setDashboardTitleGuard: { - titleText: 'Welcome to OneHealthID Service', - titleDescriptionText: - 'Complete your profile to gain access to the systems you are eligible for', - }, }, }, ]; diff --git a/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-information/college-licence-information.page.html b/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-information/college-licence-information.page.html index ca7d657c5..e96315eec 100644 --- a/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-information/college-licence-information.page.html +++ b/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-information/college-licence-information.page.html @@ -1,4 +1,9 @@
    +
    + +

    All licence information found in our records

    diff --git a/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-information/college-licence-information.page.spec.ts b/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-information/college-licence-information.page.spec.ts index f450c748d..a6531d6e7 100644 --- a/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-information/college-licence-information.page.spec.ts +++ b/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-information/college-licence-information.page.spec.ts @@ -8,6 +8,7 @@ import { RouterTestingModule } from '@angular/router/testing'; import { randTextRange } from '@ngneat/falso'; import { createSpyFromClass, provideAutoSpy } from 'jest-auto-spies'; +import { KeycloakService } from 'keycloak-angular'; import { APP_CONFIG, APP_DI_CONFIG } from '@app/app.config'; import { PartyService } from '@app/core/party/party.service'; @@ -61,6 +62,7 @@ describe('CollegeLicenceInformationPage', () => { provideAutoSpy(Router), provideAutoSpy(LoggerService), provideAutoSpy(CollegeLicenceInformationResource), + provideAutoSpy(KeycloakService), ], }); router = TestBed.inject(Router); diff --git a/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-information/college-licence-information.page.ts b/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-information/college-licence-information.page.ts index fcd377f6d..f72a3e9d3 100644 --- a/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-information/college-licence-information.page.ts +++ b/workspace/apps/pidp/src/app/features/profile/pages/college-licence/college-licence-information/college-licence-information.page.ts @@ -4,7 +4,7 @@ import { Component, OnInit } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { ActivatedRoute, Router } from '@angular/router'; -import { Observable, catchError, map, of } from 'rxjs'; +import { Observable, catchError, map, of, tap } from 'rxjs'; import { FaIconComponent } from '@fortawesome/angular-fontawesome'; import { faStethoscope } from '@fortawesome/free-solid-svg-icons'; @@ -13,6 +13,11 @@ import { InjectViewportCssClassDirective } from '@bcgov/shared/ui'; import { PartyService } from '@app/core/party/party.service'; import { LoggerService } from '@app/core/services/logger.service'; +import { PortalAlertComponent } from '@app/features/portal/components/portal-alert/portal-alert.component'; +import { ProfileStatusAlert } from '@app/features/portal/models/profile-status-alert.model'; +import { ProfileStatus } from '@app/features/portal/models/profile-status.model'; +import { PortalResource } from '@app/features/portal/portal-resource.service'; +import { PortalService } from '@app/features/portal/portal.service'; import { CollegeCertification } from '../college-licence-declaration/college-certification.model'; import { CollegeLicenceInformationResource } from './college-licence-information-resource.service'; @@ -30,6 +35,7 @@ import { CollegeLicenceInformationDetailComponent } from './components/college-l InjectViewportCssClassDirective, MatButtonModule, NgFor, + PortalAlertComponent, ], }) export class CollegeLicenceInformationPage implements OnInit { @@ -37,6 +43,7 @@ export class CollegeLicenceInformationPage implements OnInit { public title: string; public collegeCertifications$!: Observable; + public alerts: ProfileStatusAlert[] = []; public constructor( private route: ActivatedRoute, @@ -44,6 +51,8 @@ export class CollegeLicenceInformationPage implements OnInit { private partyService: PartyService, private resource: CollegeLicenceInformationResource, private logger: LoggerService, + private portalResource: PortalResource, + private portalService: PortalService, ) { this.title = this.route.snapshot.data.title; } @@ -68,9 +77,25 @@ export class CollegeLicenceInformationPage implements OnInit { return of([]); }), ); + + const profileStatus$ = this.portalResource.getProfileStatus( + this.partyService.partyId, + ); + this.updateAlerts(profileStatus$); } private navigateToRoot(): void { this.router.navigate([this.route.snapshot.data.routes.root]); } + + private updateAlerts(profileStatus$: Observable): void { + profileStatus$ + .pipe( + tap((profileStatus: ProfileStatus | null) => { + this.portalService.updateState(profileStatus); + this.alerts = this.portalService.licenceAlerts; + }), + ) + .subscribe(); + } } diff --git a/workspace/apps/pidp/src/app/features/profile/pages/personal-information/personal-information-routing.routes.ts b/workspace/apps/pidp/src/app/features/profile/pages/personal-information/personal-information-routing.routes.ts index 2bb374d35..9c9e15000 100644 --- a/workspace/apps/pidp/src/app/features/profile/pages/personal-information/personal-information-routing.routes.ts +++ b/workspace/apps/pidp/src/app/features/profile/pages/personal-information/personal-information-routing.routes.ts @@ -1,7 +1,5 @@ import { Routes } from '@angular/router'; -import { setDashboardTitleGuard } from '@pidp/presentation'; - import { canDeactivateFormGuard } from '@app/core/guards/can-deactivate-form.guard'; import { PersonalInformationPage } from './personal-information.page'; @@ -10,18 +8,12 @@ export const routes: Routes = [ { path: '', component: PersonalInformationPage, - canActivate: [setDashboardTitleGuard], canDeactivate: [canDeactivateFormGuard], data: { title: 'OneHealthID Service', routes: { root: '../../', }, - setDashboardTitleGuard: { - titleText: 'Welcome to OneHealthID Service', - titleDescriptionText: - 'Complete your profile to gain access to the systems you are eligible for', - }, }, }, ]; diff --git a/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/components/user-access-agreement-document/user-access-agreement-document.component.html b/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/components/user-access-agreement-document/user-access-agreement-document.component.html index e14fe247a..913c22598 100644 --- a/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/components/user-access-agreement-document/user-access-agreement-document.component.html +++ b/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/components/user-access-agreement-document/user-access-agreement-document.component.html @@ -1,184 +1,184 @@ - - Access Harmonization User Access Agreement - +

    +
    +

    Access harmonization user access agreement

    +
    - - Background 1.0 -

    - This Agreement is made between me and His Majesty the King in right of the - Province of British Columbia, as represented by the Minister of Health (the - “Province”), and describes the basic terms and conditions that I (the user) - must comply with in order to enroll for access to clinical health systems - available through the Province's OneHealthID Services ("OneHealthID"). -

    +
    +
    +
    +

    Background

    +

    + This Agreement is made between me and His Majesty the King in right of + the Province of British Columbia, as represented by the Minister of + Health (the “Province”) and describes the basic terms and conditions + that I (the user) must comply with in order to enroll for access to + clinical health systems available through the Province's OneHealthID + Services (“OneHealthID”). +

    -

    - This Agreement does not guarantee access will be granted, System Owner(s) - may, at their discretion, amend or change the scope of my access privileges - to the System as privacy, security, business, and clinical practice - requirements change. In such circumstances, the System Owner will notify me - of such changes. -

    - +

    + This Agreement does not guarantee access will be granted, System + Owner(s) may, at their discretion, amend or change the scope of my + access privileges to the System as privacy, security, business, and + clinical practice requirements change. In such circumstances, the + System Owner will notify me of such changes. +

    +
    - - Definitions 2.0 +
    +

    User Access Agreement

    +
      +
    • +

      + For Providers registered with a Professional College in BC: +

      -
        -
      • - 2.1"Provider" means a person who practices a designated - health profession regulated by the - Health Professions Act and is in good standing with their - Professional College. -
      • -
      • - 2.2"OneHealthID Services" means the Province's suite of - identity and access tools, including the platform where Providers and - Supervised users may apply for access to Systems. -
      • -
      • - 2.3"Supervised User" means any member of a Provider's - staff who is required to access a System in relation to the Provider's - practice. -
      • -
      • - 2.4"System" means the various provincial or private - computerized information systems available to access health information - in BC. -
      • -
      • - 2.5"System Owner" means the Health Authority, Ministry or - organization responsible and accountable for data stored within a - System. -
      • -
      - +
        +
      1. +

        + I will only access the System(s) for so long as I am a + registrant in good standing with my Professional College. +

        +
      2. +
      +
    • +
    • +

      + For Supervised Users Accessing System(s) on behalf of a College + Registrant: +

      +
        +
      1. +

        + I will only access the System(s) for so long as I am accessing + the System(s) on behalf of a Provider that meets the criteria + above. +

        +
      2. +
      +
    • +
    • +

      + I will only access the System(s) as necessary to perform my role + and duties, unless permitted by the System Owner(s). +

      +
    • +
    • +

      + I will cooperate with the execution of the System Owner's breach + management plan including responding, reporting and containing any + potential or known breach of personal information including any + unauthorized attempt, by any person, to access the System(s). +

      +
    • +
    +
    - - User Access Agreement 3.0 -
      -
    • - 3.1For Providers registered with a Professional College in BC:
      a. -

      - I will only access the System(s) for so long as I am a registrant in - good standing with my Professional College. -

      -
    • -
    • - 3.2For Supervised Users Accessing System(s) on behalf of a College - Registrant:
      a. -

      - I will only access the System(s) for so long as I am accessing the - System(s) on behalf of a Provider that meets the criteria above. -

      -
    • -
    • - 3.3 - I will only access the System(s) as necessary to perform my role and - duties, unless permitted by the System Owner(s). -
    • -
    • - 3.4 - I will cooperate with the execution of the System Owner's breach - management plan including responding, reporting and containing any - potential or known breach of personal information including any - unauthorized attempt, by any person, to access the System(s). -
    • -
    • - 3.5I will not permit any other person to access the System(s) with my - credentials and will take all reasonable measures to prevent - unauthorized access from occurring. -
    • -
    • - 3.6 - I will store all relevant System(s) data or personal information in - accordance with my or my supervising Provider's Professional College - Requirements and the System Owner's organizational policies. -
    • -
    • - 3.7 - I will ensure to the best of my ability that any personal information I - record in the System(s) about myself, or others is accurate, complete, - and up to date. -
    • -
    • - 3.8 - I will notify the System(s) Owner of any inaccuracy or errors. -
    • -
    • - 3.9 - I will cooperate with any IM/IT system audits and investigations - conducted by System Owners. -
    • -
    • - 3.10 - I acknowledge the System(s) Owner may report any material breach of this - Agreement to the Office of the Information and Privacy Commissioner of - British Columbia, and/or my organization/supervising Provider. -
    • -
    +
    +
    +
    +
    +

    + I will not permit any other person to access the System(s) with + my credentials and will take all reasonable measures to prevent + unauthorized access from occurring. +

    +
    +
    +

    + I will store all relevant System(s) data or personal information + in accordance with my or my supervising Provider's Professional + College Requirements and the System Owner's organizational + policies. +

    +
    +
    +
    +
    +

    + I will ensure to the best of my ability that any personal + information I record in the System(s) about myself, or others is + accurate, complete, and up to date. +

    -

    - The terms and conditions of this Agreement may be amended by the Province at - any time, in its sole discretion, by the Province delivering written notice - of the amendment to the email address indicated in my OneHealthID profile. - Any such notice will specify the date upon which the amendment becomes - effective. If I continue to access any of the Systems enrolled through the - OneHealthID after the effective date of the amendment, I will be deemed to - have accepted the amendment. If I do not agree with an amendment for which - notice has been provided by the Province, I must promptly (and in any event - prior to the effective date) cease all access or use of all Systems enrolled - through the OneHealthID. -

    - +

    +
    +
    +

    + I will notify the System(s) Owner of any inaccuracy or errors. +

    +
    +
    +
    + +

    + I will cooperate with any IM/IT system audits and investigations + conducted by System Owners. +

    +

    + I acknowledge the System(s) Owner may report any material breach of + this Agreement to the Office of the Information and Privacy + Commissioner of British Columbia, and/or my organization/supervising + Provider. +

    + +

    + The terms and conditions of this Agreement may be amended by the + Province at any time, in its sole discretion, by the Province + delivering written notice of the amendment to the email address + indicated in my OneHealthID profile. Any such notice will specify the + date upon which the amendment becomes effective. If I continue to + access any of the Systems enrolled through the OneHealthID after the + effective date of the amendment, I will be deemed to have accepted the + amendment. If I do not agree with an amendment for which notice has + been provided by the Province, I must promptly (and in any event prior + to the effective date) cease all access or use of all Systems enrolled + through the OneHealthID. +

    +
    +
    + +
    +

    Definitions

    +
      +
    • + + +
    • +
    • + + +
    • +
    • + + +
    • +
    • + + +
    • +
    • + + +
    • +
    +
    +
    +
    diff --git a/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/components/user-access-agreement-document/user-access-agreement-document.component.scss b/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/components/user-access-agreement-document/user-access-agreement-document.component.scss index bec63b6e1..5f61d9ef4 100644 --- a/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/components/user-access-agreement-document/user-access-agreement-document.component.scss +++ b/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/components/user-access-agreement-document/user-access-agreement-document.component.scss @@ -1,6 +1,5 @@ -p, -ul { - margin-bottom: 1.5rem; +.viewport-all { + padding: 1.25rem 0.75rem 0 0.75rem; } ul { @@ -9,30 +8,148 @@ ul { margin-left: 0; } -.definitions li { - display: flex; - margin-bottom: 1rem; -} +.viewport-all { + .content-header h1 { + color: #003366; + font-size: 50px; + font-weight: 700; + word-wrap: break-word; + } + + .page-sections { + display: grid; + grid-template-columns: calc(70% - 15px) calc(30% - 10px); + gap: 20px; + margin: 2rem 0; + + .main-container { + .sub-header { + color: #2d2d2d; + font-size: 1.5rem; + font-weight: 700; + line-height: 1.6875rem; + margin: 1.5rem 0; + } + + .body-text { + color: #313132; + font-size: 1rem; + line-height: 1.6875rem; + margin-top: 1.5rem; + } + + .ordered-list { + list-style-type: lower-alpha; + } + + .margin-left-2 { + margin-left: 2rem; + } + + .body-grid-container { + display: flex; + + .first-row, + .second-row { + flex: 0.5; + + .grid-column { + background-image: linear-gradient( + to bottom, + rgba(255, 255, 255, 0) 1px, + #fcba19 1px + ); + background-position: bottom; + background-size: 20% 3px; + background-repeat: no-repeat; + padding: 1rem 1rem 1rem 0; + min-height: 13rem; + + p { + color: #707070; + font-size: 1rem; + font-style: italic; + } + } + } + } + } + + .definitions-container { + .sub-header { + color: #2d2d2d; + font-size: 1.5rem; + font-weight: 700; + line-height: 1.6875rem; + margin: 1.5rem 0; + } -.uaa li { - display: flex; - margin-bottom: 1rem; + .sidebar-header { + color: #2d2d2d; + font-size: 1.25rem; + } - p.uaa-section-bullet-inside { - margin-bottom: 0; - margin-left: 2rem; + .sidebar-body { + color: #707070; + font-size: 1rem; + } + } } } -.uaa-section { - display: flex; - margin-left: 2rem; - - .uaa-section-bullet { - margin-left: 1rem; +.viewport-small { + .content-header h1 { + font-size: 40px; } } -.section { - padding: 5px; +.viewport-xsmall { + .content-header h1 { + font-size: 40px; + } + + .page-sections { + grid-template-columns: 100%; + + .main-container { + .sub-header { + font-size: 1.2rem; + } + + .body-text { + font-size: 0.8rem; + } + + .margin-left-2 { + margin-left: 1.2rem; + } + + .body-grid-container { + display: flex; + + .first-row, + .second-row { + .grid-column { + p { + font-size: 0.8rem; + } + } + } + } + } + + .definitions-container { + .sub-header { + font-size: 1.2rem; + } + + .sidebar-header { + font-size: 1rem; + } + + .sidebar-body { + font-size: 0.8rem; + } + } + } } diff --git a/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/components/user-access-agreement-document/user-access-agreement-document.component.ts b/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/components/user-access-agreement-document/user-access-agreement-document.component.ts index 8bd64baed..9eba963b2 100644 --- a/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/components/user-access-agreement-document/user-access-agreement-document.component.ts +++ b/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/components/user-access-agreement-document/user-access-agreement-document.component.ts @@ -1,6 +1,7 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; import { + InjectViewportCssClassDirective, PageHeaderComponent, PageSectionComponent, PageSubheaderComponent, @@ -14,7 +15,12 @@ import { userAccessAgreementTitle } from '@app/features/profile/pages/user-acces styleUrls: ['./user-access-agreement-document.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, - imports: [PageHeaderComponent, PageSectionComponent, PageSubheaderComponent], + imports: [ + PageHeaderComponent, + PageSectionComponent, + InjectViewportCssClassDirective, + PageSubheaderComponent, + ], }) export class UserAccessAgreementDocumentComponent { public readonly title: string; diff --git a/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/user-access-agreement-routing.routes.ts b/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/user-access-agreement-routing.routes.ts index c1eae3d17..3156bd931 100644 --- a/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/user-access-agreement-routing.routes.ts +++ b/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/user-access-agreement-routing.routes.ts @@ -16,11 +16,6 @@ export const routes: Routes = [ title: userAccessAgreementTitle, routes: { root: '../../', - setDashboardTitleGuard: { - titleText: 'Welcome to OneHealthID Service', - titleDescriptionText: - 'Complete your profile to gain access to the systems you are eligible for', - }, }, }, }, diff --git a/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/user-access-agreement.page.html b/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/user-access-agreement.page.html index 187f2d0b1..1fa4a9758 100644 --- a/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/user-access-agreement.page.html +++ b/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/user-access-agreement.page.html @@ -1,55 +1,54 @@ -
    - - - -

    - Your acceptance of the agreement could not be processed at this time. If - this issue persists, contact - - for assistance. -

    -
    -
    +
    + + + +

    + Your acceptance of the agreement could not be processed at this time. + If this issue persists, contact + + for assistance. +

    +
    +
    - + -

    - - I, - {{ (dashboardState$ | async)?.userProfileFullNameText }}, represent and warrant that all information provided in connection with - my application for access to the System(s), is true and correct. - -

    +

    + I, + {{ (dashboardState$ | async)?.userProfileFullNameText }}, represent and warrant that all information provided in connection with + my application for access to the System(s), is true and correct. +

    - - - - -
    +
    + + +
    +
    diff --git a/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/user-access-agreement.page.scss b/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/user-access-agreement.page.scss index f0b3b42ff..0b4097e8d 100644 --- a/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/user-access-agreement.page.scss +++ b/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/user-access-agreement.page.scss @@ -14,4 +14,25 @@ p { .viewport-all { padding: 1.25rem 0.75rem; + + .padding-container { + padding: 0 0.75rem; + margin-bottom: 1rem; + grid-template-columns: calc(70% - 15px); + display: grid; + margin-top: -1rem; + } +} + +.viewport-xsmall { + .padding-container { + grid-template-columns: 100%; + } +} + +.button-container { + .back-button { + margin-right: 2rem; + margin-left: 0.75rem; + } } diff --git a/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/user-access-agreement.page.ts b/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/user-access-agreement.page.ts index 205428c71..cef6ca283 100644 --- a/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/user-access-agreement.page.ts +++ b/workspace/apps/pidp/src/app/features/profile/pages/user-access-agreement/user-access-agreement.page.ts @@ -6,13 +6,11 @@ import { ActivatedRoute, Router } from '@angular/router'; import { Observable, catchError, noop, of, tap } from 'rxjs'; -import { DashboardStateModel, PidpStateName } from '@pidp/data-model'; -import { AppStateService } from '@pidp/presentation'; - import { AlertComponent, AlertContentDirective, AnchorDirective, + InjectViewportCssClassDirective, PageComponent, PageFooterActionDirective, PageFooterComponent, @@ -23,6 +21,11 @@ import { LoggerService } from '@app/core/services/logger.service'; import { UtilsService } from '@app/core/services/utils.service'; import { specialAuthorityEformsSupportEmail } from '@app/features/access/pages/sa-eforms/sa-eforms.constants'; import { StatusCode } from '@app/features/portal/enums/status-code.enum'; +import { + DashboardStateModel, + PidpStateName, +} from '@app/features/portal/models/state.model'; +import { AppStateService } from '@app/features/shell/services/app-state.service'; import { UserAccessAgreementDocumentComponent } from './components/user-access-agreement-document/user-access-agreement-document.component'; import { UserAccessAgreementResource } from './user-access-agreement-resource.service'; @@ -37,6 +40,7 @@ import { UserAccessAgreementResource } from './user-access-agreement-resource.se AlertContentDirective, AnchorDirective, AsyncPipe, + InjectViewportCssClassDirective, forwardRef(() => UserAccessAgreementDocumentComponent), MatButtonModule, NgIf, diff --git a/workspace/libs/shared/ui/src/lib/modules/dashboard/components/navbar-menu/nav-menu.html b/workspace/apps/pidp/src/app/features/shell/components/navbar-menu/nav-menu.html similarity index 73% rename from workspace/libs/shared/ui/src/lib/modules/dashboard/components/navbar-menu/nav-menu.html rename to workspace/apps/pidp/src/app/features/shell/components/navbar-menu/nav-menu.html index b0a8b2818..96c1fcfbc 100644 --- a/workspace/libs/shared/ui/src/lib/modules/dashboard/components/navbar-menu/nav-menu.html +++ b/workspace/apps/pidp/src/app/features/shell/components/navbar-menu/nav-menu.html @@ -7,6 +7,8 @@ mat-icon-button (click)="onMiniMenuButtonClick()"> menu +
    @@ -30,21 +32,30 @@