Source: gdfs-ui.js

  1. "use strict";
  2. const debug = require("debug")("gdfs-ui");
  3. debug("loading");
  4. const Gdfs = require("./gdfs.js");
  5. const GdfsEvent = require("./gdfs-event.js");
  6. /**
  7. * class GdfsUi
  8. * @constructor
  9. * @param {HTMLElement} The root element that UI widget will be built.
  10. * @param {Gdfs} The gapi client.
  11. */
  12. function GdfsUi(element, opt) {
  13. debug("Start of GdfsUi ctor");
  14. this._element = element;
  15. this._gdfs = new Gdfs();
  16. this._pageSize = 10;
  17. this._trashed = false;
  18. this._pageToken = null;
  19. this._files = [];
  20. this._opt = {
  21. onFileListChange: () => {},
  22. onCurrentDirChange: () => {},
  23. };
  24. opt = opt || {};
  25. for(const key of Object.keys(this._opt)) {
  26. if(key in opt) {
  27. this._opt[key] = opt[key];
  28. }
  29. }
  30. // events
  31. this._fileListChangeEvent = new GdfsEvent(
  32. this._element, "gdfsui-filelist-change");
  33. this._currentDirChangeEvent = new GdfsEvent(
  34. this._element, "gdfsui-current-dir-change");
  35. this._currentDirChangeEvent.listen(
  36. this._opt.onCurrentDirChange);
  37. this._fileListChangeEvent.listen(
  38. this._opt.onFileListChange);
  39. this._gdfs.onCwdUpdate(async () => {
  40. debug("Start of _gdfs.onCwdUpdate");
  41. await this.reload();
  42. this._currentDirChangeEvent.fire();
  43. debug("End of _gdfs.onCwdUpdate");
  44. });
  45. const onSignedInStatusChange = async status => {
  46. debug("Start of signInStatusChange");
  47. if(status) {
  48. await this._gdfs.chdir("/");
  49. }
  50. debug("End of signInStatusChange");
  51. };
  52. // Listen events
  53. Gdfs.signInStatusChangeEvent.listen(
  54. () => onSignedInStatusChange(Gdfs.isSignedIn()));
  55. onSignedInStatusChange(Gdfs.isSignedIn());
  56. debug("End of GdfsUi ctor");
  57. }
  58. /**
  59. * Returns the listing files in current directory is completed.
  60. * @returns {boolean} true if the listing files is completed.
  61. */
  62. GdfsUi.prototype.isPageCompleted = function() {
  63. const status = this._pageToken == null;
  64. return status;
  65. };
  66. /**
  67. * Get current path as full path.
  68. * @returns {Array<string>} The array of file ids.
  69. */
  70. GdfsUi.prototype.getCurrentPath = function() {
  71. return this._gdfs._currentPath;
  72. };
  73. /**
  74. * Get files list on current page.
  75. * @param {number} begin a file index
  76. * @param {number} end a file index
  77. * @returns {Array<File>} the files in current page.
  78. */
  79. GdfsUi.prototype.getFiles = async function(begin, end) {
  80. debug(`GdfsUi#getFiles param:{begin:${begin}, end:${end})}`);
  81. debug(`_pageToken: ${this._pageToken}`);
  82. if(this._pageToken == null) {
  83. this._files = [];
  84. }
  85. while(end > this._files.length) {
  86. await this.readDir();
  87. this._fileListChangeEvent.fire();
  88. if(this._pageToken == null) {
  89. break;
  90. }
  91. }
  92. return this._files.slice(begin, end);
  93. };
  94. /**
  95. * Read the files on current directory.
  96. * @async
  97. * @returns {Promise<undefined>}
  98. */
  99. GdfsUi.prototype.readDir = async function() {
  100. const andConditionsOfQuerySearchClauses = [
  101. `parents in '${this._gdfs.getCurrentFolderId()}'`,
  102. `trashed = ${this._trashed?"true":"false"}`,
  103. ];
  104. const queryParameters = {
  105. "pageSize": this._pageSize,
  106. "pageToken": this._pageToken,
  107. "q": andConditionsOfQuerySearchClauses.join(" and "),
  108. "fields": "nextPageToken, files(id, name, mimeType, webContentLink, webViewLink)",
  109. };
  110. const result = await Gdfs.getFileList(queryParameters);
  111. this._pageToken = result.nextPageToken;
  112. for(const file of result.files) {
  113. this._files.push(file);
  114. }
  115. };
  116. /**
  117. * Reload the file list.
  118. * @async
  119. * @returns {Promise} to sync
  120. */
  121. GdfsUi.prototype.reload = async function() {
  122. this._pageToken = null;
  123. this._files = [];
  124. await this.readDir();
  125. this._fileListChangeEvent.fire();
  126. };
  127. /**
  128. * Move current directory to root, parent or one of children.
  129. * @param {string} folderId A destination file id to move.
  130. * To move to parent, ".." is available.
  131. * @returns {Promise<undefined>}
  132. */
  133. GdfsUi.prototype.chdirById = async function(folderId) {
  134. await this._gdfs.chdirById(folderId);
  135. };
  136. /**
  137. * Get file resource.
  138. * @async
  139. * @param {string} fileId The file id of the target file.
  140. * @returns {Promise<object>} The resource object.
  141. */
  142. GdfsUi.prototype.getFileResource = async function(fileId) {
  143. return await Gdfs.getFileResource({
  144. "fileId": fileId,
  145. });
  146. };
  147. /**
  148. * Upload a file.
  149. * @param {File} file the file to be uploaded.
  150. * @return {Promise<File>} an uploaded File.
  151. */
  152. GdfsUi.prototype.uploadFile = function (file) {
  153. return new Promise( (resolve, reject) => {
  154. const reader = new FileReader();
  155. reader.onload = async () => {
  156. resolve(await this.writeFile(
  157. file.name, file.type, reader.result));
  158. };
  159. reader.onerror = event => {
  160. reject(new Error([
  161. "Fail to upload. Could not read the file ",
  162. `${file.name}(${event.type}).`,
  163. ].join("")));
  164. };
  165. reader.readAsArrayBuffer(file);
  166. });
  167. };
  168. /**
  169. * Create or overwrite a file to current directory.
  170. * @param {string} filename The file name.
  171. * @param {string} mimeType The content type.
  172. * @param {any} data The file content.
  173. * @returns {Promise<object>} The response of update.
  174. */
  175. GdfsUi.prototype.writeFile = async function (
  176. filename, mimeType, data)
  177. {
  178. // Find same file in current directory
  179. const fileIds = this._files
  180. .filter(file => (file.name === filename))
  181. .map( file => file.id );
  182. if(fileIds.length == 0) {
  183. //Create new file
  184. const response = await Gdfs.createFile(
  185. this._gdfs.getCurrentFolderId(), filename, mimeType);
  186. const file = JSON.parse(response);
  187. return await Gdfs.updateFile(
  188. file.id, mimeType, data);
  189. }
  190. // Overwrite the file
  191. return await Gdfs.updateFile(
  192. fileIds[0], mimeType, data);
  193. };
  194. module.exports = GdfsUi;