4

I have been trying to find out what is incorrect with my Google Drive Picker integration but haven't been able to.

Once the picker opens, I'm shown a "Sign In" screen, which then opens the OAuth flow for the first time. After completing that it repeats the Sign In screen again. On clicking it again this time, it show the error - "The feature you requested is currently unavailable. Please try again later."

I have tried searching for various answers but none have worked. I have tried adding OAuth flow before the picker initialisation but it still does not solve the problem. Any help will be appreciated.

import { h, Component } from 'preact';
import googleClientAPI from 'google-client-api';
import styles from 'stylesheets/components/commons/drive';
import config from '../../config';

export default class DriveFilePicker extends Component {
  constructor(props) {
    super(props);
    this.setState({
      loaded: false,
    });
  }

  componentWillMount() {
    googleClientAPI().then(gapi => {      
      gapi.load('picker', this.buildPicker);      
    });
  }

  handleAuthResult = (authResult) => {
    if (authResult && !authResult.error) {
      oauthToken = authResult.access_token;
      this.buildPicker(oauthToken);
    }
  }


  buildPicker = (accessToken) => {
    accessToken = accessToken || this.props.accessToken;
    if (typeof google !== 'undefined' && typeof accessToken !== 'undefined') {
      const docsView = new google.picker.DocsView()
        .setIncludeFolders(true)
        .setMimeTypes('application/vnd.google-apps.folder')
        .setSelectFolderEnabled(true);

      this.picker = new google.picker.PickerBuilder()
        .enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
        .addView(docsView)
        .setOAuthToken(accessToken)
        .setDeveloperKey(config.gapi.developerKey)
        .setCallback(this.onPicked)
        .build();
      this.setState({
        loaded: true,
      });
    }
  }

  componentWillReceiveProps({ accessToken: nextAccessToken }) {
    if (this.props.accessToken !== nextAccessToken) {
      this.setState({
        loaded: false,
      });
      this.buildPicker(nextAccessToken);
    }
  }

  onPicked = ({ action, docs }) => {
    if (action === 'picked') {
      this.props.onAddFolder(docs);
    }
  }

  onOpen() {
    this.state.loaded && this.picker.setVisible(true);
  }

  render() {
    const { loaded } = this.state;
    return (
      <div className={`${!loaded ? styles.disabled : ''} ${styles.drive}`}>
        <div className={styles.label}>Sync folders</div>
        <div className={`${!loaded ? styles.disabled : ''} ${styles.folders}`}>
          <Tag hideRemove={true} onClick={::this.onOpen}>+Add folder</Tag>
        </div>
      </div>
    );
  }
}
Rishi Raj
  • 432
  • 4
  • 12

1 Answers1

0

Finally got this series of functions to load api platform and client, I have <script src/> in index.html too but I don't think that is required when appendChild script after mounting. The order of loading api to platform to client:auth2, then building the picker upon successful authResult from authorize seems significant. I couldn't get sign-in2 + init to work so I used authorize

var SCOPES = "https://www.googleapis.com/auth/drive.file"
...
componentDidMount = () => {
this.loadGoogleAPI()
}

load google scripts


  loadGoogleApi() {
    const script = document.createElement("script");
    script.src = "https://apis.google.com/js/api.js";
    script.onload = () => {
      console.log("google api loaded");
      this.loadGapi();
    };
    document.body.appendChild(script);
  }
  loadGapi = () => {
    const script = document.createElement("script");
    script.src = "https://apis.google.com/js/platform.js";
    script.onload = () => {
      console.log("google api platform loaded");
      this.loadGapiClient();
    };
    document.body.appendChild(script);
  };
  loadGapiClient = () => {
    const script = document.createElement("script");
    script.src = "https://apis.google.com/js/client.js";
    script.onload = () => {
      console.log("google api client loaded");
      /*this.gapi.client.load("youtube", "v3", () =>
        console.log("loaded youtube")
      );*/
      this.gapi = window.gapi;
      this.gapi.load("client:auth2", () => {
        /*this.gapi.load("signin2", () => {
            console.log("render a sign in button");
            // using this method will show Signed In if the user is already signed in
          });*/
        console.log("auth2 loaded");
      });
    };
    document.body.appendChild(script);
  };

