Display featured applications in marketplace (#22635)

## After
<img width="1060" height="589" alt="image"
src="https://github.com/user-attachments/assets/74dfadcf-8698-4404-81c6-b309cc4cbf79"
/>
<img width="732" alt="image"
src="https://github.com/user-attachments/assets/0e1a3644-04bc-4208-aa77-3842d9db9cc8"
/>
<img width="797" alt="image"
src="https://github.com/user-attachments/assets/0456ecce-607a-4705-8a89-c77029bfb6ac"
/>

- Remove IS_MARKETPLACE_SETTING_TAB_VISIBLE feature flag
- add vetted toggle in admin app tab
- added people data labs, last contact and call recorder to default
vetted applications

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22635?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->

---------

Co-authored-by: prastoin <paul@twenty.com>
This commit is contained in:
martmull
2026-07-07 17:05:54 +02:00
committed by GitHub
parent 2c0e0b2eac
commit 435073e9c5
24 changed files with 161 additions and 177 deletions
@@ -1,4 +0,0 @@
export const MARKETPLACE_CURATED_APPLICATIONS: {
universalIdentifier: string;
position?: number;
}[] = [];
@@ -0,0 +1,17 @@
export const MARKETPLACE_FEATURED_APPLICATIONS: {
universalIdentifier: string;
position?: number;
}[] = [
{
universalIdentifier: '8da4b8b5-5edf-4880-b51f-ab6e679ec617',
position: 1,
},
{
universalIdentifier: '4a1178c1-3535-4a47-b592-231d3216b36f',
position: 2,
},
{
universalIdentifier: '66a504cc-0a75-410e-a43f-cdeae1db1522',
position: 3,
},
];
@@ -32,7 +32,7 @@ import { ApplicationEntity } from 'src/engine/core-modules/application/applicati
import { validateRedirectUri } from 'src/engine/core-modules/auth/utils/validate-redirect-uri.util';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { ApplicationRegistrationVariableService } from 'src/engine/core-modules/application/application-registration-variable/application-registration-variable.service';
import { MARKETPLACE_CURATED_APPLICATIONS } from 'src/engine/core-modules/application/application-marketplace/constants/marketplace-curated-applications.constant';
import { MARKETPLACE_FEATURED_APPLICATIONS } from 'src/engine/core-modules/application/application-marketplace/constants/marketplace-featured-applications.constant';
const BCRYPT_SALT_ROUNDS = 10;
@@ -281,6 +281,7 @@ export class ApplicationRegistrationService {
if (isDefined(update.isListed)) updateData.isListed = update.isListed;
if (isDefined(update.isPreInstalled))
updateData.isPreInstalled = update.isPreInstalled;
if (isDefined(update.isFeatured)) updateData.isFeatured = update.isFeatured;
if (Object.keys(updateData).length > 0) {
await this.applicationRegistrationRepository.update(id, updateData);
@@ -383,13 +384,13 @@ export class ApplicationRegistrationService {
params.universalIdentifier,
);
const curatedIdentifiers = new Set(
MARKETPLACE_CURATED_APPLICATIONS.map(
const featuredIdentifiers = new Set(
MARKETPLACE_FEATURED_APPLICATIONS.map(
(entry) => entry.universalIdentifier,
),
);
const isFeatured = curatedIdentifiers.has(params.universalIdentifier);
const isFeatured = featuredIdentifiers.has(params.universalIdentifier);
if (isDefined(existing)) {
await this.applicationRegistrationRepository.save({
@@ -400,7 +401,6 @@ export class ApplicationRegistrationService {
latestAvailableVersion: params.latestAvailableVersion,
manifest: params.manifest,
...fromManifestApplicationToDisplayFields(params.manifest?.application),
isFeatured,
});
} else {
const registration = this.applicationRegistrationRepository.create({
@@ -46,6 +46,11 @@ export class UpdateApplicationRegistrationPayload {
@IsBoolean()
@IsOptional()
isPreInstalled?: boolean;
@Field(() => Boolean, { nullable: true })
@IsBoolean()
@IsOptional()
isFeatured?: boolean;
}
@InputType()