Add isConfigured to application registration in App admin panel (#20326)

## After
Added "Configured" column in admin panel apps tab
<img width="1171" height="611" alt="image"
src="https://github.com/user-attachments/assets/e6850b39-5789-4ad2-b3df-192a28cb03e2"
/>

Add a banner to ask to configure the application 
<img width="1218" height="483" alt="image"
src="https://github.com/user-attachments/assets/1491363c-3479-41ca-97b7-c7dc9e07ff16"
/>
This commit is contained in:
martmull
2026-05-07 09:59:01 +02:00
committed by GitHub
parent eddd2c979a
commit 948ed964bb
16 changed files with 190 additions and 37 deletions
@@ -4,6 +4,7 @@ import {
type FieldMetadataLoaderPayload,
type IndexFieldMetadataLoaderPayload,
type IndexMetadataLoaderPayload,
type IsConfiguredLoaderPayload,
type MorphRelationLoaderPayload,
type ObjectMetadataLoaderPayload,
type RelationLoaderPayload,
@@ -89,4 +90,6 @@ export interface IDataloaders {
ViewFilterGroupsByViewIdLoaderPayload,
ViewFilterGroupDTO[]
>;
isConfiguredLoader: DataLoader<IsConfiguredLoaderPayload, boolean>;
}
@@ -1,11 +1,16 @@
import { Module } from '@nestjs/common';
import { ApplicationRegistrationVariableModule } from 'src/engine/core-modules/application/application-registration-variable/application-registration-variable.module';
import { DataloaderService } from 'src/engine/dataloaders/dataloader.service';
import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module';
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
@Module({
imports: [FieldMetadataModule, WorkspaceManyOrAllFlatEntityMapsCacheModule],
imports: [
FieldMetadataModule,
WorkspaceManyOrAllFlatEntityMapsCacheModule,
ApplicationRegistrationVariableModule,
],
providers: [DataloaderService],
exports: [DataloaderService],
})
@@ -7,6 +7,7 @@ import { isDefined } from 'twenty-shared/utils';
import { type IndexMetadataInterface } from 'src/engine/metadata-modules/index-metadata/interfaces/index-metadata.interface';
import { ApplicationRegistrationVariableService } from 'src/engine/core-modules/application/application-registration-variable/application-registration-variable.service';
import { I18nService } from 'src/engine/core-modules/i18n/i18n.service';
import { type IDataloaders } from 'src/engine/dataloaders/dataloader.interface';
import { filterMorphRelationDuplicateFields } from 'src/engine/dataloaders/utils/filter-morph-relation-duplicate-fields.util';
@@ -111,11 +112,16 @@ export type ViewFilterGroupsByViewIdLoaderPayload = {
viewId: string;
};
export type IsConfiguredLoaderPayload = {
applicationRegistrationId: string;
};
@Injectable()
export class DataloaderService {
constructor(
private readonly i18nService: I18nService,
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
private readonly applicationRegistrationVariableService: ApplicationRegistrationVariableService,
) {}
createLoaders(): IDataloaders {
@@ -135,6 +141,7 @@ export class DataloaderService {
const viewGroupsByViewIdLoader = this.createViewGroupsByViewIdLoader();
const viewFilterGroupsByViewIdLoader =
this.createViewFilterGroupsByViewIdLoader();
const isConfiguredLoader = this.createIsConfiguredLoader();
return {
relationLoader,
@@ -150,6 +157,7 @@ export class DataloaderService {
viewSortsByViewIdLoader,
viewGroupsByViewIdLoader,
viewFilterGroupsByViewIdLoader,
isConfiguredLoader,
};
}
@@ -733,4 +741,21 @@ export class DataloaderService {
});
});
}
private createIsConfiguredLoader() {
return new DataLoader<IsConfiguredLoaderPayload, boolean>(
async (params: IsConfiguredLoaderPayload[]) => {
const ids = params.map((p) => p.applicationRegistrationId);
const resultMap =
await this.applicationRegistrationVariableService.isConfiguredBatch(
ids,
);
return params.map(
(p) => resultMap.get(p.applicationRegistrationId) ?? true,
);
},
);
}
}