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-6744] FE: Contributors can "configure" others' addons #2438

Open
wants to merge 6 commits into
base: feature/addon-services
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 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
6 changes: 4 additions & 2 deletions app/models/configured-addon.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Model, { AsyncBelongsTo, attr, belongsTo } from '@ember-data/model';

import UserReferenceModel from 'ember-osf-web/models/user-reference';
import { ConnectedStorageOperationNames, OperationKwargs } from './addon-operation-invocation';
import UserReferenceModel from './user-reference';
import AuthorizedAccountModel, { ConnectedCapabilities } from './authorized-account';

export interface ConfiguredAddonEditableAttrs {
Expand All @@ -21,10 +21,12 @@ export default class ConfiguredAddonModel extends Model {
@attr('array') connectedOperationNames!: ConnectedStorageOperationNames[];
@attr('fixstring') rootFolder!: string;


@belongsTo('user-reference', { inverse: null })
accountOwner!: AsyncBelongsTo<UserReferenceModel> & UserReferenceModel;

@attr('boolean')
currentUserIsOwner!: boolean;

async getFolderItems(this: AuthorizedAccountModel, _kwargs?: OperationKwargs) : Promise<any> {
// To be implemented in child classes
return;
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 @@ -95,17 +95,38 @@ export default class Provider {
return Boolean(this.configuredAddons?.length);
}

get isOwned() {
if (this.node?.userHasAdminPermission) {
return true;
}
if (!this.configuredAddons || this.configuredAddons.length === 0) {
return true;
}
if (!this.userReference) {
return false;
}
return this.configuredAddons?.any(
addon => addon.currentUserIsOwner,
);
}

constructor(
provider: any,
currentUser: CurrentUserService,
node?: NodeModel,
allConfiguredAddons?: EmberArray<AllConfiguredAddonTypes>,
resourceReference?: ResourceReferenceModel,
userReference?: UserReferenceModel,
) {
setOwner(this, getOwner(provider));
this.node = node;
this.currentUser = currentUser;
this.provider = provider;
this.configuredAddons = allConfiguredAddons?.filter(addon => addon.externalServiceId === this.provider.id);
this.serviceNode = resourceReference;
if (userReference) {
this.userReference = userReference;
}

if (provider instanceof ExternalStorageServiceModel) {
this.providerMap = this.providerTypeMapper.externalStorageService;
Expand Down Expand Up @@ -144,6 +165,9 @@ export default class Provider {
@task
@waitFor
async getUserReference() {
if (this.userReference){
return;
}
const { user } = this.currentUser;
const userReferences = await this.store.query('user-reference', {
filter: {user_uri: user?.links.iri?.toString()},
Expand All @@ -155,7 +179,7 @@ export default class Provider {
@task
@waitFor
async getResourceReference() {
if (this.node) {
if (this.node && !this.serviceNode) {
const resourceRefs = await this.store.query('resource-reference', {
filter: {resource_uri: this.node.links.iri?.toString()},
});
Expand Down
4 changes: 4 additions & 0 deletions lib/osf-components/addon/components/addon-card/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ export default class AddonsCardComponent extends Component<Args> {
get addonIsConfigured() {
return this.args.addon.isConfigured;
}

get addonIsOwned() {
return this.args.addon.isOwned;
}
}
41 changes: 21 additions & 20 deletions lib/osf-components/addon/components/addon-card/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,26 @@
>
{{@addon.provider.displayName}}
</div>

<div local-class='buttons-wrapper'>
{{#if this.addonIsConfigured}}
<Button
data-test-addon-card-configure
data-analytics-name='Configure'
{{on 'click' (fn @manager.listProviderConfigurations @addon)}}
>
{{t 'osf-components.addon-card.configure'}}
</Button>
{{else}}
<Button
data-test-addon-card-connect
data-analytics-name='Connect'
{{on 'click' (fn @manager.beginAccountSetup @addon)}}
>
{{t 'osf-components.addon-card.connect'}}
</Button>
{{/if}}
</div>
{{#if this.addonIsOwned}}
<div local-class='buttons-wrapper'>
{{#if this.addonIsConfigured}}
<Button
data-test-addon-card-configure
data-analytics-name='Configure'
{{on 'click' (fn @manager.listProviderConfigurations @addon)}}
>
{{t 'osf-components.addon-card.configure'}}
</Button>
{{else}}
<Button
data-test-addon-card-connect
data-analytics-name='Connect'
{{on 'click' (fn @manager.beginAccountSetup @addon)}}
>
{{t 'osf-components.addon-card.connect'}}
</Button>
{{/if}}
</div>
{{/if}}
</div>

Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import ConfiguredStorageAddonModel from 'ember-osf-web/models/configured-storage
import { AccountCreationArgs} from 'ember-osf-web/models/authorized-account';
import AuthorizedStorageAccountModel from 'ember-osf-web/models/authorized-storage-account';
import ConfiguredCitationAddonModel from 'ember-osf-web/models/configured-citation-addon';
import UserReferenceModel from 'ember-osf-web/models/user-reference';

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

node = this.args.node;
@tracked addonServiceNode?: ResourceReferenceModel;
@tracked userReference?: UserReferenceModel;

possibleFilterTypes = Object.values(FilterTypes);
mapper: Record<FilterTypes, FilterSpecificObject> = {
Expand Down Expand Up @@ -285,7 +287,10 @@ export default class AddonsServiceManagerComponent extends Component<Args> {
@task
@waitFor
async initialize() {
await taskFor(this.getServiceNode).perform();
await Promise.all([
taskFor(this.getUserReference).perform(),
taskFor(this.getServiceNode).perform(),
]);
await taskFor(this.getStorageAddonProviders).perform();
}

Expand Down Expand Up @@ -385,7 +390,18 @@ export default class AddonsServiceManagerComponent extends Component<Args> {
}
return heading;
}

@task
@waitFor
async getUserReference() {
if (this.userReference){
return;
}
const { user } = this.currentUser;
const userReferences = await this.store.query('user-reference', {
filter: {user_uri: user?.links.iri?.toString()},
});
this.userReference = userReferences.firstObject;
}
// Service API Methods

@task
Expand All @@ -394,7 +410,9 @@ export default class AddonsServiceManagerComponent extends Component<Args> {
const serviceProviderModels = (await this.store.findAll(providerType)).toArray();
const serviceProviders = [] as Provider[];
for (const provider of serviceProviderModels) {
serviceProviders.addObject(new Provider(provider, this.currentUser, this.node, configuredAddons));
serviceProviders.addObject(new Provider(
provider, this.currentUser, this.node, configuredAddons, this.addonServiceNode, this.userReference,
));
}
return serviceProviders;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,14 @@ export default class UserAddonManagerComponent extends Component<Args> {
const serviceStorageProviders = await taskFor(this.getExternalProviders)
.perform(activeFilterObject.modelName) as ExternalStorageServiceModel[];
const list = serviceStorageProviders.sort(this.providerSorter)
.map(provider => new Provider(provider, this.currentUser));
.map(provider => new Provider(
provider,
this.currentUser,
undefined,
undefined,
undefined,
this.userReference,
));
activeFilterObject.list = list;
}

Expand All @@ -255,7 +262,14 @@ export default class UserAddonManagerComponent extends Component<Args> {
const cloudComputingProviders = await taskFor(this.getExternalProviders)
.perform(activeFilterObject.modelName) as ExternalComputingServiceModel[];
activeFilterObject.list = cloudComputingProviders.sort(this.providerSorter)
.map(provider => new Provider(provider, this.currentUser));
.map(provider => new Provider(
provider,
this.currentUser,
undefined,
undefined,
undefined,
this.userReference,
));
}

@task
Expand All @@ -265,7 +279,14 @@ export default class UserAddonManagerComponent extends Component<Args> {
const serviceCloudComputingProviders = await taskFor(this.getExternalProviders)
.perform(activeFilterObject.modelName) as ExternalCitationServiceModel[];
activeFilterObject.list = serviceCloudComputingProviders.sort(this.providerSorter)
.map(provider => new Provider(provider, this.currentUser));
.map(provider => new Provider(
provider,
this.currentUser,
undefined,
undefined,
undefined,
this.userReference,
));
}

@task
Expand Down
2 changes: 2 additions & 0 deletions tests/integration/components/addon-card/component-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ module('Integration | Component | addon-card', hooks => {
},
disableProjectAddon: sinon.stub(),
nodeAddon: { configured: false },
isOwned: true,
};
this.manager ={
node: { id: 'testnode' },
Expand Down Expand Up @@ -78,6 +79,7 @@ module('Integration | Component | addon-card', hooks => {
disableProjectAddon: { perform: sinon.stub() },
nodeAddon: { configured: true },
isConfigured: true,
isOwned: true,
};
this.addon = addonObj;
this.manager = {
Expand Down
Loading