diff --git a/src/app/features/project/addons/addons.component.html b/src/app/features/project/addons/addons.component.html index 78a7e2085..6299843ea 100644 --- a/src/app/features/project/addons/addons.component.html +++ b/src/app/features/project/addons/addons.component.html @@ -58,10 +58,7 @@ /> @if (!isConfiguredAddonsLoading()) { - + } @else {
diff --git a/src/app/features/project/addons/addons.component.ts b/src/app/features/project/addons/addons.component.ts index 43656c346..f6498d2b9 100644 --- a/src/app/features/project/addons/addons.component.ts +++ b/src/app/features/project/addons/addons.component.ts @@ -25,6 +25,8 @@ import { LoadingSpinnerComponent, SearchInputComponent, SelectComponent, SubHead import { AddonCardListComponent } from '@shared/components/addons'; import { ADDON_CATEGORY_OPTIONS, ADDON_TAB_OPTIONS } from '@shared/constants'; import { AddonCategory, AddonTabValue } from '@shared/enums'; +import { isAddonServiceConfigured } from '@shared/helpers'; +import { AddonCardModel } from '@shared/models'; import { AddonsSelectors, ClearConfiguredAddons, @@ -151,6 +153,10 @@ export class AddonsComponent implements OnInit { return authorizedAddons.filter((card) => card.displayName.toLowerCase().includes(searchValue)); }); + allConfiguredAddonsForCheck = computed(() => { + return [...this.configuredStorageAddons(), ...this.configuredCitationAddons(), ...this.configuredLinkAddons()]; + }); + resourceReferenceId = computed(() => { return this.addonsResourceReference()[0]?.id; }); @@ -181,13 +187,28 @@ export class AddonsComponent implements OnInit { } }); - filteredAddonCards = computed(() => { + filteredAddonCards = computed((): AddonCardModel[] => { const searchValue = this.searchValue().toLowerCase(); - return this.currentAddonsState().filter( - (card) => - card.externalServiceName.toLowerCase().includes(searchValue) || - card.displayName.toLowerCase().includes(searchValue) - ); + const configuredAddons = this.allConfiguredAddonsForCheck(); + + return this.currentAddonsState() + .filter( + (card) => + card.externalServiceName.toLowerCase().includes(searchValue) || + card.displayName.toLowerCase().includes(searchValue) + ) + .map((addon) => { + const isConfigured = isAddonServiceConfigured(addon, configuredAddons); + const configuredAddon = configuredAddons.find( + (config) => config.externalServiceName === addon.externalServiceName + ); + + return { + addon, + isConfigured, + configuredAddon, + } as AddonCardModel; + }); }); onCategoryChange(value: Primitive): void { diff --git a/src/app/features/settings/addons/addons.component.html b/src/app/features/settings/addons/addons.component.html index 35f135ad3..6e347e7b4 100644 --- a/src/app/features/settings/addons/addons.component.html +++ b/src/app/features/settings/addons/addons.component.html @@ -62,11 +62,7 @@ /> @if (!isAuthorizedAddonsLoading()) { - + } @else {
diff --git a/src/app/shared/components/addons/addon-card-list/addon-card-list.component.html b/src/app/shared/components/addons/addon-card-list/addon-card-list.component.html index 3ee28fa2a..ff6826ec2 100644 --- a/src/app/shared/components/addons/addon-card-list/addon-card-list.component.html +++ b/src/app/shared/components/addons/addon-card-list/addon-card-list.component.html @@ -1,8 +1,8 @@
@if (cards().length) { - @for (card of cards(); track card.id) { + @for (card of cards(); track $index) {
- +
} } @else { diff --git a/src/app/shared/components/addons/addon-card-list/addon-card-list.component.spec.ts b/src/app/shared/components/addons/addon-card-list/addon-card-list.component.spec.ts index 1dcf01735..8b64c144d 100644 --- a/src/app/shared/components/addons/addon-card-list/addon-card-list.component.spec.ts +++ b/src/app/shared/components/addons/addon-card-list/addon-card-list.component.spec.ts @@ -27,10 +27,6 @@ describe('AddonCardListComponent', () => { expect(component.cards()).toEqual([]); }); - it('should have default empty string ', () => { - expect(component.cardButtonLabel()).toBe(''); - }); - it('should have default false value', () => { expect(component.showDangerButton()).toBe(false); }); diff --git a/src/app/shared/components/addons/addon-card-list/addon-card-list.component.ts b/src/app/shared/components/addons/addon-card-list/addon-card-list.component.ts index cc1d8d41c..757788b99 100644 --- a/src/app/shared/components/addons/addon-card-list/addon-card-list.component.ts +++ b/src/app/shared/components/addons/addon-card-list/addon-card-list.component.ts @@ -2,7 +2,7 @@ import { TranslatePipe } from '@ngx-translate/core'; import { Component, input } from '@angular/core'; -import { AddonModel, AuthorizedAccountModel, ConfiguredAddonModel } from '@shared/models'; +import { AddonCardModel, AddonModel, AuthorizedAccountModel, ConfiguredAddonModel } from '@shared/models'; import { AddonCardComponent } from '../addon-card/addon-card.component'; @@ -13,7 +13,6 @@ import { AddonCardComponent } from '../addon-card/addon-card.component'; styleUrl: './addon-card-list.component.scss', }) export class AddonCardListComponent { - cards = input<(AddonModel | AuthorizedAccountModel | ConfiguredAddonModel)[]>([]); - cardButtonLabel = input(''); + cards = input<(AddonModel | AuthorizedAccountModel | ConfiguredAddonModel | AddonCardModel)[]>([]); showDangerButton = input(false); } diff --git a/src/app/shared/components/addons/addon-card/addon-card.component.html b/src/app/shared/components/addons/addon-card/addon-card.component.html index 189987acb..37081839e 100644 --- a/src/app/shared/components/addons/addon-card/addon-card.component.html +++ b/src/app/shared/components/addons/addon-card/addon-card.component.html @@ -1,17 +1,17 @@
- @if (card()!.externalServiceName) { + @if (actualAddon()?.externalServiceName) { Addon card image }
-

{{ card()?.displayName }}

+

{{ actualAddon()?.displayName }}

@if (showDangerButton()) { @@ -24,7 +24,7 @@

{{ card()?.displayName }}

diff --git a/src/app/shared/components/addons/addon-card/addon-card.component.ts b/src/app/shared/components/addons/addon-card/addon-card.component.ts index 941f0d666..2f72405b7 100644 --- a/src/app/shared/components/addons/addon-card/addon-card.component.ts +++ b/src/app/shared/components/addons/addon-card/addon-card.component.ts @@ -9,7 +9,7 @@ import { Router } from '@angular/router'; import { getAddonTypeString, isConfiguredAddon } from '@osf/shared/helpers'; import { CustomConfirmationService, LoaderService } from '@osf/shared/services'; -import { AddonModel, AuthorizedAccountModel, ConfiguredAddonModel } from '@shared/models'; +import { AddonCardModel, AddonModel, AuthorizedAccountModel, ConfiguredAddonModel } from '@shared/models'; import { DeleteAuthorizedAddon } from '@shared/stores/addons'; @Component({ @@ -24,15 +24,38 @@ export class AddonCardComponent { private readonly loaderService = inject(LoaderService); private readonly actions = createDispatchMap({ deleteAuthorizedAddon: DeleteAuthorizedAddon }); - readonly card = input(null); - readonly cardButtonLabel = input(''); + readonly card = input(null); readonly showDangerButton = input(false); - readonly addonTypeString = computed(() => getAddonTypeString(this.card())); - readonly isConfiguredAddon = computed(() => isConfiguredAddon(this.card())); + readonly actualAddon = computed(() => { + const actualCard = this.card(); + if (!actualCard) return null; + + if ('isConfigured' in actualCard) { + return actualCard.addon; + } + + return actualCard; + }); + + readonly addonTypeString = computed(() => getAddonTypeString(this.actualAddon())); + readonly isConfiguredAddon = computed(() => { + const actualCard = this.card(); + if (!actualCard) return false; + + if ('isConfigured' in actualCard) { + return actualCard.isConfigured; + } + + return isConfiguredAddon(actualCard); + }); + + readonly buttonLabel = computed(() => { + return this.isConfiguredAddon() ? 'settings.addons.form.buttons.configure' : 'settings.addons.form.buttons.connect'; + }); onConnectAddon(): void { - const addon = this.card(); + const addon = this.actualAddon(); if (addon) { const currentUrl = this.router.url; const baseUrl = currentUrl.split('/addons')[0]; @@ -43,13 +66,24 @@ export class AddonCardComponent { } onConfigureAddon(): void { - const addon = this.card(); - if (addon) { + const actualCard = this.card(); + if (!actualCard) return; + + if ('isConfigured' in actualCard && actualCard.configuredAddon) { const currentUrl = this.router.url; const baseUrl = currentUrl.split('/addons')[0]; this.router.navigate([`${baseUrl}/addons/configure-addon`], { - state: { addon }, + state: { addon: actualCard.configuredAddon }, }); + } else { + const addon = this.actualAddon(); + if (addon) { + const currentUrl = this.router.url; + const baseUrl = currentUrl.split('/addons')[0]; + this.router.navigate([`${baseUrl}/addons/configure-addon`], { + state: { addon }, + }); + } } } @@ -63,7 +97,8 @@ export class AddonCardComponent { } onDisableAddon(): void { - const addonId = this.card()?.id; + const addon = this.actualAddon(); + const addonId = addon?.id; if (addonId) { this.loaderService.show(); diff --git a/src/app/shared/helpers/addon-type.helper.ts b/src/app/shared/helpers/addon-type.helper.ts index 38adf3f89..beea10396 100644 --- a/src/app/shared/helpers/addon-type.helper.ts +++ b/src/app/shared/helpers/addon-type.helper.ts @@ -62,3 +62,9 @@ export function isConfiguredAddon(addon: AddonModel | AuthorizedAccountModel | C addon.type === ConfiguredAddonType.LINK ); } + +export function isAddonServiceConfigured(addon: AddonModel | null, configuredAddons: ConfiguredAddonModel[]): boolean { + if (!addon) return false; + + return configuredAddons.some((configuredAddon) => configuredAddon.externalServiceName === addon.externalServiceName); +} diff --git a/src/app/shared/models/addons/addon-card.model.ts b/src/app/shared/models/addons/addon-card.model.ts new file mode 100644 index 000000000..0aead2820 --- /dev/null +++ b/src/app/shared/models/addons/addon-card.model.ts @@ -0,0 +1,8 @@ +import { AddonModel } from './addons.models'; +import { ConfiguredAddonModel } from './configured-addon.model'; + +export interface AddonCardModel { + addon: AddonModel; + isConfigured: boolean; + configuredAddon?: ConfiguredAddonModel; +} diff --git a/src/app/shared/models/addons/index.ts b/src/app/shared/models/addons/index.ts index e0ae0ab42..3c8facda2 100644 --- a/src/app/shared/models/addons/index.ts +++ b/src/app/shared/models/addons/index.ts @@ -1,3 +1,4 @@ +export * from './addon-card.model'; export * from './addon-form.model'; export * from './addon-terms.model'; export * from './addons.models'; diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 15371e8f3..15a421bd6 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -1635,6 +1635,7 @@ "acceptingTerms": "Accepting...", "back": "Back", "connect": "Connect", + "configure": "Configure", "reconnect": "Reconnect", "authorize": "Authorize", "disable": "Disable",