Skip to content

Commit 99dd98d

Browse files
committed
Updates to move all the google file picker code into the component
1 parent 6f9dafe commit 99dd98d

File tree

3 files changed

+162
-125
lines changed

3 files changed

+162
-125
lines changed

lib/osf-components/addon/components/google-file-picker-widget/component.ts

Lines changed: 150 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ declare global {
4949
GoogleFilePickerWidget?: GoogleFilePickerWidget;
5050
selectFolder?: (a: Partial<Item>)=> void;
5151
handleAuthClick?: ()=> void;
52+
gapi?: any;
53+
google?: any;
5254
SCOPES: string;
5355
CLIENT_ID: string;
5456
API_KEY: string;
@@ -79,6 +81,21 @@ export default class GoogleFilePickerWidget extends Component<Args> {
7981
@tracked folderName!: string | undefined;
8082
@tracked isFolderPicker = false;
8183
@tracked openGoogleFilePicker = false;
84+
@tracked visible = false;
85+
pickerInited = false;
86+
gisInited = false;
87+
selectFolder: any = undefined;
88+
tokenClient: any = undefined;
89+
accessToken!: string;
90+
scopes = GOOGLE_FILE_PICKER_SCOPES;
91+
clientId = GOOGLE_FILE_PICKER_CLIENT_ID;
92+
apiKey = GOOGLE_FILE_PICKER_API_KEY;
93+
appId = GOOGLE_FILE_PICKER_APP_ID;
94+
mimeTypes = '';
95+
parentId = '';
96+
isMultipleSelect: boolean;
97+
title!: string;
98+
8299
/**
83100
* Constructor
84101
*
@@ -98,22 +115,32 @@ export default class GoogleFilePickerWidget extends Component<Args> {
98115
super(owner, args);
99116

100117
window.GoogleFilePickerWidget = this;
101-
window.selectFolder = this.args.selectFolder;
102-
window.SCOPES = GOOGLE_FILE_PICKER_SCOPES;
103-
window.CLIENT_ID = GOOGLE_FILE_PICKER_CLIENT_ID;
104-
window.API_KEY= GOOGLE_FILE_PICKER_API_KEY;
105-
window.APP_ID= GOOGLE_FILE_PICKER_APP_ID;
106-
window.MIME_TYPES = this.args.isFolderPicker ? 'application/vnd.google-apps.folder' : '';
107-
window.PARENT_ID = this.args.isFolderPicker ? '': this.args.rootFolderId;
118+
// window.selectFolder = this.args.selectFolder;
119+
// window.SCOPES = GOOGLE_FILE_PICKER_SCOPES;
120+
// window.CLIENT_ID = GOOGLE_FILE_PICKER_CLIENT_ID;
121+
// window.API_KEY= GOOGLE_FILE_PICKER_API_KEY;
122+
// window.APP_ID= GOOGLE_FILE_PICKER_APP_ID;
123+
// window.MIME_TYPES = this.args.isFolderPicker ? 'application/vnd.google-apps.folder' : '';
124+
// window.PARENT_ID = this.args.isFolderPicker ? '': this.args.rootFolderId;
125+
// window.IS_MULTIPLE_SELECT = !this.args.isFolderPicker;
126+
/*
108127
window.TITLE = this.args.isFolderPicker ?
109128
this.intl.t('addons.configure.google-file-picker.root-folder-title') :
110129
this.intl.t('addons.configure.google-file-picker.file-folder-title');
111-
window.IS_MULTIPLE_SELECT = !this.args.isFolderPicker;
112-
window.isFolderPicker = this.args.isFolderPicker;
130+
*/
131+
this.selectFolder = this.args.selectFolder;
132+
this.mimeTypes = this.args.isFolderPicker ? 'application/vnd.google-apps.folder' : '';
133+
this.parentId = this.args.isFolderPicker ? '': this.args.rootFolderId;
134+
this.title = this.args.isFolderPicker ?
135+
this.intl.t('addons.configure.google-file-picker.root-folder-title') :
136+
this.intl.t('addons.configure.google-file-picker.file-folder-title');
137+
this.isMultipleSelect = !this.args.isFolderPicker;
138+
// window.isFolderPicker = this.args.isFolderPicker;
113139
this.isFolderPicker = this.args.isFolderPicker;
114-
window.tokenClient = undefined;
115-
window.pickerInited = false;
116-
window.gisInited = false;
140+
// window.tokenClient = undefined;
141+
// window.pickerInited = false;
142+
// window.gisInited = false;
143+
117144

118145
this.folderName = this.args.selectedFolderName;
119146

@@ -128,7 +155,7 @@ export default class GoogleFilePickerWidget extends Component<Args> {
128155
findRecord('authorized-storage-account', this.args.accountId);
129156
authorizedStorageAccount.serializeOauthToken = true;
130157
const token = await authorizedStorageAccount.save();
131-
window.accessToken = token.oauthToken;
158+
this.accessToken = token.oauthToken;
132159
}
133160
}
134161

@@ -143,9 +170,9 @@ export default class GoogleFilePickerWidget extends Component<Args> {
143170
*/
144171
@action
145172
filePickerCallback(file: any) {
146-
if (window?.selectFolder !== undefined) {
173+
if (this.selectFolder !== undefined) {
147174
this.folderName = file.name;
148-
window?.selectFolder({
175+
this.selectFolder({
149176
itemName: file.name,
150177
itemId: file.id,
151178
});
@@ -157,8 +184,8 @@ export default class GoogleFilePickerWidget extends Component<Args> {
157184
@action
158185
openPicker() {
159186
// Logic for opening Google File Picker here
160-
if (window.handleAuthClick) {
161-
window.handleAuthClick();
187+
if (this.handleAuthClick) {
188+
this.handleAuthClick();
162189
}
163190
}
164191

@@ -171,9 +198,112 @@ export default class GoogleFilePickerWidget extends Component<Args> {
171198

172199
willDestroy() {
173200
super.willDestroy();
174-
delete window.tokenClient;
175-
window.pickerInited = false;
176-
window.gisInited = false;
201+
delete this.tokenClient;
202+
this.pickerInited = false;
203+
this.gisInited = false;
204+
}
205+
206+
207+
/**
208+
* Callback after api.js is loaded.
209+
*/
210+
gapiLoaded() {
211+
window.gapi.load('client:picker', this.initializePicker.bind(this));
212+
}
213+
214+
/**
215+
* Callback after the API client is loaded. Loads the
216+
* discovery doc to initialize the API.
217+
*/
218+
async initializePicker() {
219+
await window.gapi.client.load('https://www.googleapis.com/discovery/v1/apis/drive/v3/rest');
220+
this.pickerInited = true;
221+
this.maybeEnableButtons();
222+
}
223+
224+
/**
225+
* Callback after Google Identity Services are loaded.
226+
*/
227+
gisLoaded() {
228+
if (!this.tokenClient) {
229+
this.tokenClient = window.google?.accounts?.oauth2.initTokenClient({
230+
client_id: this.clientId,
231+
scope: this.scopes,
232+
callback: '', // defined later
233+
});
234+
}
235+
this.gisInited = true;
236+
this.maybeEnableButtons();
237+
}
238+
239+
/**
240+
* Enables user interaction after all libraries are loaded.
241+
*/
242+
maybeEnableButtons() {
243+
if (this.pickerInited && this.gisInited && this.isFolderPicker) {
244+
this.visible = true;
245+
}
246+
}
247+
248+
/**
249+
* Sign in the user upon button click.
250+
*/
251+
@action
252+
handleAuthClick() {
253+
this.tokenClient.callback = async (response: any) => {
254+
if (response.error !== undefined) {
255+
throw (response);
256+
}
257+
await this.createPicker();
258+
};
259+
260+
if (this.accessToken === null) {
261+
// Prompt the user to select a Google Account and ask for consent to share their data
262+
// when establishing a new session.
263+
this.tokenClient?.requestAccessToken({prompt: 'consent'});
264+
} else {
265+
// Skip display of account chooser and consent dialog for an existing session.
266+
this.tokenClient?.requestAccessToken({prompt: ''});
267+
}
268+
}
269+
270+
/**
271+
* Create and render a Picker object for searching images.
272+
*/
273+
createPicker() {
274+
const googlePickerView = new window.google.picker.DocsView(window.google.picker.ViewId.DOCS);
275+
googlePickerView.setSelectFolderEnabled(true);
276+
googlePickerView.setMimeTypes(this.mimeTypes);
277+
googlePickerView.setIncludeFolders(true);
278+
googlePickerView.setParent(this.parentId);
279+
280+
const picker = new window.google.picker.PickerBuilder()
281+
.enableFeature(this.isMultipleSelect ? window.google.picker.Feature.MULTISELECT_ENABLED : '')
282+
.setDeveloperKey(this.apiKey)
283+
.setAppId(this.appId)
284+
.addView(googlePickerView)
285+
.setTitle(this.title)
286+
.setOAuthToken(this.accessToken)
287+
.setCallback(this.pickerCallback.bind(this))
288+
.build();
289+
picker.setVisible(true);
290+
}
291+
292+
/**
293+
* Displays the file details of the user's selection.
294+
* @param {object} data - Containers the user selection from the picker
295+
*/
296+
async pickerCallback(data: any) {
297+
if (data.action === window.google.picker.Action.PICKED) {
298+
const document = data[window.google.picker.Response.DOCUMENTS][0];
299+
const fileId = document[window.google.picker.Document.ID];
300+
const res = await window.gapi.client.drive.files.get({
301+
fileId,
302+
fields: '*',
303+
});
304+
// Correctly call the Ember method
305+
this.filePickerCallback(res.result);
306+
}
177307
}
178308
}
179309

lib/osf-components/addon/components/google-file-picker-widget/styles.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// stylelint-disable max-nesting-depth, selector-max-compound-selectors, selector-no-qualifying-type
12

23
.google-file-picker-container {
34
width: 100%;
@@ -14,6 +15,10 @@
1415

1516
.authorize-button {
1617
visibility: hidden;
18+
19+
&.visible {
20+
visibility: visible;
21+
}
1722
}
1823
}
1924
}

lib/osf-components/addon/components/google-file-picker-widget/template.hbs

Lines changed: 7 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -15,111 +15,13 @@ local-class='google-file-picker-container {{if this.isMobile 'mobile'}}'
1515
{{/if}}
1616
</div>
1717
<div local-class='action-container'>
18-
<button class='btn btn-primary btn-medium' local-class='authorize-button' type='button' id='authorize_button' onclick='handleAuthClick()'>{{t 'addons.configure.google-file-picker.select-root-folder'}}</button>
18+
<button class='btn btn-primary btn-medium' local-class='authorize-button {{if this.visible 'visible'}}' type='button' id='authorize_button'
19+
{{on 'click' (action this.handleAuthClick)}}
20+
>
21+
{{t 'addons.configure.google-file-picker.select-root-folder'}}
22+
</button>
1923
</div>
2024
{{/if}}
21-
<script type='text/javascript'>
22-
/**
23-
* Callback after api.js is loaded.
24-
*/
25-
function gapiLoaded() {
26-
gapi.load('client:picker', initializePicker);
27-
}
28-
29-
/**
30-
* Callback after the API client is loaded. Loads the
31-
* discovery doc to initialize the API.
32-
*/
33-
async function initializePicker() {
34-
await gapi.client.load('https://www.googleapis.com/discovery/v1/apis/drive/v3/rest');
35-
pickerInited = true;
36-
maybeEnableButtons();
37-
}
38-
39-
/**
40-
* Callback after Google Identity Services are loaded.
41-
*/
42-
function gisLoaded() {
43-
if (!tokenClient) {
44-
tokenClient = google.accounts.oauth2.initTokenClient({
45-
client_id: CLIENT_ID,
46-
scope: SCOPES,
47-
callback: '', // defined later
48-
})
49-
}
50-
gisInited = true;
51-
maybeEnableButtons();
52-
}
53-
54-
/**
55-
* Enables user interaction after all libraries are loaded.
56-
*/
57-
function maybeEnableButtons() {
58-
if (pickerInited && gisInited && isFolderPicker) {
59-
document.getElementById('authorize_button').style.visibility = 'visible';
60-
}
61-
}
62-
63-
/**
64-
* Sign in the user upon button click.
65-
*/
66-
function handleAuthClick() {
67-
tokenClient.callback = async (response) => {
68-
if (response.error !== undefined) {
69-
throw (response);
70-
}
71-
await createPicker();
72-
};
73-
74-
if (accessToken === null) {
75-
// Prompt the user to select a Google Account and ask for consent to share their data
76-
// when establishing a new session.
77-
tokenClient.requestAccessToken({prompt: 'consent'});
78-
} else {
79-
// Skip display of account chooser and consent dialog for an existing session.
80-
tokenClient.requestAccessToken({prompt: ''});
81-
}
82-
}
83-
84-
/**
85-
* Create and render a Picker object for searching images.
86-
*/
87-
function createPicker() {
88-
const googlePickerView = new google.picker.DocsView(google.picker.ViewId.DOCS);
89-
googlePickerView.setSelectFolderEnabled(true);
90-
googlePickerView.setMimeTypes(MIME_TYPES);
91-
googlePickerView.setIncludeFolders(true);
92-
googlePickerView.setParent(PARENT_ID);
93-
94-
const picker = new google.picker.PickerBuilder()
95-
.enableFeature(IS_MULTIPLE_SELECT ? google.picker.Feature.MULTISELECT_ENABLED : '')
96-
.setDeveloperKey(API_KEY)
97-
.setAppId(APP_ID)
98-
.addView(googlePickerView)
99-
.setTitle(TITLE)
100-
.setOAuthToken(accessToken)
101-
.setCallback(pickerCallback)
102-
.build();
103-
picker.setVisible(true);
104-
}
105-
106-
/**
107-
* Displays the file details of the user's selection.
108-
* @param {object} data - Containers the user selection from the picker
109-
*/
110-
async function pickerCallback(data) {
111-
if (data.action === google.picker.Action.PICKED) {
112-
const document = data[google.picker.Response.DOCUMENTS][0];
113-
const fileId = document[google.picker.Document.ID];
114-
const res = await gapi.client.drive.files.get({
115-
'fileId': fileId,
116-
'fields': '*',
117-
});
118-
// Correctly call the Ember method
119-
window.GoogleFilePickerWidget.filePickerCallback(res.result);
120-
}
121-
}
122-
</script>
123-
<script async defer src='https://apis.google.com/js/api.js' onload='gapiLoaded()'></script>
124-
<script async defer src='https://accounts.google.com/gsi/client' onload='gisLoaded()'></script>
25+
<script async defer src='https://apis.google.com/js/api.js' onload='window.GoogleFilePickerWidget.gapiLoaded()'></script>
26+
<script async defer src='https://accounts.google.com/gsi/client' onload='window.GoogleFilePickerWidget.gisLoaded()'></script>
12527
</div>

0 commit comments

Comments
 (0)