Skip to content

Commit

Permalink
[ENG-5454] Addons/multiple configured addons part 3 (#2218)
Browse files Browse the repository at this point in the history
-   Ticket: [ENG-5454]
-   Feature flag: `gravy_waffle`

## Purpose

Allow multiple addons to be configurable. This updates the template and supporting ts files.

## Summary of Changes

1. Add configurationList page mode to the template
2. Update some text to match mockups
3. Style
4. Add function to remove a configured addon
  • Loading branch information
brianjgeiger authored May 14, 2024
1 parent 1cf9677 commit 537bfba
Show file tree
Hide file tree
Showing 8 changed files with 168 additions and 17 deletions.
34 changes: 34 additions & 0 deletions app/guid-node/addons/index/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,37 @@
color: var(--primary-color);
}
}

.configured-addons {
border: 1px solid $color-border-gray;
box-sizing: border-box;
padding: 10px;
}

.configured-addons-heading {
border-bottom: 1px solid $color-border-gray;
box-sizing: border-box;
}

.configured-addon-display-name {
margin-top: 10px;
font-size: large;
}

.configured-addon-connected-to {
border-bottom: 1px solid $color-border-gray;
box-sizing: border-box;
}

.remove-connected-button {
border: 0;
color: $brand-danger;
}

.edit-connected-button {
border: 0;
}

