Kaynağa Gözat

Merge branch 'master' into fix/gw7821-openid-connect-fails

Haku Mizuki 3 yıl önce
ebeveyn
işleme
18bd10e43a

+ 14 - 18
packages/app/src/components/Page/TagsInput.tsx

@@ -1,11 +1,10 @@
 import React, {
 import React, {
   FC, useRef, useState, useCallback,
   FC, useRef, useState, useCallback,
 } from 'react';
 } from 'react';
+
 import { AsyncTypeahead } from 'react-bootstrap-typeahead';
 import { AsyncTypeahead } from 'react-bootstrap-typeahead';
 
 
-import { apiGet } from '~/client/util/apiv1-client';
-import { toastError } from '~/client/util/apiNotification';
-import { IResTagsSearchApiv1 } from '~/interfaces/tag';
+import { useSWRxTagsSearch } from '~/stores/tag';
 
 
 type TypeaheadInstance = {
 type TypeaheadInstance = {
   _handleMenuItemSelect: (activeItem: string, event: React.KeyboardEvent) => void,
   _handleMenuItemSelect: (activeItem: string, event: React.KeyboardEvent) => void,
@@ -24,7 +23,11 @@ const TagsInput: FC<Props> = (props: Props) => {
   const tagsInputRef = useRef<TypeaheadInstance>(null);
   const tagsInputRef = useRef<TypeaheadInstance>(null);
 
 
   const [resultTags, setResultTags] = useState<string[]>([]);
   const [resultTags, setResultTags] = useState<string[]>([]);
-  const [isLoading, setLoading] = useState(false);
+  const [searchQuery, setSearchQuery] = useState('');
+
+  const { data: tagsSearch, error } = useSWRxTagsSearch(searchQuery);
+
+  const isLoading = error == null && tagsSearch === undefined;
 
 
   const changeHandler = useCallback((selected: string[]) => {
   const changeHandler = useCallback((selected: string[]) => {
     if (props.onTagsUpdated != null) {
     if (props.onTagsUpdated != null) {
@@ -33,20 +36,13 @@ const TagsInput: FC<Props> = (props: Props) => {
   }, [props]);
   }, [props]);
 
 
   const searchHandler = useCallback(async(query: string) => {
   const searchHandler = useCallback(async(query: string) => {
-    setLoading(true);
-    try {
-      // TODO: 91698 SWRize
-      const res = await apiGet('/tags.search', { q: query }) as IResTagsSearchApiv1;
-      res.tags.unshift(query);
-      setResultTags(Array.from(new Set(res.tags)));
-    }
-    catch (err) {
-      toastError(err);
-    }
-    finally {
-      setLoading(false);
-    }
-  }, []);
+    const tagsSearchData = tagsSearch?.tags || [];
+    setSearchQuery(query);
+
+    tagsSearchData.unshift(searchQuery);
+    setResultTags(Array.from(new Set(tagsSearchData)));
+
+  }, [searchQuery, tagsSearch?.tags]);
 
 
   const keyDownHandler = useCallback((event: React.KeyboardEvent) => {
   const keyDownHandler = useCallback((event: React.KeyboardEvent) => {
     if (event.key === ' ') {
     if (event.key === ' ') {

+ 4 - 2
packages/app/src/server/service/file-uploader/gcs.js

@@ -2,8 +2,8 @@ import loggerFactory from '~/utils/logger';
 
 
 const logger = loggerFactory('growi:service:fileUploaderAws');
 const logger = loggerFactory('growi:service:fileUploaderAws');
 
 
-const urljoin = require('url-join');
 const { Storage } = require('@google-cloud/storage');
 const { Storage } = require('@google-cloud/storage');
+const urljoin = require('url-join');
 
 
 let _instance;
 let _instance;
 
 
@@ -21,7 +21,9 @@ module.exports = function(crowi) {
     if (_instance == null) {
     if (_instance == null) {
       const keyFilename = configManager.getConfig('crowi', 'gcs:apiKeyJsonPath');
       const keyFilename = configManager.getConfig('crowi', 'gcs:apiKeyJsonPath');
       // see https://googleapis.dev/nodejs/storage/latest/Storage.html
       // see https://googleapis.dev/nodejs/storage/latest/Storage.html
-      _instance = new Storage({ keyFilename });
+      _instance = keyFilename != null
+        ? new Storage({ keyFilename }) // Create a client with explicit credentials
+        : new Storage(); // Create a client that uses Application Default Credentials
     }
     }
     return _instance;
     return _instance;
   }
   }

+ 8 - 1
packages/app/src/stores/tag.tsx

@@ -2,7 +2,7 @@ import { SWRResponse } from 'swr';
 import useSWRImmutable from 'swr/immutable';
 import useSWRImmutable from 'swr/immutable';
 
 
 import { apiGet } from '~/client/util/apiv1-client';
 import { apiGet } from '~/client/util/apiv1-client';
-import { IResTagsListApiv1 } from '~/interfaces/tag';
+import { IResTagsListApiv1, IResTagsSearchApiv1 } from '~/interfaces/tag';
 
 
 export const useSWRxTagsList = (limit?: number, offset?: number): SWRResponse<IResTagsListApiv1, Error> => {
 export const useSWRxTagsList = (limit?: number, offset?: number): SWRResponse<IResTagsListApiv1, Error> => {
   return useSWRImmutable(
   return useSWRImmutable(
@@ -10,3 +10,10 @@ export const useSWRxTagsList = (limit?: number, offset?: number): SWRResponse<IR
     (endpoint, limit, offset) => apiGet(endpoint, { limit, offset }).then((result: IResTagsListApiv1) => result),
     (endpoint, limit, offset) => apiGet(endpoint, { limit, offset }).then((result: IResTagsListApiv1) => result),
   );
   );
 };
 };
+
+export const useSWRxTagsSearch = (query: string): SWRResponse<IResTagsSearchApiv1, Error> => {
+  return useSWRImmutable(
+    ['/tags.search', query],
+    (endpoint, query) => apiGet(endpoint, { q: query }).then((result: IResTagsSearchApiv1) => result),
+  );
+};