Skip to content

[ENG-7876] Feature/file picker select root #2556

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

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
6 changes: 6 additions & 0 deletions app/config/environment.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ declare const config: {
doiUrlPrefix: string;
dataciteTrackerRepoId: string;
dataCiteTrackerUrl: string;
googleFilePicker: {
GOOGLE_FILE_PICKER_SCOPES: string;
GOOGLE_FILE_PICKER_CLIENT_ID: string;
GOOGLE_FILE_PICKER_API_KEY: string;
GOOGLE_FILE_PICKER_APP_ID: number;
}
};
social: {
twitter: {
Expand Down
1 change: 1 addition & 0 deletions app/guid-node/files/provider/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
>
<div local-class='FileBrowser'>
<FileBrowser
@configuredStorageAddon={{this.model.configuredStorageAddon}}
@manager={{manager}}
@selectable={{not this.model.providerTask.value.currentUser.viewOnlyToken}}
@enableUpload={{true}}
Expand Down
3 changes: 1 addition & 2 deletions app/models/authorized-account.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Model, { attr } from '@ember-data/model';
import Model, { attr} from '@ember-data/model';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import Model, { attr} from '@ember-data/model';
import Model, { attr } from '@ember-data/model';

import { OperationKwargs } from 'ember-osf-web/models/addon-operation-invocation';

export enum ConnectedCapabilities {
Expand Down Expand Up @@ -36,7 +36,6 @@ export default class AuthorizedAccountModel extends Model {
return;
}


async getItemInfo(this: AuthorizedAccountModel, _itemId: string) : Promise<any> {
// To be implemented in child classes
return;
Expand Down
7 changes: 5 additions & 2 deletions app/models/authorized-storage-account.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { AsyncBelongsTo, belongsTo } from '@ember-data/model';
import { AsyncBelongsTo, attr, belongsTo } from '@ember-data/model';
import { waitFor } from '@ember/test-waiters';
import { task } from 'ember-concurrency';
import { ConnectedStorageOperationNames, OperationKwargs } from 'ember-osf-web/models/addon-operation-invocation';
import ExternalStorageServiceModel from 'ember-osf-web/models/external-storage-service';

import ExternalStorageServiceModel from './external-storage-service';
import AuthorizedAccountModel from './authorized-account';
import UserReferenceModel from './user-reference';

export default class AuthorizedStorageAccountModel extends AuthorizedAccountModel {
@attr('fixstring') serializeOauthToken!: string;
@attr('fixstring') oauthToken!: string;

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

Expand Down
13 changes: 13 additions & 0 deletions config/environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,13 @@ const {
SHARE_SEARCH_URL: shareSearchUrl = 'http://localhost:8003/api/v2/search/creativeworks/_search',
SOURCEMAPS_ENABLED: sourcemapsEnabled = true,
SHOW_DEV_BANNER = false,

GOOGLE_FILE_PICKER_SCOPES,
/* eslint-disable-next-line max-len */
GOOGLE_FILE_PICKER_CLIENT_ID,
GOOGLE_FILE_PICKER_API_KEY,
GOOGLE_FILE_PICKER_APP_ID,

} = { ...process.env, ...localConfig };

module.exports = function(environment) {
Expand Down Expand Up @@ -224,6 +231,12 @@ module.exports = function(environment) {
doiUrlPrefix: 'https://doi.org/',
dataciteTrackerRepoId,
dataCiteTrackerUrl,
googleFilePicker: {
GOOGLE_FILE_PICKER_SCOPES,
GOOGLE_FILE_PICKER_CLIENT_ID,
GOOGLE_FILE_PICKER_API_KEY,
GOOGLE_FILE_PICKER_APP_ID,
},
},
social: {
twitter: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { action } from '@ember/object';
import { waitFor } from '@ember/test-waiters';
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { TaskInstance } from 'ember-concurrency';
import { task, TaskInstance } from 'ember-concurrency';
import { taskFor } from 'ember-concurrency-ts';


import { Item, ItemType } from 'ember-osf-web/models/addon-operation-invocation';
import AuthorizedAccountModel from 'ember-osf-web/models/authorized-account';
Expand All @@ -12,6 +15,7 @@ import ConfiguredAddonModel from 'ember-osf-web/models/configured-addon';
import ConfiguredCitationAddonModel from 'ember-osf-web/models/configured-citation-addon';
import ConfiguredComputingAddonModel from 'ember-osf-web/models/configured-computing-addon';
import ConfiguredStorageAddonModel from 'ember-osf-web/models/configured-storage-addon';
import ExternalStorageServiceModel from 'ember-osf-web/models/external-storage-service';


interface Args {
Expand All @@ -25,6 +29,8 @@ export default class ConfiguredAddonEdit extends Component<Args> {
@tracked selectedFolder = this.args.configuredAddon?.rootFolder;
@tracked selectedFolderDisplayName = this.args.configuredAddon?.rootFolderName;
@tracked currentItems: Item[] = [];
@tracked isWBGoogleDrive = false;
@tracked accountId!: string;

originalName = this.displayName;
originalRootFolder = this.selectedFolder;
Expand All @@ -34,6 +40,7 @@ export default class ConfiguredAddonEdit extends Component<Args> {
super(owner, args);
if (this.args.configuredAddon) {
if (this.args.configuredAddon instanceof ConfiguredStorageAddonModel) {
taskFor(this.loadExternalStorageService).perform();
this.defaultKwargs['itemType'] = ItemType.Folder;
}
if (this.args.configuredAddon instanceof ConfiguredCitationAddonModel) {
Expand All @@ -42,6 +49,7 @@ export default class ConfiguredAddonEdit extends Component<Args> {
}
if (this.args.authorizedAccount) {
if (this.args.authorizedAccount instanceof AuthorizedStorageAccountModel) {
taskFor(this.loadExternalStorageService).perform();
this.defaultKwargs['itemType'] = ItemType.Folder;
}
if (this.args.authorizedAccount instanceof AuthorizedCitationAccountModel) {
Expand All @@ -50,6 +58,28 @@ export default class ConfiguredAddonEdit extends Component<Args> {
}
}

/**
* This is called only to authorize because the current implementation will throw an
* error because the "root folder" is not yet set.
*/
@task
@waitFor
async loadExternalStorageService() {
let external!: ExternalStorageServiceModel;
if (this.args.configuredAddon && this.args.configuredAddon instanceof ConfiguredStorageAddonModel) {
const baseAccount = await this.args.configuredAddon.baseAccount;
this.accountId = baseAccount?.id;
external = await this.args.configuredAddon.externalStorageService;
}
if (this.args.authorizedAccount && this.args.authorizedAccount instanceof AuthorizedStorageAccountModel) {
external = await this.args.authorizedAccount.externalStorageService;

this.accountId = this.args.authorizedAccount.id;
}

this.isWBGoogleDrive = external?.wbKey === 'googledrive';
}

get requiresRootFolder() {
return !(
this.args.authorizedAccount instanceof AuthorizedComputingAccountModel
Expand All @@ -58,6 +88,14 @@ export default class ConfiguredAddonEdit extends Component<Args> {
);
}

get isGoogleDrive(): boolean {
return this.isWBGoogleDrive;
}

get displayFileManager(): boolean {
return this.requiresRootFolder && !this.isGoogleDrive;
}

get invalidDisplayName() {
return !this.displayName || this.displayName?.trim().length === 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,8 @@
.item-name {
white-space: normal;
}

.picker-style {
white-space: pre-wrap;

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
</span>
{{/if}}
</div>
{{#if this.requiresRootFolder }}
{{#if this.displayFileManager}}
<div local-class='input-wrapper'>
<b>
{{t 'addons.configure.selected-folder'}}
Expand Down Expand Up @@ -150,6 +150,13 @@
</tbody>
</table>
</AddonsService::FileManager>
{{else}}
<GoogleFilePickerWidget
@selectedFolderName={{this.selectedFolderDisplayName}}
@selectFolder={{action this.selectFolder}}
@isFolderPicker={{true}}
@accountId={{this.accountId}}
></GoogleFilePickerWidget>
{{/if}}
<div local-class='footer-buttons-wrapper'>
<Button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,8 @@ export default class AddonsServiceManagerComponent extends Component<Args> {
@waitFor
async createAuthorizedAccount(arg: AccountCreationArgs) {
if (this.selectedProvider) {
const newAccount = await taskFor(this.selectedProvider.createAuthorizedAccount)
return await taskFor(this.selectedProvider.createAuthorizedAccount)
.perform(arg);
return newAccount;
}
return undefined;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,61 @@
// import { inject as service } from '@ember/service';
import { action } from '@ember/object';
import { waitFor } from '@ember/test-waiters';
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';

import { task } from 'ember-concurrency';
import { taskFor } from 'ember-concurrency-ts';
import ConfiguredStorageAddonModel from 'ember-osf-web/models/configured-storage-addon';
import GoogleFilePickerWidget from 'osf-components/components/google-file-picker-widget/component';
import StorageManager from 'osf-components/components/storage-provider-manager/storage-manager/component';

interface Args {
manager: StorageManager;
configuredStorageAddon: ConfiguredStorageAddonModel;
}

export default class FileBrowser extends Component<Args> {
@tracked createFolderModalOpen = false;
@tracked googlePickerComponent: GoogleFilePickerWidget | null = null;
@tracked dropzoneClickableElementId = '';
@tracked isWBGoogleDrive = false;
@tracked googleFilePickerRootFolder!: string;
@tracked accountId!: string;

constructor(owner: unknown, args: Args) {
super(owner, args);

taskFor(this.loadExternalStorageService).perform();
}

/**
* This is called only to authorize because the current implementation will throw an
* error because the "root folder" is not yet set.
*/
@task
@waitFor
async loadExternalStorageService() {
this.googleFilePickerRootFolder = this.args.configuredStorageAddon?.rootFolder;
const baseAccount = await this.args.configuredStorageAddon?.baseAccount;
this.accountId = baseAccount?.id;
const external = await this.args.configuredStorageAddon?.externalStorageService;
this.isWBGoogleDrive = external?.wbKey === 'googledrive';
}

get isGoogleDrive(): boolean {
return this.isWBGoogleDrive;
}

@action
registerChild(child: GoogleFilePickerWidget) {
this.googlePickerComponent = child; // Store the child's instance
}

@action
openGoogleFilePicker(dropdown: any) {
dropdown.close();
if (this.googlePickerComponent) {
this.googlePickerComponent.openPicker();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,26 @@
>
{{t 'osf-components.file-browser.upload_file'}}
</Button>
{{#if this.isGoogleDrive}}
<Button
data-analytics-name='Add a file from Google Drive'
data-test-add-google-drive
@layout='fake-link'
{{on 'click' (fn this.openGoogleFilePicker dropdown)}}
>
{{t 'osf-components.file-browser.add-from-drive'}}
</Button>
{{/if}}
</dropdown.content>
</ResponsiveDropdown>
<FileBrowser::AddNew::CreateFolderModal @isOpen={{this.createFolderModalOpen}} @manager={{@manager}} />
{{#if this.isGoogleDrive}}
<GoogleFilePickerWidget
@isFolderPicker={{false}}
@accountId={{this.accountId}}
@onRegisterChild={{this.registerChild}}
@rootFolderId={{this.googleFilePickerRootFolder}}
@manager={{@manager}}
></GoogleFilePickerWidget>
{{/if}}
{{/let}}
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,11 @@
@isRegistration={{@manager.targetNode.isRegistration}}
/>
{{#if (and @manager.currentFolder.userCanUploadToHere @enableUpload)}}
<FileBrowser::AddNew @manager={{@manager}} @setClickableElementId={{uploadWidget.setClickableElementId}} />
<FileBrowser::AddNew
@manager={{@manager}}
@setClickableElementId={{uploadWidget.setClickableElementId}}
@configuredStorageAddon={{@configuredStorageAddon}}
/>
{{/if}}
{{/if}}
</div>
Expand Down
Loading