Browse Source

Merge pull request #6761 from weseek/dev/5.1.x

release: v5.1.6
Yuki Takei 3 years ago
parent
commit
b5461b8aaf

+ 1 - 1
lerna.json

@@ -1,7 +1,7 @@
 {
   "npmClient": "yarn",
   "useWorkspaces": true,
-  "version": "5.1.5",
+  "version": "5.1.6-RC.0",
   "packages": [
     "packages/*"
   ]

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "growi",
-  "version": "5.1.5",
+  "version": "5.1.6-RC.0",
   "description": "Team collaboration software using markdown",
   "tags": [
     "wiki",

+ 8 - 8
packages/app/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/app",
-  "version": "5.1.5",
+  "version": "5.1.6-RC.0",
   "license": "MIT",
   "scripts": {
     "//// for production": "",
@@ -64,12 +64,12 @@
     "@elastic/elasticsearch7": "npm:@elastic/elasticsearch@^7.17.0",
     "@godaddy/terminus": "^4.9.0",
     "@google-cloud/storage": "^5.8.5",
-    "@growi/codemirror-textlint": "^5.1.5",
-    "@growi/core": "^5.1.5",
-    "@growi/plugin-attachment-refs": "^5.1.5",
-    "@growi/plugin-lsx": "^5.1.5",
-    "@growi/plugin-pukiwiki-like-linker": "^5.1.5",
-    "@growi/slack": "^5.1.5",
+    "@growi/codemirror-textlint": "^5.1.6-RC.0",
+    "@growi/core": "^5.1.6-RC.0",
+    "@growi/plugin-attachment-refs": "^5.1.6-RC.0",
+    "@growi/plugin-lsx": "^5.1.6-RC.0",
+    "@growi/plugin-pukiwiki-like-linker": "^5.1.6-RC.0",
+    "@growi/slack": "^5.1.6-RC.0",
     "@promster/express": "^7.0.2",
     "@promster/server": "^7.0.4",
     "@slack/events-api": "^3.0.0",
@@ -172,7 +172,7 @@
   },
   "devDependencies": {
     "@alienfast/i18next-loader": "^1.1.4",
-    "@growi/ui": "^5.1.5",
+    "@growi/ui": "^5.1.6-RC.0",
     "@handsontable/react": "=2.1.0",
     "@types/compression": "^1.7.0",
     "@types/express": "^4.17.11",

+ 5 - 11
packages/app/src/client/services/PageContainer.js

@@ -7,9 +7,6 @@ import { Container } from 'unstated';
 import { EditorMode } from '~/stores/ui';
 import loggerFactory from '~/utils/logger';
 
-import { toastError } from '../util/apiNotification';
-import { apiPost } from '../util/apiv1-client';
-import { apiv3Post } from '../util/apiv3-client';
 import {
   DetachCodeBlockInterceptor,
   RestoreCodeBlockInterceptor,
@@ -17,6 +14,9 @@ import {
 import {
   DrawioInterceptor,
 } from '../../services/renderer/interceptor/drawio-interceptor';
+import { toastError } from '../util/apiNotification';
+import { apiPost } from '../util/apiv1-client';
+import { apiv3Post } from '../util/apiv3-client';
 
 const { isTrashPage } = pagePathUtils;
 
@@ -423,23 +423,17 @@ export default class PageContainer extends Container {
   retrieveMyBookmarkList() {
   }
 
-  async resolveConflict(markdown, editorMode) {
+  async resolveConflict(markdown, editorMode, optionsToSave) {
 
     const { pageId, remoteRevisionId, path } = this.state;
     const editorContainer = this.appContainer.getContainer('EditorContainer');
-    const options = editorContainer.getCurrentOptionsToSave();
-    const optionsToSave = Object.assign({}, options);
 
     const res = await this.updatePage(pageId, remoteRevisionId, markdown, optionsToSave);
 
     editorContainer.clearDraft(path);
     this.updateStateAfterSave(res.page, res.tags, res.revision, editorMode);
 
-    // Update PageEditor component
-    if (editorMode !== EditorMode.Editor) {
-      // eslint-disable-next-line no-undef
-      globalEmitter.emit('updateEditorValue', markdown);
-    }
+    window.globalEmitter.emit('updateEditorValue', markdown);
 
     editorContainer.setState({ tags: res.tags });
 

+ 1 - 1
packages/app/src/client/util/editor.ts

@@ -1,4 +1,4 @@
-type OptionsToSave = {
+export type OptionsToSave = {
   isSlackEnabled: boolean;
   slackChannels: string;
   grant: number;

+ 33 - 12
packages/app/src/components/Common/ImageCropModal.tsx

@@ -49,6 +49,14 @@ const ImageCropModal: FC<Props> = (props: Props) => {
   const { t } = useTranslation();
   const reset = useCallback(() => {
     if (imageRef) {
+      // Some SVG files may not have width and height properties, causing the render size to be 0x0
+      // Force imageRef to have width and height by create temporary image element then set the imageRef width with tempImage width
+      // Set imageRef width & height by natural width / height if image has no dimension
+      if (imageRef.width === 0 || imageRef.height === 0) {
+        imageRef.width = imageRef.naturalWidth;
+        imageRef.height = imageRef.naturalHeight;
+      }
+      // Get size of Image, min value of width and height
       const size = Math.min(imageRef.width, imageRef.height);
       setCropOtions({
         aspect: 1,
@@ -63,6 +71,7 @@ const ImageCropModal: FC<Props> = (props: Props) => {
 
   useEffect(() => {
     document.body.style.position = 'static';
+    setIsCropImage(true);
     reset();
   }, [reset]);
 
@@ -73,18 +82,22 @@ const ImageCropModal: FC<Props> = (props: Props) => {
   };
 
 
-  const onCropChange = (crop) => {
-    setCropOtions(crop);
-  };
+  const getCroppedImg = async(image: HTMLImageElement, crop: ICropOptions) => {
+    const {
+      naturalWidth: imageNaturalWidth, naturalHeight: imageNaturalHeight, width: imageWidth, height: imageHeight,
+    } = image;
+
+    const {
+      width: cropWidth, height: cropHeight, x, y,
+    } = crop;
 
-  const getCroppedImg = async(image, crop) => {
     const canvas = document.createElement('canvas');
-    const scaleX = image.naturalWidth / image.width;
-    const scaleY = image.naturalHeight / image.height;
-    canvas.width = crop.width;
-    canvas.height = crop.height;
+    const scaleX = imageNaturalWidth / imageWidth;
+    const scaleY = imageNaturalHeight / imageHeight;
+    canvas.width = cropWidth;
+    canvas.height = cropHeight;
     const ctx = canvas.getContext('2d');
-    ctx?.drawImage(image, crop.x * scaleX, crop.y * scaleY, crop.width * scaleX, crop.height * scaleY, 0, 0, crop.width, crop.height);
+    ctx?.drawImage(image, x * scaleX, y * scaleY, cropWidth * scaleX, cropHeight * scaleY, 0, 0, cropWidth, cropHeight);
     try {
       const blob = await canvasToBlob(canvas);
       return blob;
@@ -105,7 +118,6 @@ const ImageCropModal: FC<Props> = (props: Props) => {
   // Clear image and set isImageCrop true on modal close
   const onModalCloseHandler = async() => {
     setImageRef(null);
-    setIsCropImage(true);
     onModalClose();
   };
 
@@ -129,12 +141,21 @@ const ImageCropModal: FC<Props> = (props: Props) => {
       <ModalBody className="my-4">
         {
           isCropImage
-            ? (<ReactCrop src={src} crop={cropOptions} onImageLoaded={onImageLoaded} onChange={onCropChange} circularCrop={isCircular} />)
+            ? (
+              <ReactCrop
+                style={{ backgroundColor: 'transparent' }}
+                src={src}
+                crop={cropOptions}
+                onImageLoaded={onImageLoaded}
+                onChange={crop => setCropOtions(crop)}
+                circularCrop={isCircular}
+              />
+            )
             : (<img style={{ maxWidth: imageRef?.width }} src={imageRef?.src} />)
         }
       </ModalBody>
       <ModalFooter>
-        <button type="button" className="btn btn-outline-danger rounded-pill mr-auto" onClick={reset}>
+        <button type="button" className="btn btn-outline-danger rounded-pill mr-auto" disabled={!isCropImage} onClick={reset}>
           {t('crop_image_modal.reset')}
         </button>
         { !showCropOption && (

+ 12 - 9
packages/app/src/components/PageEditor.tsx

@@ -107,6 +107,16 @@ const PageEditor = (props: Props): JSX.Element => {
   const editorRef = useRef<EditorRef>(null);
   const previewRef = useRef<HTMLDivElement>(null);
 
+
+  const optionsToSave = useMemo(() => {
+    if (grant == null) {
+      return;
+    }
+    const slackChannels = slackChannelsData ? slackChannelsData.toString() : '';
+    const optionsToSave = getOptionsToSave(isSlackEnabled ?? false, slackChannels, grant, grantGroupId, grantGroupName, pageTags || []);
+    return optionsToSave;
+  }, [grant, grantGroupId, grantGroupName, isSlackEnabled, pageTags, slackChannelsData]);
+
   const setMarkdownWithDebounce = useMemo(() => debounce(50, throttle(100, value => setMarkdown(value))), []);
   const saveDraftWithDebounce = useMemo(() => debounce(800, () => {
     editorContainer.saveDraft(pageContainer.state.path, markdown);
@@ -122,14 +132,6 @@ const PageEditor = (props: Props): JSX.Element => {
 
 
   const saveWithShortcut = useCallback(async() => {
-    if (grant == null) {
-      return;
-    }
-
-    const slackChannels = slackChannelsData ? slackChannelsData.toString() : '';
-
-    const optionsToSave = getOptionsToSave(isSlackEnabled ?? false, slackChannels, grant, grantGroupId, grantGroupName, pageTags || []);
-
     try {
       // disable unsaved warning
       editorContainer.disableUnsavedWarning();
@@ -147,7 +149,7 @@ const PageEditor = (props: Props): JSX.Element => {
       logger.error('failed to save', error);
       pageContainer.showErrorToastr(error);
     }
-  }, [editorContainer, editorMode, grant, grantGroupId, grantGroupName, isSlackEnabled, slackChannelsData, markdown, pageContainer, pageTags]);
+  }, [editorContainer, pageContainer, markdown, editorMode, optionsToSave]);
 
 
   /**
@@ -430,6 +432,7 @@ const PageEditor = (props: Props): JSX.Element => {
         onClose={() => pageContainer.setState({ isConflictDiffModalOpen: false })}
         pageContainer={pageContainer}
         markdownOnEdit={markdown}
+        optionsToSave={optionsToSave}
       />
     </div>
   );

+ 4 - 2
packages/app/src/components/PageEditor/ConflictDiffModal.tsx

@@ -10,6 +10,7 @@ import {
   Modal, ModalHeader, ModalBody, ModalFooter,
 } from 'reactstrap';
 
+import { OptionsToSave } from '~/client/util/editor';
 import { IUser } from '~/interfaces/user';
 import { useCurrentUser } from '~/stores/context';
 import { useEditorMode } from '~/stores/ui';
@@ -31,6 +32,7 @@ type ConflictDiffModalProps = {
   onClose?: (() => void);
   pageContainer: PageContainer;
   markdownOnEdit: string;
+  optionsToSave: OptionsToSave | undefined;
 };
 
 type IRevisionOnConflictWithStringDate = Omit<IRevisionOnConflict, 'createdAt'> & {
@@ -101,7 +103,7 @@ const ConflictDiffModalCore = (props: ConflictDiffModalProps & { currentUser: IU
     const codeMirrorVal = uncontrolledRef.current?.editor.doc.getValue();
 
     try {
-      await pageContainer.resolveConflict(codeMirrorVal, editorMode);
+      await pageContainer.resolveConflict(codeMirrorVal, editorMode, props.optionsToSave);
       close();
       pageContainer.showSuccessToastr();
     }
@@ -109,7 +111,7 @@ const ConflictDiffModalCore = (props: ConflictDiffModalProps & { currentUser: IU
       pageContainer.showErrorToastr(error);
     }
 
-  }, [editorMode, close, pageContainer]);
+  }, [pageContainer, editorMode, props.optionsToSave, close]);
 
   const resizeAndCloseButtons = useMemo(() => (
     <div className="d-flex flex-nowrap">

+ 1 - 1
packages/codemirror-textlint/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/codemirror-textlint",
-  "version": "5.1.5",
+  "version": "5.1.6-RC.0",
   "license": "MIT",
   "main": "dist/index.js",
   "scripts": {

+ 1 - 1
packages/core/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/core",
-  "version": "5.1.5",
+  "version": "5.1.6-RC.0",
   "description": "GROWI Core Libraries",
   "license": "MIT",
   "keywords": [

+ 1 - 1
packages/plugin-attachment-refs/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/plugin-attachment-refs",
-  "version": "5.1.5",
+  "version": "5.1.6-RC.0",
   "description": "GROWI Plugin to add ref/refimg/refs/refsimg tags",
   "license": "MIT",
   "keywords": [

+ 1 - 1
packages/plugin-lsx/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/plugin-lsx",
-  "version": "5.1.5",
+  "version": "5.1.6-RC.0",
   "description": "GROWI plugin to list pages",
   "license": "MIT",
   "keywords": [

+ 1 - 1
packages/plugin-pukiwiki-like-linker/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/plugin-pukiwiki-like-linker",
-  "version": "5.1.5",
+  "version": "5.1.6-RC.0",
   "description": "GROWI plugin to add PukiwikiLikeLinker",
   "license": "MIT",
   "keywords": [

+ 1 - 1
packages/slack/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/slack",
-  "version": "5.1.5",
+  "version": "5.1.6-RC.0",
   "license": "MIT",
   "main": "dist/index.js",
   "typings": "dist/index.d.ts",

+ 2 - 2
packages/slackbot-proxy/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/slackbot-proxy",
-  "version": "5.1.5",
+  "version": "5.1.6-slackbot-proxy.0",
   "license": "MIT",
   "scripts": {
     "build": "yarn tsc && tsc-alias -p tsconfig.build.json",
@@ -25,7 +25,7 @@
   },
   "dependencies": {
     "@godaddy/terminus": "^4.9.0",
-    "@growi/slack": "^5.1.5",
+    "@growi/slack": "^5.1.6-RC.0",
     "@slack/oauth": "^2.0.1",
     "@slack/web-api": "^6.2.4",
     "@tsed/common": "^6.43.0",

+ 1 - 1
packages/ui/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@growi/ui",
-  "version": "5.1.5",
+  "version": "5.1.6-RC.0",
   "description": "GROWI UI Libraries",
   "license": "MIT",
   "keywords": [