.add-location-button {
margin-top: 10px;
}
79 changes: 79 additions & 0 deletions app/guid-node/addons/index/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,85 @@
{{if manager.confirmAccountSetup.isRunning (t 'addons.confirm.authorizing') (t 'general.confirm')}}
</Button>
</div>
{{else if (eq manager.pageMode 'configurationList')}}
<div local-class='configured-addons'>
<div local-class='configured-addons-heading'>
<h4>{{t 'addons.list.connected-locations'}}</h4>
</div>
{{#each provider.configuredAddons as |configuredAddon|}}
<div local-class='configured-addon-display-name'>
{{configuredAddon.displayName}}
<span local-class='float-right'>
<Button
data-test-edit-connected-location={{configuredAddon.displayName}}
data-analytics-name='Edit connected location'
local-class='edit-connected-button'
{{on 'click' (fn manager.configureProvider manager.selectedProvider configuredAddon)}}
>
<FaIcon @icon='pencil-alt' />
</Button>
<Button
data-test-remove-connected-location={{configuredAddon.displayName}}
data-analytics-name='Remove connected location'
local-class='remove-connected-button'
{{on 'click' (queue
(action (mut manager.selectedConfiguration) configuredAddon)
(action (mut manager.confirmRemoveConnectedLocation) true)
)}}
>
<FaIcon @icon='times' />
</Button>
</span>
</div>
<div local-class='configured-addon-root-folder'>
{{#if configuredAddon.rootFolder}}
{{configuredAddon.rootFolder}}
{{else}}
{{t 'addons.list.root-folder-not-set'}}
{{/if}}
</div>
<div local-class='configured-addon-connected-to'>
{{t 'addons.list.connected-to-account'}} {{configuredAddon.baseAccount.displayName}}
</div>
{{/each}}
</div>
<div local-class='float-right'>
<Button
data-test-add-another-location-button
data-analytics-name='Add another location'
local-class='add-location-button'
{{on 'click' (action manager.beginAccountSetup this.currentProvider)}}
>
{{t 'addons.list.add-another-location'}}
</Button>
</div>
<OsfDialog
@isOpen={{manager.confirmRemoveConnectedLocation}}
@onClose={{action (mut manager.confirmRemoveConnectedLocation) false}}
as |dialog|
>
<dialog.main>
{{t 'addons.list.confirm-remove-connected-location'}}
</dialog.main>
<dialog.footer>
<div local-class='float-right'>
<Button
data-test-cancel-remove-connected-location-button
data-analytics-name='Cancel remove connected location'
{{on 'click' (action (mut manager.confirmRemoveConnectedLocation) false)}}
>
{{t 'general.cancel'}}
</Button>
<Button
data-test-confirm-remove-connected-location-button
data-analytics-name='Confirm remove connected location'
{{on 'click' (perform provider.removeConfiguredAddon manager.selectedConfiguration)}}
>
{{t 'general.confirm'}}
</Button>
</div>
</dialog.footer>
</OsfDialog>
{{else if (eq manager.pageMode 'configure')}}
<div local-class='float-right'>
<Button
Expand Down
26 changes: 25 additions & 1 deletion app/packages/addons-service/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import Store from '@ember-data/store';
import { tracked } from '@glimmer/tracking';
import { Task, task } from 'ember-concurrency';
import { taskFor } from 'ember-concurrency-ts';
import Intl from 'ember-intl/services/intl';
import Toast from 'ember-toastr/services/toast';

import NodeModel from 'ember-osf-web/models/node';
import CurrentUserService from 'ember-osf-web/services/current-user';
Expand All @@ -21,6 +23,8 @@ import AuthorizedComputingAccount from 'ember-osf-web/models/authorized-computin
import ExternalStorageServiceModel from 'ember-osf-web/models/external-storage-service';
import ExternalComputingServiceModel from 'ember-osf-web/models/external-computing-service';
import ExternalCitationServiceModel from 'ember-osf-web/models/external-citation-service';
import { notifyPropertyChange } from '@ember/object';
import captureException, { getApiErrorMessage } from 'ember-osf-web/utils/capture-exception';

export type AllProviderTypes =
ExternalStorageServiceModel |
Expand All @@ -43,6 +47,9 @@ interface ProviderTypeMapper {


export default class Provider {
@service toast!: Toast;
@service intl!: Intl;

@tracked node?: NodeModel;
@tracked serviceNode?: ResourceReferenceModel;

Expand Down Expand Up @@ -86,7 +93,7 @@ export default class Provider {
@service store!: Store;

get isConfigured() {
return Boolean(this.configuredAddon) || Boolean(this.configuredAddons?.length);
return Boolean(this.configuredAddons?.length);
}

constructor(
Expand Down Expand Up @@ -119,6 +126,23 @@ export default class Provider {
this.getProviderConfiguredAddons();
}

@task
@waitFor
async removeConfiguredAddon(selectedConfiguration: AllConfiguredAddonTypes) {
const errorMessage = this.intl.t('addons.provider.remove-configured-addon-error');
const successMessage = this.intl.t('addons.provider.remove-configured-addon-success');
try {
await selectedConfiguration?.destroyRecord();
this.configuredAddons?.removeObject(selectedConfiguration);
notifyPropertyChange(this, 'configuredAddons');
this.toast.success(successMessage);
} catch (e) {
captureException(e, { errorMessage });
this.toast.error(getApiErrorMessage(e), errorMessage);
return;
}
}

@task
@waitFor
async getUserReference() {
Expand Down
8 changes: 4 additions & 4 deletions lib/osf-components/addon/components/addon-card/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,25 @@
<Button
data-test-addon-card-edit
data-analytics-name='Edit'
{{on 'click' (fn @manager.configureProvider @addon)}}
{{on 'click' (fn @manager.listProviderConfigurations @addon)}}
>
{{t 'general.edit'}}
{{t 'osf-components.addon-card.configure'}}
</Button>
<Button
data-test-addon-card-disconnect
data-analytics-name='Disconnect'
local-class='disconnect'
{{on 'click' (action (mut this.deleteModalOpen) true)}}
>
{{t 'osf-components.addon-card.disconnect'}}
{{t 'osf-components.addon-card.disable'}}
</Button>
{{else}}
<Button
data-test-addon-card-connect
data-analytics-name='Connect'
{{on 'click' (fn @manager.beginAccountSetup @addon)}}
>
{{t 'osf-components.addon-card.connect'}}
{{t 'osf-components.addon-card.enable'}}
</Button>
{{/if}}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import ConfiguredStorageAddonModel from 'ember-osf-web/models/configured-storage
import { AddonCredentialFields} from 'ember-osf-web/models/authorized-account';
import AuthorizedStorageAccountModel from 'ember-osf-web/models/authorized-storage-account';
import captureException, { getApiErrorMessage } from 'ember-osf-web/utils/capture-exception';
import { TrackedObject } from 'tracked-built-ins';

interface FilterSpecificObject {
modelName: string;
Expand Down Expand Up @@ -58,7 +59,7 @@ export default class AddonsServiceManagerComponent extends Component<Args> {
@tracked addonServiceNode?: ResourceReferenceModel;

possibleFilterTypes = Object.values(FilterTypes);
filterTypeMapper: Record<FilterTypes, FilterSpecificObject> = {
mapper: Record<FilterTypes, FilterSpecificObject> = {
[FilterTypes.STORAGE]: {
modelName: 'external-storage-service',
task: taskFor(this.getStorageAddonProviders),
Expand All @@ -78,9 +79,11 @@ export default class AddonsServiceManagerComponent extends Component<Args> {
configuredAddons: A([]),
},
};
filterTypeMapper = new TrackedObject(this.mapper);
@tracked filterText = '';
@tracked activeFilterType: FilterTypes = FilterTypes.STORAGE;

@tracked confirmRemoveConnectedLocation = false;
@tracked pageMode?: PageMode;
@tracked selectedProvider?: Provider;
@tracked selectedConfiguration?: AllConfiguredAddonTypes;
Expand Down Expand Up @@ -250,8 +253,10 @@ export default class AddonsServiceManagerComponent extends Component<Args> {
cancelSetup() {
this.pageMode = undefined;
this.selectedProvider = undefined;
this.selectedConfiguration = undefined;
this.clearCredentials();
this.selectedAccount = undefined;
this.confirmRemoveConnectedLocation = false;
}

@action
Expand Down Expand Up @@ -320,8 +325,6 @@ export default class AddonsServiceManagerComponent extends Component<Args> {
await taskFor(this.getExternalProviders)
.perform(activeFilterObject.modelName, activeFilterObject.configuredAddons);
activeFilterObject.list = A(serviceStorageProviders.sort(this.providerSorter));


}

@task
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
authorizeSelectedAccount=this.authorizeSelectedAccount
chooseExistingAccount=this.chooseExistingAccount
createNewAccount=this.createNewAccount

listProviderConfigurations=this.listProviderConfigurations
createAuthorizedAccount=this.createAuthorizedAccount
createConfiguredAddon=this.createConfiguredAddon
oauthFlowRefocus=this.oauthFlowRefocus
Expand All @@ -32,4 +32,6 @@
save=this.save
pageMode=this.pageMode
headingText=this.headingText
removeConfiguredAddon=this.removeConfiguredAddon
selectedConfiguration=this.selectedConfiguration
)}}
10 changes: 5 additions & 5 deletions tests/integration/components/addon-card/component-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ module('Integration | Component | addon-card', hooks => {
node: { id: 'testnode' },
projectEnabledAddons: [],
beginAccountSetup: sinon.stub(),
configureProvider: sinon.stub(),
listProviderConfigurations: sinon.stub(),
};

await render(hbs`
Expand Down Expand Up @@ -84,7 +84,7 @@ module('Integration | Component | addon-card', hooks => {
node: { id: 'testnode' },
projectEnabledAddons: [],
beginAccountSetup: sinon.stub(),
configureProvider: sinon.stub(),
listProviderConfigurations: sinon.stub(),
};

await render(hbs`
Expand All @@ -105,11 +105,11 @@ module('Integration | Component | addon-card', hooks => {
assert.dom('[data-test-addon-card-connect]').doesNotExist();

await click('[data-test-addon-card-edit]');
assert.ok(this.manager.configureProvider.calledOnce);
assert.ok(this.manager.listProviderConfigurations.calledOnce);
await click('[data-test-addon-card-disconnect]');
assert.dom('[data-test-addon-disconnect-modal-confirm]').exists();
assert.dom('#osf-dialog-heading').hasText('Disconnect Add-on');
assert.dom('[data-test-dialog] main').containsText('Are you sure you want to disconnect this add-on?');
assert.dom('#osf-dialog-heading').hasText('Disable Add-on');
assert.dom('[data-test-dialog] main').containsText('Are you sure you want to disable this add-on?');
await click('[data-test-addon-disconnect-modal-confirm]');
assert.ok(addonObj.disableProjectAddon.perform.calledOnce);
});
Expand Down
15 changes: 12 additions & 3 deletions translations/en-us.yml
Original file line number Diff line number Diff line change
Expand Up @@ -222,11 +222,19 @@ dashboard:

addons:
heading: 'Add-ons'
provider:
remove-configured-addon-success: 'You have successfully removed this addon'
remove-configured-addon-error: 'There was a problem removing this addon'
list:
authorized-accounts-for-provider: 'Authorized accounts for {providerName}'
authorized-accounts: 'Authorized accounts'
connected-accounts: 'Connected Accounts'
connected-locations: 'Connected locations'
add-another-location: 'Add another location'
all-addons: 'All Add-ons'
confirm-remove-connected-location: 'Are you sure you want to disconnect this addon?'
connected-to-account: 'Connected to account'
root-folder-not-set: 'Root folder not set'
sync-details-1: 'Sync your projects with external services to help stay connected and organized. Select a category and browse the options.'
sync-details-2: 'To manage all add-ons connected to your account, visit your profile settings.'
filter-placeholder: 'Filter add-ons'
Expand Down Expand Up @@ -2143,12 +2151,13 @@ routes:
email: Email
osf-components:
addon-card:
enable: Enable
connect: Connect
disconnect: Disconnect
disable: Disable
configure: Configure
provider-logo-alt: '{provider} logo'
disconnect-modal-header: 'Disconnect Add-on'
disconnect-modal-body: 'Are you sure you want to disconnect this add-on?'
disconnect-modal-header: 'Disable Add-on'
disconnect-modal-body: 'Are you sure you want to disable this add-on?'
search-result-card:
show_additional_metadata: 'Show additional metadata'
hide_additional_metadata: 'Hide additional metadata'
Expand Down

0 comments on commit 537bfba

Please sign in to comment.