clicked google branded sign-in button

  loadGapiApi = () => {
    //var DIALOG_DIMENSIONS = { width: "90%", height: "90%" };
    this.gapi = window.gapi;

    console.log("authooo");
    this.gapi.auth2.authorize(
      //getAuthInstance().signIn(
      //init(
      //authorize(
      {
        api_key: API_KEY,
        client_id: CLIENT_ID,
        scope: SCOPES,
        prompt: "none"
        //prompt: "select_account"
      },
      (authResult) => {
        if (authResult) {
          this.gapi.client.load("drive", "v3", () =>
            console.log("loaded drive")
          );

          this.gapi.load("picker", () => {
            console.log("drive picker loaded");
            this.googlepicker = window.google;

            var view1 = new this.googlepicker.picker.DocsView(
              this.googlepicker.picker.ViewId.IMAGE
            ).setSelectFolderEnabled(true);


            var view = new this.googlepicker.picker.DocsView(
              this.googlepicker.picker.ViewId.DOCS
            ).setSelectFolderEnabled(true);
            var uploadView = new this.googlepicker.picker.DocsUploadView();
            view.setMode(this.googlepicker.picker.DocsViewMode.LIST);
            view.setQuery(window.dataFeedName);

            this.picker = new this.googlepicker.picker.PickerBuilder()
              .setAppId(CLIENT_ID)
              .setOAuthToken(authResult.access_token)
              .addView(view)
              .addView(uploadView)
              //.enableFeature(google.picker.Feature.SIMPLE_UPLOAD_ENABLED)
              //.enableFeature(google.picker.Feature.SUPPORT_TEAM_DRIVES)
              .enableFeature(
                this.googlepicker.picker.Feature.MULTISELECT_ENABLED
              ) //optional
              .setOrigin("https://thumbprint.us")
              .setCallback(this.pickerCallback)
              .build();
            window.picker = this.picker;

          });

          this.gapi.load("drive-share", () => {
            console.log("share dialog loaded");
            this.s = window.s;
            this.s = new window.gapi.drive.share.ShareClient();
            this.s.setOAuthToken(authResult.access_token);
          });

          this.setState({
            authResult,
            accessToken: authResult.access_token,
            authorizedScopes: true,
            signedIn: true
          });
          //const auth2 = this.gapi.auth2.getAuthInstance();
          //this.auth2.signIn();
        }
      }
    );
  };

share drive & signout


  logout = () => {
    window.location.href =
      "https://www.google.com/accounts/Logout?continue=https://appengine.google.com/_ah/logout?continue=https://thumbprint.us";
  };
  signOut = () => {
    console.log("trying to sign out");
    if (this.gapi) {
      //console.log(auth2);
      this.auth2 = window.auth2;
      this.auth2
        .signOut()
        .then(() => {
          //if (auth2 !== null) {
          console.log("outted successfully");
          this.auth2.disconnect();
        })
        .catch((err) => console.log(err.message));
      this.auth2.disconnect();
      //this.logout();
    }
  };
  switchAccount = () => {
    console.log("trying to sign out");
    this.gapi = window.gapi;
    this.gapi.auth2
      .getAuthInstance()
      .signIn({
        api_key: API_KEY,
        client_id: CLIENT_ID,
        scope: SCOPES,
        prompt: "select_account"
      })
      .then(() => {
        //if (auth2 !== null) {
        console.log("outted successfully");
        this.auth2.disconnect();
      })
      .catch((err) => console.log(err.message));
  };
  pickerCallback = (data) => {
    if (data.action === window.google.picker.Action.PICKED) {
      var fileId = data.docs[0].id;
      //console.log(fileId);
      //console.log(window.gapi);
      //console.log(data.docs[0].name);
      this.s.setItemIds([fileId]);
      if (this.state.filesPreparedToSend !== data.docs) {
        //console.log(data.docs);
        this.setState({ filesPreparedToSend: data.docs });
      }
    }
  };