Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENG-5454] Addons/multiple configured addons part 3 #2218

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading