diff --git a/backend/Application/Aggregates/Contract/Entities/Contract.cs b/backend/Application/Aggregates/Contract/Entities/Contract.cs index c31b6349f..065dc0a5b 100644 --- a/backend/Application/Aggregates/Contract/Entities/Contract.cs +++ b/backend/Application/Aggregates/Contract/Entities/Contract.cs @@ -109,7 +109,7 @@ public IQueryable GetContracts( } /// - /// Adds additional field to the returned GraphQL type + /// Adds additional field to the GraphQL type /// [ExtendObjectType(typeof(Contract))] public sealed class ContractExtensions diff --git a/backend/Application/Aggregates/Contract/Entities/ModuleReferenceContractLinkEvent.cs b/backend/Application/Aggregates/Contract/Entities/ModuleReferenceContractLinkEvent.cs index 98bf7fa76..502e2c692 100644 --- a/backend/Application/Aggregates/Contract/Entities/ModuleReferenceContractLinkEvent.cs +++ b/backend/Application/Aggregates/Contract/Entities/ModuleReferenceContractLinkEvent.cs @@ -1,6 +1,8 @@ using Application.Aggregates.Contract.Types; using Application.Api.GraphQL; using Application.Api.GraphQL.Accounts; +using HotChocolate; +using HotChocolate.Types; namespace Application.Aggregates.Contract.Entities; @@ -55,4 +57,14 @@ public enum ModuleReferenceContractLinkAction Added, Removed } + + /// + /// Adds additional fields to the GraphQL type . + /// + [ExtendObjectType(typeof(ModuleReferenceContractLinkEvent))] + public sealed class ModuleReferenceContractLinkEventExtensions + { + public ContractAddress GetContractAddress([Parent] ModuleReferenceContractLinkEvent linkEvent) => + new(linkEvent.ContractAddressIndex, linkEvent.ContractAddressSubIndex); + } } diff --git a/backend/Application/Aggregates/Contract/Entities/ModuleReferenceEvent.cs b/backend/Application/Aggregates/Contract/Entities/ModuleReferenceEvent.cs index 222204108..fc152a2a7 100644 --- a/backend/Application/Aggregates/Contract/Entities/ModuleReferenceEvent.cs +++ b/backend/Application/Aggregates/Contract/Entities/ModuleReferenceEvent.cs @@ -1,5 +1,12 @@ +using System.Threading.Tasks; using Application.Aggregates.Contract.Types; +using Application.Api.GraphQL; using Application.Api.GraphQL.Accounts; +using Application.Api.GraphQL.EfCore; +using HotChocolate; +using HotChocolate.Types; +using Microsoft.EntityFrameworkCore; +using Polly; namespace Application.Aggregates.Contract.Entities; @@ -11,7 +18,21 @@ public sealed class ModuleReferenceEvent : BaseIdentification public uint EventIndex { get; init; } public string ModuleReference { get; init; } = null!; public AccountAddress Sender { get; init; } = null!; - + /// + /// It is important, that when pagination is used together with a return type + /// then aggregation result like will not be correct. + /// + /// Hence pagination should only by used in cases where database query has executed like + /// . + /// + [UsePaging(IncludeTotalCount = true)] + public IList ModuleReferenceContractLinkEvents { get; init; } = null!; + /// + /// See pagination comment on above. + /// + [UsePaging(IncludeTotalCount = true)] + public IList ModuleReferenceRejectEvents { get; init; } = null!; + /// /// Needed for EF Core /// @@ -33,4 +54,60 @@ public ModuleReferenceEvent( ModuleReference = moduleReference; Sender = sender; } + + [ExtendObjectType(typeof(Query))] + public class ModuleReferenceEventQuery + { + public Task GetModuleReferenceEvent(GraphQlDbContext context, string moduleReference) + { + return context.ModuleReferenceEvents + .AsSplitQuery() + .AsNoTracking() + .Where(m => m.ModuleReference == moduleReference) + .Include(m => m.ModuleReferenceContractLinkEvents + .OrderByDescending(me => me.BlockHeight) + .ThenByDescending(me => me.TransactionIndex) + .ThenByDescending(me => me.EventIndex)) + .Include(m => m.ModuleReferenceRejectEvents + .OrderByDescending(me => me.BlockHeight) + .ThenByDescending(me => me.TransactionIndex)) + .SingleOrDefaultAsync(); + } + } + + /// + /// Adds additional fields to the GraphQL type . + /// + [ExtendObjectType(typeof(ModuleReferenceEvent))] + public sealed class ModuleReferenceEventExtensions + { + [UsePaging(IncludeTotalCount = true)] + public IList GetLinkedContracts([Parent] ModuleReferenceEvent moduleReferenceEvent) + { + var map = new Dictionary<(ulong, ulong), DateTimeOffset>(); + foreach (var moduleReferenceContractLinkEvent in moduleReferenceEvent.ModuleReferenceContractLinkEvents + .OrderBy(me => me.BlockHeight) + .ThenBy(me => me.TransactionIndex) + .ThenBy(me => me.EventIndex)) + { + switch (moduleReferenceContractLinkEvent.LinkAction) + { + case ModuleReferenceContractLinkEvent.ModuleReferenceContractLinkAction.Added: + map[(moduleReferenceContractLinkEvent.ContractAddressIndex, moduleReferenceContractLinkEvent.ContractAddressSubIndex)] = moduleReferenceContractLinkEvent.BlockSlotTime; + break; + case ModuleReferenceContractLinkEvent.ModuleReferenceContractLinkAction.Removed: + map.Remove((moduleReferenceContractLinkEvent.ContractAddressIndex, + moduleReferenceContractLinkEvent.ContractAddressSubIndex)); + break; + } + } + + return map + .Select(entry => new LinkedContract(new ContractAddress(entry.Key.Item1, entry.Key.Item2), entry.Value)) + .OrderByDescending(l => l.LinkedDateTime) + .ToList(); + } + } } + +public record LinkedContract(ContractAddress ContractAddress, DateTimeOffset LinkedDateTime); diff --git a/backend/Application/Aggregates/Contract/Extensions/ContractExtensions.cs b/backend/Application/Aggregates/Contract/Extensions/ContractExtensions.cs index 8aac2379d..53111f22a 100644 --- a/backend/Application/Aggregates/Contract/Extensions/ContractExtensions.cs +++ b/backend/Application/Aggregates/Contract/Extensions/ContractExtensions.cs @@ -51,7 +51,10 @@ internal static IRequestExecutorBuilder AddContractGraphQlConfigurations(this IR { builder .AddType() - .AddTypeExtension(); + .AddTypeExtension() + .AddType() + .AddTypeExtension() + .AddTypeExtension(); return builder; } diff --git a/backend/Application/Api/GraphQL/Search/SearchResult.cs b/backend/Application/Api/GraphQL/Search/SearchResult.cs index 8ca01d459..1fa703478 100644 --- a/backend/Application/Api/GraphQL/Search/SearchResult.cs +++ b/backend/Application/Api/GraphQL/Search/SearchResult.cs @@ -43,6 +43,22 @@ public IQueryable GetContracts(GraphQlDbContext context) .ThenByDescending(c => c.ContractAddressSubIndex); } + [UsePaging] + public IQueryable GetModules(GraphQlDbContext context) + { + if (string.IsNullOrEmpty(_queryString) || !HashRegex.IsMatch(_queryString)) + { + return new List().AsQueryable(); + } + + var lowerCaseQuery = _queryString.ToLowerInvariant() + "%"; + return context.ModuleReferenceEvents.AsNoTracking() + .Where(module => EF.Functions.Like(module.ModuleReference, lowerCaseQuery)) + .OrderByDescending(module => module.BlockHeight) + .ThenByDescending(module => module.TransactionIndex) + .ThenByDescending(module => module.EventIndex); + } + [UseDbContext(typeof(GraphQlDbContext))] [UsePaging] public IQueryable GetBlocks([ScopedService] GraphQlDbContext dbContext) diff --git a/backend/CHANGELOG.md b/backend/CHANGELOG.md index f3e02eef6..5ec049101 100644 --- a/backend/CHANGELOG.md +++ b/backend/CHANGELOG.md @@ -5,8 +5,9 @@ - Duration of GraphQL endpoints - Added health checks, where application goes into degraded state if some job stops running. These health checks are now making endpoint `rest/health` redundant and it is removed. - Added GraphQL endpoints - - Contract listing with pagination -- Extended search functionality to include contracts. + - Contract listing with pagination and details page. + - Module details page. +- Extended search functionality to include contracts and modules. - Updated - `HotChocolate` nuget libraries from major `12` to `13`. Because of this done some migration changes like adding `RegisterDbContext(DbContextKind.Pooled)` to GraphQL schema configuration *(migration documentation located at: https://chillicream.com/docs/hotchocolate/v13/migrating/migrate-from-12-to-13)*. diff --git a/backend/Tests/Aggregates/Contract/Entities/ModuleReferenceEventTests.cs b/backend/Tests/Aggregates/Contract/Entities/ModuleReferenceEventTests.cs new file mode 100644 index 000000000..d909af308 --- /dev/null +++ b/backend/Tests/Aggregates/Contract/Entities/ModuleReferenceEventTests.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using Application.Aggregates.Contract.Entities; +using Application.Api.GraphQL; +using FluentAssertions; +using Tests.TestUtilities.Builders; + +namespace Tests.Aggregates.Contract.Entities; + +public sealed class ModuleReferenceEventTests +{ + [Fact] + public void WhenGetLinkedContract_ThenReturnThoseWhichHasNotBeenRemoved() + { + // Arrange + var contractFirst = new ContractAddress(1, 0); + var contractSecond = new ContractAddress(2, 0); + var contractThird = new ContractAddress(3, 0); + const string moduleReference = "fooBart"; + var firstEvent = ModuleReferenceContractLinkEventBuilder.Create() + .WithBlockHeight(1) + .WithTransactionIndex(0) + .WithEventIndex(0) + .WithLinkAction(ModuleReferenceContractLinkEvent.ModuleReferenceContractLinkAction.Added) + .WithModuleReference(moduleReference) + .WithContractAddress(contractFirst) + .Build(); + var secondEvent = ModuleReferenceContractLinkEventBuilder.Create() + .WithBlockHeight(1) + .WithTransactionIndex(1) + .WithEventIndex(0) + .WithLinkAction(ModuleReferenceContractLinkEvent.ModuleReferenceContractLinkAction.Added) + .WithModuleReference(moduleReference) + .WithContractAddress(contractSecond) + .Build(); + var thirdEvent = ModuleReferenceContractLinkEventBuilder.Create() + .WithBlockHeight(2) + .WithTransactionIndex(0) + .WithEventIndex(0) + .WithLinkAction(ModuleReferenceContractLinkEvent.ModuleReferenceContractLinkAction.Removed) + .WithModuleReference(moduleReference) + .WithContractAddress(contractFirst) + .Build(); + var fourthEvent = ModuleReferenceContractLinkEventBuilder.Create() + .WithBlockHeight(2) + .WithTransactionIndex(0) + .WithEventIndex(1) + .WithLinkAction(ModuleReferenceContractLinkEvent.ModuleReferenceContractLinkAction.Added) + .WithModuleReference(moduleReference) + .WithContractAddress(contractThird) + .Build(); + var fifthEvent = ModuleReferenceContractLinkEventBuilder.Create() + .WithBlockHeight(2) + .WithTransactionIndex(0) + .WithEventIndex(2) + .WithLinkAction(ModuleReferenceContractLinkEvent.ModuleReferenceContractLinkAction.Removed) + .WithModuleReference(moduleReference) + .WithContractAddress(contractThird) + .Build(); + var moduleReferenceContractLinkEvents = new List{firstEvent, secondEvent, thirdEvent, fourthEvent, fifthEvent}; + var moduleReferenceEvent = ModuleReferenceEventBuilder.Create() + .WithModuleReferenceContractLinkEvent(moduleReferenceContractLinkEvents) + .WithModuleReference(moduleReference) + .Build(); + var moduleReferenceEventExtensions = new ModuleReferenceEvent.ModuleReferenceEventExtensions(); + + // Act + var linkedContracts = moduleReferenceEventExtensions.GetLinkedContracts(moduleReferenceEvent); + + // Assert + linkedContracts.Count.Should().Be(1); + linkedContracts[0].ContractAddress.Index.Should().Be(contractSecond.Index); + } +} diff --git a/backend/Tests/Api/GraphQL/__snapshots__/committed-schema.verified.graphql b/backend/Tests/Api/GraphQL/__snapshots__/committed-schema.verified.graphql index bbf05cb56..455efdcf2 100644 --- a/backend/Tests/Api/GraphQL/__snapshots__/committed-schema.verified.graphql +++ b/backend/Tests/Api/GraphQL/__snapshots__/committed-schema.verified.graphql @@ -1202,6 +1202,31 @@ type LeverageFactor { denominator: UnsignedLong! } +type LinkedContract { + contractAddress: ContractAddress! + linkedDateTime: DateTime! +} + +"A connection to a list of items." +type LinkedContractsConnection { + "Information to aid in pagination." + pageInfo: PageInfo! + "A list of edges." + edges: [LinkedContractsEdge!] + "A flattened list of the nodes." + nodes: [LinkedContract!] + "Identifies the total count of items in the connection." + totalCount: Int! +} + +"An edge in a connection." +type LinkedContractsEdge { + "A cursor for use in pagination." + cursor: String! + "The item at the end of the edge." + node: LinkedContract! +} + type MicroCcdPerEuroChainUpdatePayload { exchangeRate: ExchangeRate! } @@ -1266,6 +1291,92 @@ type ModuleReferenceContractLinkEvent { source: ImportSource! blockSlotTime: DateTime! createdAt: DateTime! + contractAddress: ContractAddress! +} + +"A connection to a list of items." +type ModuleReferenceContractLinkEventsConnection { + "Information to aid in pagination." + pageInfo: PageInfo! + "A list of edges." + edges: [ModuleReferenceContractLinkEventsEdge!] + "A flattened list of the nodes." + nodes: [ModuleReferenceContractLinkEvent!] + "Identifies the total count of items in the connection." + totalCount: Int! +} + +"An edge in a connection." +type ModuleReferenceContractLinkEventsEdge { + "A cursor for use in pagination." + cursor: String! + "The item at the end of the edge." + node: ModuleReferenceContractLinkEvent! +} + +type ModuleReferenceEvent { + eventIndex: UnsignedInt! + moduleReference: String! + sender: AccountAddress! + moduleReferenceContractLinkEvents("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): ModuleReferenceContractLinkEventsConnection + moduleReferenceRejectEvents("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): ModuleReferenceRejectEventsConnection + blockHeight: UnsignedLong! + transactionHash: String! + transactionIndex: UnsignedLong! + source: ImportSource! + blockSlotTime: DateTime! + createdAt: DateTime! + linkedContracts("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): LinkedContractsConnection +} + +type ModuleReferenceRejectEvent { + moduleReference: String! + sender: AccountAddress! + rejectedEvent: TransactionRejectReason! + blockHeight: UnsignedLong! + transactionHash: String! + transactionIndex: UnsignedLong! + source: ImportSource! + blockSlotTime: DateTime! + createdAt: DateTime! +} + +"A connection to a list of items." +type ModuleReferenceRejectEventsConnection { + "Information to aid in pagination." + pageInfo: PageInfo! + "A list of edges." + edges: [ModuleReferenceRejectEventsEdge!] + "A flattened list of the nodes." + nodes: [ModuleReferenceRejectEvent!] + "Identifies the total count of items in the connection." + totalCount: Int! +} + +"An edge in a connection." +type ModuleReferenceRejectEventsEdge { + "A cursor for use in pagination." + cursor: String! + "The item at the end of the edge." + node: ModuleReferenceRejectEvent! +} + +"A connection to a list of items." +type ModulesConnection { + "Information to aid in pagination." + pageInfo: PageInfo! + "A list of edges." + edges: [ModulesEdge!] + "A flattened list of the nodes." + nodes: [ModuleReferenceEvent!] +} + +"An edge in a connection." +type ModulesEdge { + "A cursor for use in pagination." + cursor: String! + "The item at the end of the edge." + node: ModuleReferenceEvent! } type NewEncryptedAmount { @@ -1631,6 +1742,7 @@ type Query { nodeStatus(id: ID!): NodeStatus contract(contractAddressIndex: UnsignedLong! contractAddressSubIndex: UnsignedLong!): Contract contracts("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): ContractsConnection + moduleReferenceEvent(moduleReference: String!): ModuleReferenceEvent } type Ranking { @@ -1711,6 +1823,7 @@ type ScheduledSelfTransfer { type SearchResult { contracts("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): ContractsConnection + modules("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): ModulesConnection blocks("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): BlocksConnection transactions("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): TransactionsConnection accounts("Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String): AccountsConnection diff --git a/backend/Tests/TestUtilities/Builders/ModuleReferenceContractLinkEventBuilder.cs b/backend/Tests/TestUtilities/Builders/ModuleReferenceContractLinkEventBuilder.cs index 847b70d60..b61f3f848 100644 --- a/backend/Tests/TestUtilities/Builders/ModuleReferenceContractLinkEventBuilder.cs +++ b/backend/Tests/TestUtilities/Builders/ModuleReferenceContractLinkEventBuilder.cs @@ -5,7 +5,7 @@ namespace Tests.TestUtilities.Builders; -internal class ModuleReferenceContractLinkEventBuilder +internal sealed class ModuleReferenceContractLinkEventBuilder { private ulong _blockHeight = 1; private readonly string _transactionHash = ""; @@ -26,9 +26,8 @@ internal static ModuleReferenceContractLinkEventBuilder Create() return new ModuleReferenceContractLinkEventBuilder(); } - internal ModuleReferenceContractLinkEvent Build() - { - return new ModuleReferenceContractLinkEvent( + internal ModuleReferenceContractLinkEvent Build() => + new( _blockHeight, _transactionHash, _transactionIndex, @@ -40,31 +39,26 @@ internal ModuleReferenceContractLinkEvent Build() _action, _dateTimeOffset ); - } - - internal ModuleReferenceContractLinkEventBuilder WithModuleReference( - string moduleReference) + + internal ModuleReferenceContractLinkEventBuilder WithModuleReference(string moduleReference) { _moduleReference = moduleReference; return this; } - internal ModuleReferenceContractLinkEventBuilder WithBlockHeight( - ulong blockHeight) + internal ModuleReferenceContractLinkEventBuilder WithBlockHeight(ulong blockHeight) { _blockHeight = blockHeight; return this; } - internal ModuleReferenceContractLinkEventBuilder WithTransactionIndex( - ulong transactionIndex) + internal ModuleReferenceContractLinkEventBuilder WithTransactionIndex(ulong transactionIndex) { _transactionIndex = transactionIndex; return this; } - internal ModuleReferenceContractLinkEventBuilder WithEventIndex( - uint eventIndex) + internal ModuleReferenceContractLinkEventBuilder WithEventIndex(uint eventIndex) { _eventIndex = eventIndex; return this; @@ -76,4 +70,10 @@ internal ModuleReferenceContractLinkEventBuilder WithLinkAction( _action = action; return this; } -} \ No newline at end of file + + public ModuleReferenceContractLinkEventBuilder WithContractAddress(ContractAddress contractAddress) + { + _contractAddress = contractAddress; + return this; + } +} diff --git a/backend/Tests/TestUtilities/Builders/ModuleReferenceEventBuilder.cs b/backend/Tests/TestUtilities/Builders/ModuleReferenceEventBuilder.cs new file mode 100644 index 000000000..2565aa689 --- /dev/null +++ b/backend/Tests/TestUtilities/Builders/ModuleReferenceEventBuilder.cs @@ -0,0 +1,57 @@ +using System.Collections.Generic; +using Application.Aggregates.Contract.Entities; +using Application.Aggregates.Contract.Types; +using Application.Api.GraphQL; +using Application.Api.GraphQL.Accounts; + +namespace Tests.TestUtilities.Builders; + +internal sealed class ModuleReferenceEventBuilder +{ + private const ulong BlockHeight = 1; + private const string TransactionHash = ""; + private const ulong TransactionIndex = 1; + private const uint EventIndex = 1; + private string _moduleReference = ""; + private readonly AccountAddress _accountAddress = new(""); + private const ImportSource Source = ImportSource.DatabaseImport; + private readonly DateTimeOffset _dateTimeOffset = DateTimeOffset.UtcNow; + private IList _moduleReferenceContractLinkEvents = new List(); + + private ModuleReferenceEventBuilder() {} + + internal static ModuleReferenceEventBuilder Create() + { + return new ModuleReferenceEventBuilder(); + } + + internal ModuleReferenceEvent Build() + { + return new ModuleReferenceEvent( + BlockHeight, + TransactionHash, + TransactionIndex, + EventIndex, + _moduleReference, + _accountAddress, + Source, + _dateTimeOffset + ) + { + ModuleReferenceContractLinkEvents = _moduleReferenceContractLinkEvents + }; + } + + internal ModuleReferenceEventBuilder WithModuleReference(string moduleReference) + { + _moduleReference = moduleReference; + return this; + } + + internal ModuleReferenceEventBuilder WithModuleReferenceContractLinkEvent( + IList moduleReferenceContractLinkEvents) + { + _moduleReferenceContractLinkEvents = moduleReferenceContractLinkEvents; + return this; + } +} diff --git a/frontend/src/components/Contracts/ContractDetailsContent.vue b/frontend/src/components/Contracts/ContractDetailsContent.vue index 94115bc0c..2f481e4a8 100644 --- a/frontend/src/components/Contracts/ContractDetailsContent.vue +++ b/frontend/src/components/Contracts/ContractDetailsContent.vue @@ -16,7 +16,7 @@ @@ -65,6 +65,7 @@ diff --git a/frontend/src/components/Module/ModuleDetailsContent.vue b/frontend/src/components/Module/ModuleDetailsContent.vue new file mode 100644 index 000000000..59bd59444 --- /dev/null +++ b/frontend/src/components/Module/ModuleDetailsContent.vue @@ -0,0 +1,108 @@ + + + diff --git a/frontend/src/components/Module/ModuleDetailsContractLinkEvents.vue b/frontend/src/components/Module/ModuleDetailsContractLinkEvents.vue new file mode 100644 index 000000000..4ed6208d4 --- /dev/null +++ b/frontend/src/components/Module/ModuleDetailsContractLinkEvents.vue @@ -0,0 +1,61 @@ + + + diff --git a/frontend/src/components/Module/ModuleDetailsHeader.vue b/frontend/src/components/Module/ModuleDetailsHeader.vue new file mode 100644 index 000000000..af9ff94fd --- /dev/null +++ b/frontend/src/components/Module/ModuleDetailsHeader.vue @@ -0,0 +1,39 @@ + + + + + diff --git a/frontend/src/components/Module/ModuleDetailsLinkedContracts.vue b/frontend/src/components/Module/ModuleDetailsLinkedContracts.vue new file mode 100644 index 000000000..8346b0155 --- /dev/null +++ b/frontend/src/components/Module/ModuleDetailsLinkedContracts.vue @@ -0,0 +1,56 @@ + + + diff --git a/frontend/src/components/Module/ModuleDetailsRejectEvents.vue b/frontend/src/components/Module/ModuleDetailsRejectEvents.vue new file mode 100644 index 000000000..d5dcdab17 --- /dev/null +++ b/frontend/src/components/Module/ModuleDetailsRejectEvents.vue @@ -0,0 +1,82 @@ + + + diff --git a/frontend/src/components/RejectionReason/Reasons/InvalidInitMethod.vue b/frontend/src/components/RejectionReason/Reasons/InvalidInitMethod.vue index 9fb9b4478..00b6e3b35 100644 --- a/frontend/src/components/RejectionReason/Reasons/InvalidInitMethod.vue +++ b/frontend/src/components/RejectionReason/Reasons/InvalidInitMethod.vue @@ -1,12 +1,12 @@ diff --git a/frontend/src/components/TransactionEventList/Events/ContractUpgraded.vue b/frontend/src/components/TransactionEventList/Events/ContractUpgraded.vue index 5d9db7aac..867c7c961 100644 --- a/frontend/src/components/TransactionEventList/Events/ContractUpgraded.vue +++ b/frontend/src/components/TransactionEventList/Events/ContractUpgraded.vue @@ -1,14 +1,15 @@ diff --git a/frontend/src/composables/useDrawer.ts b/frontend/src/composables/useDrawer.ts index d5965fc65..ef4e94483 100644 --- a/frontend/src/composables/useDrawer.ts +++ b/frontend/src/composables/useDrawer.ts @@ -26,6 +26,11 @@ type ContractDrawerItem = { contractAddressSubIndex: number } +type ModuleDrawerItem = { + entityTypeName: 'module' + moduleReference: string +} + type BakerDrawerItem = { entityTypeName: 'baker' bakerId: number @@ -42,6 +47,7 @@ export type DrawerItem = ( | TxDrawerItem | AccountDrawerItem | ContractDrawerItem + | ModuleDrawerItem | BakerDrawerItem | PassiveDelegationItem | NodeDrawerItem @@ -97,7 +103,14 @@ export const isItemOnTop = ( item.contractAddressSubIndex === currentTopItem.value.contractAddressSubIndex ) - + if ( + item.entityTypeName === 'module' && + item.entityTypeName === currentTopItem.value.entityTypeName + ) + return !!( + item.moduleReference && + item.moduleReference === currentTopItem.value.moduleReference + ) if ( item.entityTypeName === 'baker' && item.entityTypeName === currentTopItem.value.entityTypeName @@ -157,6 +170,10 @@ export const pushToRouter = drawerItem.entityTypeName === 'contract' ? drawerItem.contractAddressSubIndex : undefined, + dmoduleReference: + drawerItem.entityTypeName === 'module' + ? drawerItem.moduleReference + : undefined, }, }) } @@ -195,6 +212,17 @@ export const useDrawer = () => { }, false ) + } else if ( + route.query.dentity === 'module' && + route.query.dmoduleReference + ) { + push( + { + entityTypeName: 'module', + moduleReference: route.query.dmoduleReference as string, + }, + false + ) } else if ( route.query.density === 'contract' && route.query.dcontractAddressIndex && diff --git a/frontend/src/pages/contracts/index.vue b/frontend/src/pages/contracts/index.vue index 342362e9c..6644df2dc 100644 --- a/frontend/src/pages/contracts/index.vue +++ b/frontend/src/pages/contracts/index.vue @@ -40,7 +40,7 @@ - + @@ -59,7 +59,6 @@