From c731bb9ad087a83de491b5331239b111e94455ef Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Sun, 29 Nov 2020 15:43:30 +0700 Subject: [PATCH 01/37] added promoted switch button --- .../editors/EditorImageUploadButton/index.tsx | 1 - .../editors/EditorPanel/styles.module.scss | 3 +- .../editors/EditorPublicSwitch/index.tsx | 49 +++++++++++++++ .../EditorPublicSwitch/styles.module.scss | 63 +++++++++++++++++++ .../editors/EditorUploadButton/index.tsx | 25 ++------ .../EditorUploadButton/styles.module.scss | 9 +-- src/redux/node/constants.ts | 15 ++++- src/redux/types.ts | 2 + src/sprites/Sprites.tsx | 10 +++ src/styles/variables.scss | 10 +++ 10 files changed, 153 insertions(+), 34 deletions(-) create mode 100644 src/components/editors/EditorPublicSwitch/index.tsx create mode 100644 src/components/editors/EditorPublicSwitch/styles.module.scss diff --git a/src/components/editors/EditorImageUploadButton/index.tsx b/src/components/editors/EditorImageUploadButton/index.tsx index 68504973..f333cf9d 100644 --- a/src/components/editors/EditorImageUploadButton/index.tsx +++ b/src/components/editors/EditorImageUploadButton/index.tsx @@ -1,6 +1,5 @@ import React, { FC } from 'react'; import { EditorUploadButton } from '~/components/editors/EditorUploadButton'; -import { INode } from '~/redux/types'; import { UPLOAD_TYPES } from '~/redux/uploads/constants'; import { IEditorComponentProps } from '~/redux/node/types'; diff --git a/src/components/editors/EditorPanel/styles.module.scss b/src/components/editors/EditorPanel/styles.module.scss index a58338b2..5bda9666 100644 --- a/src/components/editors/EditorPanel/styles.module.scss +++ b/src/components/editors/EditorPanel/styles.module.scss @@ -13,11 +13,12 @@ flex-direction: row; & > * { - margin: 0 $gap; + margin: 0 $gap / 2; &:first-child { margin-left: 0; } + &:last-child { margin-right: 0; } diff --git a/src/components/editors/EditorPublicSwitch/index.tsx b/src/components/editors/EditorPublicSwitch/index.tsx new file mode 100644 index 00000000..d8f9f889 --- /dev/null +++ b/src/components/editors/EditorPublicSwitch/index.tsx @@ -0,0 +1,49 @@ +import React, { FC, useCallback, useEffect, useRef } from 'react'; +import styles from './styles.module.scss'; +import { Icon } from '~/components/input/Icon'; +import { IEditorComponentProps } from '~/redux/node/types'; +import classNames from 'classnames'; +import { usePopper } from 'react-popper'; + +interface IProps extends IEditorComponentProps {} + +const EditorPublicSwitch: FC = ({ data, setData }) => { + const tooltip = useRef(null); + const onChange = useCallback(() => setData({ ...data, is_promoted: !data.is_promoted }), [ + data, + setData, + ]); + + const pop = usePopper(tooltip?.current?.parentElement, tooltip.current, { + placement: 'bottom', + modifiers: [ + { + name: 'offset', + options: { + offset: [0, 4], + }, + }, + ], + }); + + useEffect(() => console.log(pop), [pop]); + + return ( +
+
+ {data.is_promoted + ? 'Доступно всем на главной странице' + : 'Видно только сотрудникам в лаборатории'} +
+ +
+ {data.is_promoted ? : } +
+
+ ); +}; + +export { EditorPublicSwitch }; diff --git a/src/components/editors/EditorPublicSwitch/styles.module.scss b/src/components/editors/EditorPublicSwitch/styles.module.scss new file mode 100644 index 00000000..e41682c0 --- /dev/null +++ b/src/components/editors/EditorPublicSwitch/styles.module.scss @@ -0,0 +1,63 @@ +@import "src/styles/variables"; + +.wrap { + @include outer_shadow(); + @include editor_round_button(); + + transition: all 0.5s; + fill: $content_bg; + background-color: $olive; + + &.promoted { + background-color: lighten($content_bg, 4%); + fill: $red; + } + + &:hover { + opacity: 1; + + .tooltip { + opacity: 1; + } + } + + input { + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; + opacity: 0; + z-index: 1; + cursor: pointer; + } +} + +.icon { + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; + display: flex; + align-items: center; + justify-content: center; +} + +.tooltip { + border-radius: 2px; + background: darken($content_bg, 6%); + padding: $gap; + position: absolute; + font: $font_12_semibold; + bottom: 100%; + right: 0; + transform: translate(0, -$gap); + text-align: center; + touch-action: none; + pointer-events: none; + opacity: 0; + width: 100px; + user-select: none; + transition: all 0.1s; +} diff --git a/src/components/editors/EditorUploadButton/index.tsx b/src/components/editors/EditorUploadButton/index.tsx index 34e90a44..03fda22f 100644 --- a/src/components/editors/EditorUploadButton/index.tsx +++ b/src/components/editors/EditorUploadButton/index.tsx @@ -1,15 +1,15 @@ import React, { FC, useCallback, useEffect } from 'react'; import styles from './styles.module.scss'; import { Icon } from '~/components/input/Icon'; -import { IFileWithUUID, INode, IFile } from '~/redux/types'; +import { IFile, IFileWithUUID } from '~/redux/types'; import uuid from 'uuid4'; import { UPLOAD_SUBJECTS, UPLOAD_TARGETS, UPLOAD_TYPES } from '~/redux/uploads/constants'; import * as UPLOAD_ACTIONS from '~/redux/uploads/actions'; -import { assocPath } from 'ramda'; -import { append } from 'ramda'; +import { append, assocPath } from 'ramda'; import { selectUploads } from '~/redux/uploads/selectors'; import { connect } from 'react-redux'; import { NODE_SETTINGS } from '~/redux/node/constants'; +import { IEditorComponentProps } from '~/redux/node/types'; const mapStateToProps = state => { const { statuses, files } = selectUploads(state); @@ -22,12 +22,7 @@ const mapDispatchToProps = { }; type IProps = ReturnType & - typeof mapDispatchToProps & { - data: INode; - setData: (val: INode) => void; - temp: string[]; - setTemp: (val: string[]) => void; - + typeof mapDispatchToProps & IEditorComponentProps & { accept?: string; icon?: string; type?: typeof UPLOAD_TYPES[keyof typeof UPLOAD_TYPES]; @@ -79,18 +74,6 @@ const EditorUploadButtonUnconnected: FC = ({ [data, setData] ); - // const onDrop = useCallback( - // (event: React.DragEvent) => { - // event.preventDefault(); - - // if (!event.dataTransfer || !event.dataTransfer.files || !event.dataTransfer.files.length) - // return; - - // onUpload(Array.from(event.dataTransfer.files)); - // }, - // [onUpload] - // ); - useEffect(() => { window.addEventListener('dragover', eventPreventer, false); window.addEventListener('drop', eventPreventer, false); diff --git a/src/components/editors/EditorUploadButton/styles.module.scss b/src/components/editors/EditorUploadButton/styles.module.scss index 3ba89ad9..3347fd46 100644 --- a/src/components/editors/EditorUploadButton/styles.module.scss +++ b/src/components/editors/EditorUploadButton/styles.module.scss @@ -2,17 +2,10 @@ .wrap { @include outer_shadow(); + @include editor_round_button(); - width: $upload_button_height; - height: $upload_button_height; - border-radius: ($upload_button_height / 2) !important; - position: relative; - border-radius: $radius; - cursor: pointer; - // opacity: 0.7; transition: opacity 0.5s; background: $red_gradient; - // box-shadow: $content_bg 0 0 5px 10px; &:hover { opacity: 1; diff --git a/src/redux/node/constants.ts b/src/redux/node/constants.ts index 9d3da6af..30df9a77 100644 --- a/src/redux/node/constants.ts +++ b/src/redux/node/constants.ts @@ -15,6 +15,7 @@ import { EditorUploadCoverButton } from '~/components/editors/EditorUploadCoverB import { modalShowPhotoswipe } from '../modal/actions'; import { IEditorComponentProps } from '~/redux/node/types'; import { EditorFiller } from '~/components/editors/EditorFiller'; +import { EditorPublicSwitch } from '~/components/editors/EditorPublicSwitch'; const prefix = 'NODE.'; export const NODE_ACTIONS = { @@ -63,6 +64,8 @@ export const EMPTY_NODE: INode = { blocks: [], tags: [], + is_public: true, + is_promoted: true, flow: { display: 'single', @@ -120,14 +123,20 @@ export const NODE_EDITORS = { }; export const NODE_PANEL_COMPONENTS: Record[]> = { - [NODE_TYPES.TEXT]: [EditorFiller, EditorUploadCoverButton], - [NODE_TYPES.VIDEO]: [EditorFiller, EditorUploadCoverButton], - [NODE_TYPES.IMAGE]: [EditorImageUploadButton, EditorFiller, EditorUploadCoverButton], + [NODE_TYPES.TEXT]: [EditorFiller, EditorUploadCoverButton, EditorPublicSwitch], + [NODE_TYPES.VIDEO]: [EditorFiller, EditorUploadCoverButton, EditorPublicSwitch], + [NODE_TYPES.IMAGE]: [ + EditorImageUploadButton, + EditorFiller, + EditorUploadCoverButton, + EditorPublicSwitch, + ], [NODE_TYPES.AUDIO]: [ EditorAudioUploadButton, EditorImageUploadButton, EditorFiller, EditorUploadCoverButton, + EditorPublicSwitch, ], }; diff --git a/src/redux/types.ts b/src/redux/types.ts index dd5b95b4..b9beecaf 100644 --- a/src/redux/types.ts +++ b/src/redux/types.ts @@ -124,6 +124,8 @@ export interface INode { description?: string; is_liked?: boolean; is_heroic?: boolean; + is_promoted?: boolean; + is_public?: boolean; like_count?: number; flow: { diff --git a/src/sprites/Sprites.tsx b/src/sprites/Sprites.tsx index d3c8a38e..be5368da 100644 --- a/src/sprites/Sprites.tsx +++ b/src/sprites/Sprites.tsx @@ -235,6 +235,16 @@ const Sprites: FC<{}> = () => ( + + + + + + + + + + diff --git a/src/styles/variables.scss b/src/styles/variables.scss index 8577202c..a518e5d4 100644 --- a/src/styles/variables.scss +++ b/src/styles/variables.scss @@ -209,3 +209,13 @@ $sidebar_border: transparentize(white, 0.95); background: transparentize($content_bg, 0.4); box-shadow: transparentize(white, 0.95) -1px 0; } + +@mixin editor_round_button { + width: $upload_button_height; + height: $upload_button_height; + border-radius: ($upload_button_height / 2) !important; + flex: 0 0 $upload_button_height; + position: relative; + border-radius: $radius; + cursor: pointer; +} From 40af254e5c94bb492be0f76b36b01f2322ff7c14 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Fri, 5 Mar 2021 17:50:28 +0700 Subject: [PATCH 02/37] replaced div with button --- .../editors/EditorPublicSwitch/index.tsx | 29 +++++++++---------- src/components/input/Button/index.tsx | 3 ++ .../input/Button/styles.module.scss | 3 ++ 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/components/editors/EditorPublicSwitch/index.tsx b/src/components/editors/EditorPublicSwitch/index.tsx index d8f9f889..be6feed0 100644 --- a/src/components/editors/EditorPublicSwitch/index.tsx +++ b/src/components/editors/EditorPublicSwitch/index.tsx @@ -1,9 +1,7 @@ import React, { FC, useCallback, useEffect, useRef } from 'react'; -import styles from './styles.module.scss'; -import { Icon } from '~/components/input/Icon'; import { IEditorComponentProps } from '~/redux/node/types'; -import classNames from 'classnames'; import { usePopper } from 'react-popper'; +import { Button } from '~/components/input/Button'; interface IProps extends IEditorComponentProps {} @@ -29,20 +27,19 @@ const EditorPublicSwitch: FC = ({ data, setData }) => { useEffect(() => console.log(pop), [pop]); return ( -
-
- {data.is_promoted +
+ : 'Видно только сотрудникам в лаборатории' + } + onClick={onChange} + round + /> ); }; diff --git a/src/components/input/Button/index.tsx b/src/components/input/Button/index.tsx index 8c263770..1f2a02a6 100644 --- a/src/components/input/Button/index.tsx +++ b/src/components/input/Button/index.tsx @@ -28,6 +28,7 @@ type IButtonProps = DetailedHTMLProps< stretchy?: boolean; iconOnly?: boolean; label?: string; + round?: boolean; }; const Button: FC = memo( @@ -48,6 +49,7 @@ const Button: FC = memo( iconOnly, label, ref, + round, ...props }) => { const tooltip = useRef(null); @@ -75,6 +77,7 @@ const Button: FC = memo( icon: ((iconLeft || iconRight) && !title && !children) || iconOnly, has_icon_left: !!iconLeft, has_icon_right: !!iconRight, + round, }), ...props, }, diff --git a/src/components/input/Button/styles.module.scss b/src/components/input/Button/styles.module.scss index 676bb62d..667007bd 100644 --- a/src/components/input/Button/styles.module.scss +++ b/src/components/input/Button/styles.module.scss @@ -202,14 +202,17 @@ .normal { height: 38px; } + .big { height: 40px; } + .giant { height: 50px; padding: 0 15px; min-width: 50px; } + .disabled { opacity: 0.5; } From 470e1745472cd7ba36a5768134ad66996f77ca5c Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Tue, 9 Mar 2021 12:41:32 +0700 Subject: [PATCH 03/37] made swiper call slideTo(0) with timeout --- src/components/node/NodeImageSwiperBlock/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/node/NodeImageSwiperBlock/index.tsx b/src/components/node/NodeImageSwiperBlock/index.tsx index c6011813..da2b51f7 100644 --- a/src/components/node/NodeImageSwiperBlock/index.tsx +++ b/src/components/node/NodeImageSwiperBlock/index.tsx @@ -43,6 +43,7 @@ const NodeImageSwiperBlock: FC = ({ node }) => { const resetSwiper = useCallback(() => { if (!controlledSwiper) return; controlledSwiper.slideTo(0, 0); + setTimeout(() => controlledSwiper.slideTo(0, 0), 300); }, [controlledSwiper]); useEffect(() => { From 11325b96b31bda9e314ab17dfd3ac3cbfbcefc50 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Tue, 9 Mar 2021 13:42:36 +0700 Subject: [PATCH 04/37] fixed sidebar --- src/components/containers/Sticky/index.tsx | 12 +++-- src/components/node/NodeBottomBlock/index.tsx | 8 ++-- .../node/NodeBottomBlock/styles.module.scss | 48 +++++++++++++++++++ .../node/NodeImageSwiperBlock/index.tsx | 1 + .../main/Container/styles.module.scss | 4 ++ 5 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 src/components/node/NodeBottomBlock/styles.module.scss diff --git a/src/components/containers/Sticky/index.tsx b/src/components/containers/Sticky/index.tsx index f3e817d5..dfeda268 100644 --- a/src/components/containers/Sticky/index.tsx +++ b/src/components/containers/Sticky/index.tsx @@ -1,14 +1,16 @@ import React, { DetailsHTMLAttributes, FC, useEffect, useRef } from 'react'; import styles from './styles.module.scss'; -import StickySidebar from 'sticky-sidebar'; -import classnames from 'classnames'; + import ResizeSensor from 'resize-sensor'; +(window as any).ResizeSensor = ResizeSensor; + +import StickySidebar from 'sticky-sidebar'; +(window as any).StickySidebar = StickySidebar; + +import classnames from 'classnames'; interface IProps extends DetailsHTMLAttributes {} -(window as any).StickySidebar = StickySidebar; -(window as any).ResizeSensor = ResizeSensor; - const Sticky: FC = ({ children }) => { const ref = useRef(null); const sb = useRef(null); diff --git a/src/components/node/NodeBottomBlock/index.tsx b/src/components/node/NodeBottomBlock/index.tsx index 73a114e6..d06da73c 100644 --- a/src/components/node/NodeBottomBlock/index.tsx +++ b/src/components/node/NodeBottomBlock/index.tsx @@ -2,16 +2,16 @@ import React, { FC } from 'react'; import { NodeDeletedBadge } from '~/components/node/NodeDeletedBadge'; import { Group } from '~/components/containers/Group'; import { Padder } from '~/components/containers/Padder'; -import styles from '~/containers/node/NodeLayout/styles.module.scss'; import { NodeCommentsBlock } from '~/components/node/NodeCommentsBlock'; import { NodeCommentForm } from '~/components/node/NodeCommentForm'; -import { Sticky } from '~/components/containers/Sticky'; import { NodeRelatedBlock } from '~/components/node/NodeRelatedBlock'; import { useNodeBlocks } from '~/utils/hooks/node/useNodeBlocks'; import { IComment, INode } from '~/redux/types'; import { useUser } from '~/utils/hooks/user/userUser'; import { NodeTagsBlock } from '~/components/node/NodeTagsBlock'; import { INodeRelated } from '~/redux/node/types'; +import StickyBox from 'react-sticky-box/dist/esnext'; +import styles from './styles.module.scss'; interface IProps { node: INode; @@ -59,12 +59,12 @@ const NodeBottomBlock: FC = ({
- + - +
diff --git a/src/components/node/NodeBottomBlock/styles.module.scss b/src/components/node/NodeBottomBlock/styles.module.scss new file mode 100644 index 00000000..a34d0d9b --- /dev/null +++ b/src/components/node/NodeBottomBlock/styles.module.scss @@ -0,0 +1,48 @@ +@import "~/styles/variables.scss"; + +.sticky { + width: 100%; +} + +.content { + align-items: stretch !important; + @include vertical_at_tablet; +} + +.comments { + flex: 3 1; + min-width: 0; + display: flex; + align-items: stretch; + justify-content: flex-start; + flex-direction: column; + + @media (max-width: 1024px) { + flex: 2 1; + } +} + + +.panel { + flex: 1 3; + display: flex; + align-items: flex-start; + justify-content: flex-start; + padding-left: $gap / 2; + min-width: 0; + position: relative; + z-index: 10; + + @media (max-width: 1024px) { + padding-left: 0; + padding-top: $comment_height / 2; + flex: 1 2; + } +} + +.buttons { + background: $node_buttons_bg; + flex: 1; + border-radius: $panel_radius; + box-shadow: $comment_shadow; +} diff --git a/src/components/node/NodeImageSwiperBlock/index.tsx b/src/components/node/NodeImageSwiperBlock/index.tsx index da2b51f7..75ff0291 100644 --- a/src/components/node/NodeImageSwiperBlock/index.tsx +++ b/src/components/node/NodeImageSwiperBlock/index.tsx @@ -75,6 +75,7 @@ const NodeImageSwiperBlock: FC = ({ node }) => { observeParents resizeObserver watchOverflow + updateOnImagesReady onInit={resetSwiper} zoom > diff --git a/src/containers/main/Container/styles.module.scss b/src/containers/main/Container/styles.module.scss index cbf85b78..736fa115 100644 --- a/src/containers/main/Container/styles.module.scss +++ b/src/containers/main/Container/styles.module.scss @@ -9,4 +9,8 @@ @include tablet { padding: 0; } + + @media (max-width: $content_width + $gap * 4) { + padding: 0; + } } From 9e87e1eb3e881aebb726b87384e1088c297018f0 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Tue, 9 Mar 2021 13:45:23 +0700 Subject: [PATCH 05/37] updated deps --- package.json | 3 ++- yarn.lock | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index ddd058ae..5ca469e5 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "react-router-dom": "^5.1.2", "react-scripts": "3.4.4", "react-sortable-hoc": "^1.11", + "react-sticky-box": "^0.9.3", "redux": "^4.0.1", "redux-persist": "^5.10.0", "redux-saga": "^1.1.1", @@ -71,8 +72,8 @@ "@types/node": "^11.13.22", "@types/ramda": "^0.26.33", "@types/react-redux": "^7.1.11", - "@types/yup": "^0.29.11", "@types/swiper": "^5.4.2", + "@types/yup": "^0.29.11", "craco-alias": "^2.1.1", "craco-fast-refresh": "^1.0.2", "prettier": "^1.18.2" diff --git a/yarn.lock b/yarn.lock index f0c085db..fe6bc4cc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1109,6 +1109,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.1.5": + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.10.tgz#47d42a57b6095f4468da440388fdbad8bebf0d7d" + integrity sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/runtime@^7.10.5": version "7.13.7" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.7.tgz#d494e39d198ee9ca04f4dcb76d25d9d7a1dc961a" @@ -9454,6 +9461,14 @@ react-sortable-hoc@^1.11: invariant "^2.2.4" prop-types "^15.5.7" +react-sticky-box@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/react-sticky-box/-/react-sticky-box-0.9.3.tgz#8450d4cef8e4fdd7b0351520365bc98c97da11af" + integrity sha512-Y/qO7vTqAvXuRR6G6ZCW4fX2Bz0GZRwiiLTVeZN5CVz9wzs37ev0Xj3KSKF/PzF0jifwATivI4t24qXG8rSz4Q== + dependencies: + "@babel/runtime" "^7.1.5" + resize-observer-polyfill "^1.5.1" + react@^17.0.1: version "17.0.1" resolved "https://registry.yarnpkg.com/react/-/react-17.0.1.tgz#6e0600416bd57574e3f86d92edba3d9008726127" @@ -9780,6 +9795,11 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= +resize-observer-polyfill@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" + integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== + resize-sensor@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/resize-sensor/-/resize-sensor-0.0.6.tgz#75147dcb273de6832760e461d2e28de6dcf88c45" From dd46a3f0361074f7b535b28488888e5c6c25ccec Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Tue, 9 Mar 2021 13:52:49 +0700 Subject: [PATCH 06/37] fixed sticky at boris layout --- src/containers/node/BorisLayout/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/containers/node/BorisLayout/index.tsx b/src/containers/node/BorisLayout/index.tsx index 57127226..d2593ad4 100644 --- a/src/containers/node/BorisLayout/index.tsx +++ b/src/containers/node/BorisLayout/index.tsx @@ -12,7 +12,6 @@ import { NodeCommentForm } from '~/components/node/NodeCommentForm'; import isBefore from 'date-fns/isBefore'; import { Card } from '~/components/containers/Card'; import { Footer } from '~/components/main/Footer'; -import { Sticky } from '~/components/containers/Sticky'; import { BorisStats } from '~/components/boris/BorisStats'; import { useShallowSelect } from '~/utils/hooks/useShallowSelect'; import { selectBorisStats } from '~/redux/boris/selectors'; @@ -20,6 +19,7 @@ import { authSetUser } from '~/redux/auth/actions'; import { nodeLoadNode } from '~/redux/node/actions'; import { borisLoadStats } from '~/redux/boris/actions'; import { Container } from '~/containers/main/Container'; +import StickyBox from 'react-sticky-box/dist/esnext'; type IProps = {}; @@ -89,7 +89,7 @@ const BorisLayout: FC = () => { - +

Господи-боженьки, где это я?

@@ -106,7 +106,7 @@ const BorisLayout: FC = () => {
-
+
From ebdb09a611fdbd4a5830d4d416e3dfee5c816510 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Tue, 9 Mar 2021 15:19:40 +0700 Subject: [PATCH 07/37] fixed comment buttons mobile appearance --- src/components/comment/CommentForm/index.tsx | 54 ++++++++++--------- .../comment/CommentForm/styles.module.scss | 33 +++++++++++- .../styles.module.scss | 7 +-- 3 files changed, 63 insertions(+), 31 deletions(-) diff --git a/src/components/comment/CommentForm/index.tsx b/src/components/comment/CommentForm/index.tsx index b644509d..6fbdea56 100644 --- a/src/components/comment/CommentForm/index.tsx +++ b/src/components/comment/CommentForm/index.tsx @@ -65,34 +65,40 @@ const CommentForm: FC = ({ comment, nodeId, onCancelEdit }) => { - - +
+
+ +
- {!!textarea && ( - - )} +
+ {!!textarea && ( + + )} +
- {isLoading && } +
+ {isLoading && } - {isEditing && ( - + )} + + - )} - - - +
+
diff --git a/src/components/comment/CommentForm/styles.module.scss b/src/components/comment/CommentForm/styles.module.scss index 12798bf2..fb629c05 100644 --- a/src/components/comment/CommentForm/styles.module.scss +++ b/src/components/comment/CommentForm/styles.module.scss @@ -21,13 +21,42 @@ position: relative; z-index: 1; - display: flex; - flex-direction: row; + display: grid; background: transparentize(black, 0.8); padding: $gap / 2; border-radius: 0 0 $radius $radius; flex-wrap: wrap; + column-gap: $gap; + grid-template-columns: auto 1fr auto; + grid-template-rows: 1fr; + grid-template-areas: "attach format submit"; + @media(max-width: 470px) { + padding: $gap; + grid-template-columns: 1fr auto; + grid-template-rows: 1fr 1fr; + grid-template-areas: + "attach format" + "submit submit"; + row-gap: $gap; + } + + &_attach { + grid-area: attach; + } + + &_format { + grid-area: format; + } + + &_submit { + grid-area: submit; + display: grid; + grid-auto-flow: column; + align-items: flex-end; + justify-content: flex-end; + column-gap: $gap / 2; + } } .uploads { diff --git a/src/components/comment/CommentFormFormatButtons/styles.module.scss b/src/components/comment/CommentFormFormatButtons/styles.module.scss index e63a68c1..d07205e9 100644 --- a/src/components/comment/CommentFormFormatButtons/styles.module.scss +++ b/src/components/comment/CommentFormFormatButtons/styles.module.scss @@ -2,11 +2,8 @@ .wrap { display: flex; - flex-wrap: wrap; + flex-wrap: nowrap; height: 32px; flex: 1; - - @media(max-width: 480px) { - display: none; - } + width: 100%; } From 807b43cd1e22def973a7cb79d2d962cb4a92d1e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Mar 2021 22:50:28 +0000 Subject: [PATCH 08/37] Bump elliptic from 6.5.3 to 6.5.4 Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.3 to 6.5.4. - [Release notes](https://github.com/indutny/elliptic/releases) - [Commits](https://github.com/indutny/elliptic/compare/v6.5.3...v6.5.4) Signed-off-by: dependabot[bot] --- yarn.lock | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/yarn.lock b/yarn.lock index fe6bc4cc..a3992a4e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2644,10 +2644,10 @@ bluebird@^3.5.5: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.4.0: - version "4.11.9" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" - integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== bn.js@^5.0.0, bn.js@^5.1.1: version "5.1.3" @@ -2723,7 +2723,7 @@ braces@~3.0.2: dependencies: fill-range "^7.0.1" -brorand@^1.0.1: +brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= @@ -4207,17 +4207,17 @@ electron-to-chromium@^1.3.378, electron-to-chromium@^1.3.591: integrity sha512-ctRyXD9y0mZu8pgeNwBUhLP3Guyr5YuqkfLKYmpTwYx7o9JtCEJme9JVX4xBXPr5ZNvr/iBXUvHLFEVJQThATg== elliptic@^6.5.3: - version "6.5.3" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6" - integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw== + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" + bn.js "^4.11.9" + brorand "^1.1.0" hash.js "^1.0.0" - hmac-drbg "^1.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" emoji-regex@^7.0.1, emoji-regex@^7.0.2: version "7.0.3" @@ -5476,7 +5476,7 @@ history@^4.9.0: tiny-warning "^1.0.0" value-equal "^1.0.1" -hmac-drbg@^1.0.0: +hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= @@ -7373,7 +7373,7 @@ minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: +minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= From de1065f7b275ed8befa6bc32ac37d924efe7c18c Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Wed, 10 Mar 2021 10:58:20 +0700 Subject: [PATCH 09/37] added image upload on paste to comment form --- src/components/comment/CommentForm/index.tsx | 3 +- src/utils/hooks/useInputPasteUpload.ts | 24 ++++++++++++++ src/utils/uploader.ts | 34 ++++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/utils/hooks/useInputPasteUpload.ts diff --git a/src/components/comment/CommentForm/index.tsx b/src/components/comment/CommentForm/index.tsx index 6fbdea56..d1a9337e 100644 --- a/src/components/comment/CommentForm/index.tsx +++ b/src/components/comment/CommentForm/index.tsx @@ -14,7 +14,7 @@ import { EMPTY_COMMENT } from '~/redux/node/constants'; import { CommentFormDropzone } from '~/components/comment/CommentFormDropzone'; import styles from './styles.module.scss'; import { ERROR_LITERAL } from '~/constants/errors'; -import { Group } from '~/components/containers/Group'; +import { useInputPasteUpload } from '~/utils/hooks/useInputPasteUpload'; interface IProps { comment?: IComment; @@ -47,6 +47,7 @@ const CommentForm: FC = ({ comment, nodeId, onCancelEdit }) => { }, [formik]); const error = formik.status || formik.errors.text; + useInputPasteUpload(textarea, uploader.uploadFiles); return ( diff --git a/src/utils/hooks/useInputPasteUpload.ts b/src/utils/hooks/useInputPasteUpload.ts new file mode 100644 index 00000000..dff574a1 --- /dev/null +++ b/src/utils/hooks/useInputPasteUpload.ts @@ -0,0 +1,24 @@ +import { useCallback, useEffect } from 'react'; +import { getImageFromPaste } from '~/utils/uploader'; + +// useInputPasteUpload attaches event listener to input, that calls onUpload if user pasted any image +export const useInputPasteUpload = ( + input: HTMLTextAreaElement | HTMLInputElement | undefined, + onUpload: (files: File[]) => void +) => { + const onPaste = useCallback(async event => { + const image = await getImageFromPaste(event); + + if (!image) return; + + onUpload([image]); + }, []); + + useEffect(() => { + if (!input) return; + + input.addEventListener('paste', onPaste); + + return () => input.removeEventListener('paste', onPaste); + }, [input, onPaste]); +}; diff --git a/src/utils/uploader.ts b/src/utils/uploader.ts index c1ad5941..3ade4cf8 100644 --- a/src/utils/uploader.ts +++ b/src/utils/uploader.ts @@ -74,3 +74,37 @@ export const fakeUploader = ({ export const getFileType = (file: File): keyof typeof UPLOAD_TYPES | undefined => (file.type && Object.keys(FILE_MIMES).find(mime => FILE_MIMES[mime].includes(file.type))) || undefined; + +// getImageFromPaste returns any images from paste event +export const getImageFromPaste = (event: ClipboardEvent): Promise => { + const items = event.clipboardData?.items; + + return new Promise(resolve => { + for (let index in items) { + const item = items[index]; + + if (item.kind === 'file' && item.type.match(/^image\//)) { + const blob = item.getAsFile(); + const reader = new FileReader(); + const type = item.type; + + reader.onload = function(e) { + if (!e.target?.result) { + return; + } + + resolve( + new File([e.target?.result], 'paste.png', { + type, + lastModified: new Date().getTime(), + }) + ); + }; + + reader.readAsArrayBuffer(blob); + } + } + + // resolve(undefined); + }); +}; From 596eb03f98ac218b24d5c0a6fba75fb535612c45 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Wed, 10 Mar 2021 12:46:40 +0700 Subject: [PATCH 10/37] disabled devtools at prod --- src/redux/store.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/redux/store.ts b/src/redux/store.ts index eb9c60ff..ea16f709 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -75,7 +75,9 @@ export const sagaMiddleware = createSagaMiddleware(); export const history = createBrowserHistory(); const composeEnhancers = - typeof window === 'object' && (window).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ + typeof window === 'object' && + (window).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ && + process.env.NODE_ENV === 'development' ? (window).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose; From 29ffeb6b4850806d3fda47d215e8cc96d9ff04c2 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Wed, 10 Mar 2021 14:47:04 +0700 Subject: [PATCH 11/37] #25 getting github issues as tasks --- src/components/boris/BorisStatsGit/index.tsx | 11 ++++---- .../boris/BorisStatsGitCard/index.tsx | 25 +++++++++++++------ .../BorisStatsGitCard/styles.module.scss | 20 ++++++++++++++- src/redux/boris/api.ts | 14 +++++++++-- src/redux/boris/reducer.ts | 3 +++ src/redux/boris/sagas.ts | 8 +++--- src/redux/boris/types.ts | 12 +++++++++ 7 files changed, 74 insertions(+), 19 deletions(-) create mode 100644 src/redux/boris/types.ts diff --git a/src/components/boris/BorisStatsGit/index.tsx b/src/components/boris/BorisStatsGit/index.tsx index d81ac721..6557869c 100644 --- a/src/components/boris/BorisStatsGit/index.tsx +++ b/src/components/boris/BorisStatsGit/index.tsx @@ -9,7 +9,7 @@ interface IProps { } const BorisStatsGit: FC = ({ stats }) => { - if (!stats.git.length) return null; + if (!stats.issues.length) return null; if (stats.is_loading) { return ( @@ -35,11 +35,12 @@ const BorisStatsGit: FC = ({ stats }) => { - {stats.git - .filter(data => data.commit && data.timestamp && data.subject) - .slice(0, 5) + {stats.issues + .filter(el => !el.pull_request) + .slice(0, 10) + .sort(el => (el.state === 'open' ? 1 : -1)) .map(data => ( - + ))} ); diff --git a/src/components/boris/BorisStatsGitCard/index.tsx b/src/components/boris/BorisStatsGitCard/index.tsx index f393b710..20f4d469 100644 --- a/src/components/boris/BorisStatsGitCard/index.tsx +++ b/src/components/boris/BorisStatsGitCard/index.tsx @@ -1,22 +1,33 @@ -import React, { FC } from 'react'; -import { IStatGitRow } from '~/redux/boris/reducer'; +import React, { FC, useMemo } from 'react'; import styles from './styles.module.scss'; import { getPrettyDate } from '~/utils/dom'; +import { IGithubIssue } from '~/redux/boris/types'; +import classNames from 'classnames'; interface IProps { - data: Partial; + data: IGithubIssue; } -const BorisStatsGitCard: FC = ({ data: { timestamp, subject } }) => { - if (!subject || !timestamp) return null; +const stateLabels: Record = { + open: 'Ожидает', + closed: 'Сделано', +}; + +const BorisStatsGitCard: FC = ({ data: { created_at, title, html_url, state } }) => { + if (!title || !created_at) return null; + + const date = useMemo(() => getPrettyDate(created_at), [created_at]); return (
- {getPrettyDate(new Date(parseInt(`${timestamp}000`)).toISOString())} + {stateLabels[state]} + {date}
-
{subject}
+ + {title} +
); }; diff --git a/src/components/boris/BorisStatsGitCard/styles.module.scss b/src/components/boris/BorisStatsGitCard/styles.module.scss index 37bd0b23..eaad031a 100644 --- a/src/components/boris/BorisStatsGitCard/styles.module.scss +++ b/src/components/boris/BorisStatsGitCard/styles.module.scss @@ -12,10 +12,28 @@ .time { font: $font_12_regular; line-height: 17px; - opacity: 0.3; + color: transparentize(white, 0.7) } .subject { font: $font_14_regular; word-break: break-word; + text-decoration: none; + color: inherit; +} + +.icon { + font: $font_10_semibold; + margin-right: 5px; + border-radius: 2px; + padding: 2px 0; + text-transform: uppercase; + + &.open { + color: $red; + } + + &.closed { + color: $green; + } } diff --git a/src/redux/boris/api.ts b/src/redux/boris/api.ts index c1bd5a72..d8cc8867 100644 --- a/src/redux/boris/api.ts +++ b/src/redux/boris/api.ts @@ -1,10 +1,20 @@ import git from '~/stats/git.json'; import { API } from '~/constants/api'; -import { api, resultMiddleware, errorMiddleware, cleanResult } from '~/utils/api'; +import { api, cleanResult } from '~/utils/api'; import { IBorisState, IStatBackend } from './reducer'; -import { IResultWithStatus } from '../types'; +import axios from 'axios'; +import { IGetGithubIssuesResult } from '~/redux/boris/types'; export const getBorisGitStats = () => Promise.resolve(git); export const getBorisBackendStats = () => api.get(API.BORIS.GET_BACKEND_STATS).then(cleanResult); + +export const getGithubIssues = () => { + return axios + .get('https://api.github.com/repos/muerwre/vault-frontend/issues', { + params: { state: 'all', sort: 'created' }, + }) + .then(result => result.data) + .catch(() => []); +}; diff --git a/src/redux/boris/reducer.ts b/src/redux/boris/reducer.ts index 2032c793..5e182674 100644 --- a/src/redux/boris/reducer.ts +++ b/src/redux/boris/reducer.ts @@ -1,5 +1,6 @@ import { createReducer } from '~/utils/reducer'; import { BORIS_HANDLERS } from './handlers'; +import { IGithubIssue } from '~/redux/boris/types'; export type IStatGitRow = { commit: string; @@ -31,6 +32,7 @@ export type IStatBackend = { export type IBorisState = Readonly<{ stats: { git: Partial[]; + issues: IGithubIssue[]; backend?: IStatBackend; is_loading: boolean; }; @@ -39,6 +41,7 @@ export type IBorisState = Readonly<{ const BORIS_INITIAL_STATE: IBorisState = { stats: { git: [], + issues: [], backend: undefined, is_loading: false, }, diff --git a/src/redux/boris/sagas.ts b/src/redux/boris/sagas.ts index a0b1d003..b17e2c16 100644 --- a/src/redux/boris/sagas.ts +++ b/src/redux/boris/sagas.ts @@ -1,17 +1,17 @@ -import { takeLatest, put, call } from 'redux-saga/effects'; +import { call, put, takeLatest } from 'redux-saga/effects'; import { BORIS_ACTIONS } from './constants'; import { borisSetStats } from './actions'; -import { getBorisGitStats, getBorisBackendStats } from './api'; +import { getBorisBackendStats, getGithubIssues } from './api'; import { Unwrap } from '../types'; function* loadStats() { try { yield put(borisSetStats({ is_loading: true })); - const git: Unwrap = yield call(getBorisGitStats); const backend: Unwrap = yield call(getBorisBackendStats); + const issues: Unwrap = yield call(getGithubIssues); - yield put(borisSetStats({ git, backend })); + yield put(borisSetStats({ issues, backend })); } catch (e) { yield put(borisSetStats({ git: [], backend: undefined })); } finally { diff --git a/src/redux/boris/types.ts b/src/redux/boris/types.ts new file mode 100644 index 00000000..73552b25 --- /dev/null +++ b/src/redux/boris/types.ts @@ -0,0 +1,12 @@ +export interface IGithubIssue { + id: string; + url: string; + html_url: string; + body: string; + title: string; + state: 'open' | 'closed'; + created_at: string; + pull_request?: unknown; +} + +export type IGetGithubIssuesResult = IGithubIssue[]; From bb6c853d3c69e513c9d7cb2157e7841799516e17 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Wed, 10 Mar 2021 16:09:48 +0700 Subject: [PATCH 12/37] #25 removed issues sort --- src/components/boris/BorisStatsGit/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/boris/BorisStatsGit/index.tsx b/src/components/boris/BorisStatsGit/index.tsx index 6557869c..b8049034 100644 --- a/src/components/boris/BorisStatsGit/index.tsx +++ b/src/components/boris/BorisStatsGit/index.tsx @@ -38,7 +38,6 @@ const BorisStatsGit: FC = ({ stats }) => { {stats.issues .filter(el => !el.pull_request) .slice(0, 10) - .sort(el => (el.state === 'open' ? 1 : -1)) .map(data => ( ))} From 054f3041c4782c1e823c4ede157e4f440b136f64 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Wed, 10 Mar 2021 16:11:49 +0700 Subject: [PATCH 13/37] #25 groupping issues by type --- src/components/boris/BorisStatsGit/index.tsx | 25 ++++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/components/boris/BorisStatsGit/index.tsx b/src/components/boris/BorisStatsGit/index.tsx index b8049034..7ad88808 100644 --- a/src/components/boris/BorisStatsGit/index.tsx +++ b/src/components/boris/BorisStatsGit/index.tsx @@ -1,4 +1,4 @@ -import React, { FC } from 'react'; +import React, { FC, useMemo } from 'react'; import { IBorisState } from '~/redux/boris/reducer'; import styles from './styles.module.scss'; import { Placeholder } from '~/components/placeholders/Placeholder'; @@ -11,6 +11,16 @@ interface IProps { const BorisStatsGit: FC = ({ stats }) => { if (!stats.issues.length) return null; + const open = useMemo( + () => stats.issues.filter(el => !el.pull_request && el.state === 'open').slice(0, 5), + [stats.issues] + ); + + const closed = useMemo( + () => stats.issues.filter(el => !el.pull_request && el.state === 'closed').slice(0, 5), + [stats.issues] + ); + if (stats.is_loading) { return ( <> @@ -35,12 +45,13 @@ const BorisStatsGit: FC = ({ stats }) => { - {stats.issues - .filter(el => !el.pull_request) - .slice(0, 10) - .map(data => ( - - ))} + {closed.map(data => ( + + ))} + + {open.map(data => ( + + ))} ); }; From 69530a84081f4797d102608f502765a0b6b12e21 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Thu, 11 Mar 2021 10:03:02 +0700 Subject: [PATCH 14/37] #47 fixed youtube embed urls --- src/components/comment/CommentEmbedBlock/index.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/comment/CommentEmbedBlock/index.tsx b/src/components/comment/CommentEmbedBlock/index.tsx index 77a374d2..e07b7ecf 100644 --- a/src/components/comment/CommentEmbedBlock/index.tsx +++ b/src/components/comment/CommentEmbedBlock/index.tsx @@ -30,6 +30,8 @@ const CommentEmbedBlockUnconnected: FC = memo( return (match && match[1]) || ''; }, [block.content]); + const url = useMemo(() => `https://youtube.com/watch?v=${id}`, [id]); + const preview = useMemo(() => getYoutubeThumb(block.content), [block.content]); useEffect(() => { @@ -47,7 +49,7 @@ const CommentEmbedBlockUnconnected: FC = memo( return (
- +
From 5de7064e2b858da642a918af9f68771815f90f48 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Thu, 11 Mar 2021 10:09:35 +0700 Subject: [PATCH 15/37] fixed paddings on last paragraph --- src/styles/common/markdown.module.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/styles/common/markdown.module.scss b/src/styles/common/markdown.module.scss index 9cfcb7e1..82cb22a5 100644 --- a/src/styles/common/markdown.module.scss +++ b/src/styles/common/markdown.module.scss @@ -55,6 +55,10 @@ $margin: 1em; p { margin-bottom: $margin; + + &:last-child { + margin-bottom: 0; + } } h5, h4, h3, h2, h1 { From fc5098054f81d5db4fe589ae1201f5e7f00aaf05 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Thu, 11 Mar 2021 10:10:16 +0700 Subject: [PATCH 16/37] fixed order of the git stats --- src/components/boris/BorisStatsGit/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/boris/BorisStatsGit/index.tsx b/src/components/boris/BorisStatsGit/index.tsx index 7ad88808..030699a3 100644 --- a/src/components/boris/BorisStatsGit/index.tsx +++ b/src/components/boris/BorisStatsGit/index.tsx @@ -45,11 +45,11 @@ const BorisStatsGit: FC = ({ stats }) => {
- {closed.map(data => ( + {open.map(data => ( ))} - {open.map(data => ( + {closed.map(data => ( ))}
From 46506f35413919dfe5dd8395f4a7d0d71e6f2393 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Thu, 11 Mar 2021 13:53:52 +0700 Subject: [PATCH 17/37] fixed loading more nodes for tag --- src/redux/tag/sagas.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/redux/tag/sagas.ts b/src/redux/tag/sagas.ts index eb1c3f16..90c5cf1f 100644 --- a/src/redux/tag/sagas.ts +++ b/src/redux/tag/sagas.ts @@ -11,7 +11,7 @@ import { apiGetTagSuggestions, apiGetNodesOfTag } from '~/redux/tag/api'; import { Unwrap } from '~/redux/types'; function* loadTagNodes({ tag }: ReturnType) { - yield put(tagSetNodes({ isLoading: true, list: [] })); + yield put(tagSetNodes({ isLoading: true })); try { const { list }: ReturnType = yield select(selectTagNodes); From c5288e0f8099724e68e9dbd3fab32678ed3e7178 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Fri, 12 Mar 2021 10:09:56 +0700 Subject: [PATCH 18/37] added arrow navigation for swiper --- src/components/flow/FlowRecent/index.tsx | 1 - src/components/node/NodeImageSwiperBlock/index.tsx | 10 ++++++++-- .../node/NodeImageSwiperBlock/styles.module.scss | 11 +++++++++++ src/containers/node/NodeLayout/index.tsx | 4 ++-- src/containers/node/NodeLayout/styles.module.scss | 2 ++ 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/components/flow/FlowRecent/index.tsx b/src/components/flow/FlowRecent/index.tsx index 79bae2d4..53ac700e 100644 --- a/src/components/flow/FlowRecent/index.tsx +++ b/src/components/flow/FlowRecent/index.tsx @@ -11,7 +11,6 @@ const FlowRecent: FC = ({ recent, updated }) => { return ( <> {updated && updated.map(node => )} - {recent && recent.map(node => )} ); diff --git a/src/components/node/NodeImageSwiperBlock/index.tsx b/src/components/node/NodeImageSwiperBlock/index.tsx index 75ff0291..417ae430 100644 --- a/src/components/node/NodeImageSwiperBlock/index.tsx +++ b/src/components/node/NodeImageSwiperBlock/index.tsx @@ -1,12 +1,13 @@ import React, { FC, useCallback, useEffect, useState } from 'react'; import { INodeComponentProps } from '~/redux/node/constants'; -import SwiperCore, { A11y, Pagination, SwiperOptions } from 'swiper'; +import SwiperCore, { A11y, Pagination, Navigation, SwiperOptions, Keyboard } from 'swiper'; import { Swiper, SwiperSlide } from 'swiper/react'; import 'swiper/swiper.scss'; import 'swiper/components/pagination/pagination.scss'; import 'swiper/components/scrollbar/scrollbar.scss'; import 'swiper/components/zoom/zoom.scss'; +import 'swiper/components/navigation/navigation.scss'; import styles from './styles.module.scss'; import { useNodeImages } from '~/utils/hooks/node/useNodeImages'; @@ -16,13 +17,14 @@ import SwiperClass from 'swiper/types/swiper-class'; import { modalShowPhotoswipe } from '~/redux/modal/actions'; import { useDispatch } from 'react-redux'; -SwiperCore.use([Pagination, A11y]); +SwiperCore.use([Navigation, Pagination, A11y]); interface IProps extends INodeComponentProps {} const breakpoints: SwiperOptions['breakpoints'] = { 599: { spaceBetween: 20, + navigation: true, }, }; @@ -77,6 +79,10 @@ const NodeImageSwiperBlock: FC = ({ node }) => { watchOverflow updateOnImagesReady onInit={resetSwiper} + keyboard={{ + enabled: true, + onlyInViewport: false, + }} zoom > {images.map(file => ( diff --git a/src/components/node/NodeImageSwiperBlock/styles.module.scss b/src/components/node/NodeImageSwiperBlock/styles.module.scss index 7766bfe5..6dd0a49b 100644 --- a/src/components/node/NodeImageSwiperBlock/styles.module.scss +++ b/src/components/node/NodeImageSwiperBlock/styles.module.scss @@ -20,6 +20,17 @@ :global(.swiper-container) { width: 100vw; } + + :global(.swiper-button-next), + :global(.swiper-button-prev) { + color: white; + font-size: 10px; + + &::after { + font-size: 32px; + } + } + } .slide { diff --git a/src/containers/node/NodeLayout/index.tsx b/src/containers/node/NodeLayout/index.tsx index 589b9072..35dd2cf2 100644 --- a/src/containers/node/NodeLayout/index.tsx +++ b/src/containers/node/NodeLayout/index.tsx @@ -40,7 +40,7 @@ const NodeLayout: FC = memo( const { head, block } = useNodeBlocks(current, is_loading); return ( - <> +
{head} @@ -64,7 +64,7 @@ const NodeLayout: FC = memo( - +
); } ); diff --git a/src/containers/node/NodeLayout/styles.module.scss b/src/containers/node/NodeLayout/styles.module.scss index f799e1a4..9481da26 100644 --- a/src/containers/node/NodeLayout/styles.module.scss +++ b/src/containers/node/NodeLayout/styles.module.scss @@ -2,6 +2,8 @@ .content { align-items: stretch !important; + background-color: red; + @include vertical_at_tablet; } From cefc85bf8d82309a50f56d15a7c00cef1642183e Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Fri, 12 Mar 2021 10:12:00 +0700 Subject: [PATCH 19/37] removed color-reds --- src/components/containers/CommentWrapper/styles.module.scss | 1 - src/components/input/Button/styles.module.scss | 1 - src/containers/node/NodeLayout/styles.module.scss | 1 - 3 files changed, 3 deletions(-) diff --git a/src/components/containers/CommentWrapper/styles.module.scss b/src/components/containers/CommentWrapper/styles.module.scss index c1f36ae5..6587b197 100644 --- a/src/components/containers/CommentWrapper/styles.module.scss +++ b/src/components/containers/CommentWrapper/styles.module.scss @@ -33,7 +33,6 @@ @include tablet { :global(.comment-author) { display: none !important; - color: red; } } } diff --git a/src/components/input/Button/styles.module.scss b/src/components/input/Button/styles.module.scss index 676bb62d..584600ca 100644 --- a/src/components/input/Button/styles.module.scss +++ b/src/components/input/Button/styles.module.scss @@ -44,7 +44,6 @@ @include outer_shadow(); input { - color: red; position: absolute; top: 0; left: 0; diff --git a/src/containers/node/NodeLayout/styles.module.scss b/src/containers/node/NodeLayout/styles.module.scss index 9481da26..0a824c0d 100644 --- a/src/containers/node/NodeLayout/styles.module.scss +++ b/src/containers/node/NodeLayout/styles.module.scss @@ -2,7 +2,6 @@ .content { align-items: stretch !important; - background-color: red; @include vertical_at_tablet; } From 18ec220a4e508a2bf67fdd076b8b6c15aee0fc7b Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Fri, 12 Mar 2021 12:04:10 +0700 Subject: [PATCH 20/37] #23 added labs layout --- src/components/containers/Sticky/index.tsx | 45 ++++--------------- .../containers/Sticky/styles.module.scss | 17 ------- src/components/main/Header/index.tsx | 14 ++++-- src/components/node/NodeAudioBlock/index.tsx | 6 +-- .../node/NodeAudioImageBlock/index.tsx | 6 +-- src/constants/urls.ts | 1 + src/containers/lab/LabGrid/index.tsx | 21 +++++++++ src/containers/lab/LabGrid/styles.module.scss | 8 ++++ src/containers/lab/LabLayout/index.tsx | 27 +++++++++++ .../lab/LabLayout/styles.module.scss | 11 +++++ src/containers/lab/LabNode/index.tsx | 34 ++++++++++++++ src/containers/main/MainRouter/index.tsx | 2 + src/utils/hooks/node/useNodeAudios.ts | 4 ++ src/utils/hooks/node/useNodeImages.ts | 4 ++ 14 files changed, 135 insertions(+), 65 deletions(-) delete mode 100644 src/components/containers/Sticky/styles.module.scss create mode 100644 src/containers/lab/LabGrid/index.tsx create mode 100644 src/containers/lab/LabGrid/styles.module.scss create mode 100644 src/containers/lab/LabLayout/index.tsx create mode 100644 src/containers/lab/LabLayout/styles.module.scss create mode 100644 src/containers/lab/LabNode/index.tsx diff --git a/src/components/containers/Sticky/index.tsx b/src/components/containers/Sticky/index.tsx index dfeda268..55288c87 100644 --- a/src/components/containers/Sticky/index.tsx +++ b/src/components/containers/Sticky/index.tsx @@ -1,42 +1,15 @@ -import React, { DetailsHTMLAttributes, FC, useEffect, useRef } from 'react'; -import styles from './styles.module.scss'; +import React, { DetailsHTMLAttributes, FC } from 'react'; +import StickyBox from 'react-sticky-box/dist/esnext'; -import ResizeSensor from 'resize-sensor'; -(window as any).ResizeSensor = ResizeSensor; - -import StickySidebar from 'sticky-sidebar'; -(window as any).StickySidebar = StickySidebar; - -import classnames from 'classnames'; - -interface IProps extends DetailsHTMLAttributes {} - -const Sticky: FC = ({ children }) => { - const ref = useRef(null); - const sb = useRef(null); - - useEffect(() => { - if (!ref.current) return; - - sb.current = new StickySidebar(ref.current, { - resizeSensor: true, - topSpacing: 72, - bottomSpacing: 10, - }); - - return () => sb.current?.destroy(); - }, [ref.current, sb.current, children]); - - if (sb) { - sb.current?.updateSticky(); - } +interface IProps extends DetailsHTMLAttributes { + offsetTop?: number; +} +const Sticky: FC = ({ children, offsetTop = 65 }) => { return ( -
-
-
{children}
-
-
+ + {children} + ); }; diff --git a/src/components/containers/Sticky/styles.module.scss b/src/components/containers/Sticky/styles.module.scss deleted file mode 100644 index eb680535..00000000 --- a/src/components/containers/Sticky/styles.module.scss +++ /dev/null @@ -1,17 +0,0 @@ -@import "src/styles/variables"; - -.wrap { - height: 100%; - width: 100%; - position: relative; - - :global(.sidebar) { - will-change: min-height; - } - - :global(.sidebar__inner) { - transform: translate(0, 0); /* For browsers don't support translate3d. */ - transform: translate3d(0, 0, 0); - will-change: position, transform; - } -} diff --git a/src/components/main/Header/index.tsx b/src/components/main/Header/index.tsx index 43d7646c..69d0dee4 100644 --- a/src/components/main/Header/index.tsx +++ b/src/components/main/Header/index.tsx @@ -82,6 +82,15 @@ const HeaderUnconnected: FC = memo(
+ {is_user && ( + + ЛАБ + + )} + = memo( } ); -const Header = connect( - mapStateToProps, - mapDispatchToProps -)(HeaderUnconnected); +const Header = connect(mapStateToProps, mapDispatchToProps)(HeaderUnconnected); export { Header }; diff --git a/src/components/node/NodeAudioBlock/index.tsx b/src/components/node/NodeAudioBlock/index.tsx index 9581a16b..c064e831 100644 --- a/src/components/node/NodeAudioBlock/index.tsx +++ b/src/components/node/NodeAudioBlock/index.tsx @@ -4,14 +4,12 @@ import { UPLOAD_TYPES } from '~/redux/uploads/constants'; import { AudioPlayer } from '~/components/media/AudioPlayer'; import styles from './styles.module.scss'; import { INodeComponentProps } from '~/redux/node/constants'; +import { useNodeAudios } from '~/utils/hooks/node/useNodeAudios'; interface IProps extends INodeComponentProps {} const NodeAudioBlock: FC = ({ node }) => { - const audios = useMemo( - () => node.files.filter(file => file && file.type === UPLOAD_TYPES.AUDIO), - [node.files] - ); + const audios = useNodeAudios(node); return (
diff --git a/src/components/node/NodeAudioImageBlock/index.tsx b/src/components/node/NodeAudioImageBlock/index.tsx index ca848b3f..e7834737 100644 --- a/src/components/node/NodeAudioImageBlock/index.tsx +++ b/src/components/node/NodeAudioImageBlock/index.tsx @@ -6,14 +6,12 @@ import { path } from 'ramda'; import { getURL } from '~/utils/dom'; import { PRESETS } from '~/constants/urls'; import { INodeComponentProps } from '~/redux/node/constants'; +import { useNodeImages } from '~/utils/hooks/node/useNodeImages'; interface IProps extends INodeComponentProps {} const NodeAudioImageBlock: FC = ({ node }) => { - const images = useMemo( - () => node.files.filter(file => file && file.type === UPLOAD_TYPES.IMAGE), - [node.files] - ); + const images = useNodeImages(node); if (images.length === 0) return null; diff --git a/src/constants/urls.ts b/src/constants/urls.ts index 67eb4a39..527e072e 100644 --- a/src/constants/urls.ts +++ b/src/constants/urls.ts @@ -2,6 +2,7 @@ import { INode } from '~/redux/types'; export const URLS = { BASE: '/', + LAB: '/lab', BORIS: '/boris', AUTH: { LOGIN: '/auth/login', diff --git a/src/containers/lab/LabGrid/index.tsx b/src/containers/lab/LabGrid/index.tsx new file mode 100644 index 00000000..1caa8381 --- /dev/null +++ b/src/containers/lab/LabGrid/index.tsx @@ -0,0 +1,21 @@ +import React, { FC } from 'react'; +import { useShallowSelect } from '~/utils/hooks/useShallowSelect'; +import { selectFlowNodes } from '~/redux/flow/selectors'; +import styles from './styles.module.scss'; +import { LabNode } from '~/containers/lab/LabNode'; + +interface IProps {} + +const LabGrid: FC = () => { + const nodes = useShallowSelect(selectFlowNodes); + + return ( +
+ {nodes.map(node => ( + + ))} +
+ ); +}; + +export { LabGrid }; diff --git a/src/containers/lab/LabGrid/styles.module.scss b/src/containers/lab/LabGrid/styles.module.scss new file mode 100644 index 00000000..3f42c360 --- /dev/null +++ b/src/containers/lab/LabGrid/styles.module.scss @@ -0,0 +1,8 @@ +@import "~/styles/variables.scss"; + +.wrap { + display: grid; + grid-auto-flow: row; + grid-auto-rows: auto; + grid-row-gap: $gap; +} diff --git a/src/containers/lab/LabLayout/index.tsx b/src/containers/lab/LabLayout/index.tsx new file mode 100644 index 00000000..47a77bcd --- /dev/null +++ b/src/containers/lab/LabLayout/index.tsx @@ -0,0 +1,27 @@ +import React, { FC } from 'react'; +import styles from './styles.module.scss'; +import { Card } from '~/components/containers/Card'; +import { Sticky } from '~/components/containers/Sticky'; +import { Container } from '~/containers/main/Container'; +import { LabGrid } from '~/containers/lab/LabGrid'; + +interface IProps {} + +const LabLayout: FC = () => ( +
+ +
+
+ +
+
+ + Test + +
+
+
+
+); + +export { LabLayout }; diff --git a/src/containers/lab/LabLayout/styles.module.scss b/src/containers/lab/LabLayout/styles.module.scss new file mode 100644 index 00000000..c204075d --- /dev/null +++ b/src/containers/lab/LabLayout/styles.module.scss @@ -0,0 +1,11 @@ +@import "~/styles/variables.scss"; + +.wrap { + display: grid; + grid-template-columns: 3fr 1fr; + column-gap: $gap; +} + +.panel { + margin-top: -7px; +} diff --git a/src/containers/lab/LabNode/index.tsx b/src/containers/lab/LabNode/index.tsx new file mode 100644 index 00000000..246a119b --- /dev/null +++ b/src/containers/lab/LabNode/index.tsx @@ -0,0 +1,34 @@ +import React, { FC } from 'react'; +import { INode } from '~/redux/types'; +import { NodePanelInner } from '~/components/node/NodePanelInner'; +import { useNodeBlocks } from '~/utils/hooks/node/useNodeBlocks'; + +interface IProps { + node: INode; +} + +const LabNode: FC = ({ node }) => { + const { inline, block, head } = useNodeBlocks(node, false); + + return ( +
+ + + {inline} + {block} + {head} +
+ ); +}; + +export { LabNode }; diff --git a/src/containers/main/MainRouter/index.tsx b/src/containers/main/MainRouter/index.tsx index bed1579a..b5a17270 100644 --- a/src/containers/main/MainRouter/index.tsx +++ b/src/containers/main/MainRouter/index.tsx @@ -6,6 +6,7 @@ import { BorisLayout } from '~/containers/node/BorisLayout'; import { ErrorNotFound } from '~/containers/pages/ErrorNotFound'; import { ProfilePage } from '~/containers/profile/ProfilePage'; import { Redirect, Route, Switch, useLocation } from 'react-router'; +import { LabLayout } from '~/containers/lab/LabLayout'; interface IProps {} @@ -15,6 +16,7 @@ const MainRouter: FC = () => { return ( + diff --git a/src/utils/hooks/node/useNodeAudios.ts b/src/utils/hooks/node/useNodeAudios.ts index 7ece487f..5dc043a1 100644 --- a/src/utils/hooks/node/useNodeAudios.ts +++ b/src/utils/hooks/node/useNodeAudios.ts @@ -3,6 +3,10 @@ import { useMemo } from 'react'; import { UPLOAD_TYPES } from '~/redux/uploads/constants'; export const useNodeAudios = (node: INode) => { + if (!node?.files) { + return []; + } + return useMemo(() => node.files.filter(file => file && file.type === UPLOAD_TYPES.AUDIO), [ node.files, ]); diff --git a/src/utils/hooks/node/useNodeImages.ts b/src/utils/hooks/node/useNodeImages.ts index 4f6b71d5..375d6198 100644 --- a/src/utils/hooks/node/useNodeImages.ts +++ b/src/utils/hooks/node/useNodeImages.ts @@ -3,6 +3,10 @@ import { useMemo } from 'react'; import { UPLOAD_TYPES } from '~/redux/uploads/constants'; export const useNodeImages = (node: INode) => { + if (!node?.files) { + return []; + } + return useMemo(() => node.files.filter(file => file && file.type === UPLOAD_TYPES.IMAGE), [ node.files, ]); From 3aa2d4f609e909556978bb2173f558fd88a70e10 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Fri, 12 Mar 2021 13:56:23 +0700 Subject: [PATCH 21/37] #23 added lab node layout (sample) --- .../node/NodePanelInner/styles.module.scss | 4 +- src/components/node/NodePanelLab/index.tsx | 19 +++++++++ .../node/NodePanelLab/styles.module.scss | 24 +++++++++++ src/constants/api.ts | 3 ++ src/containers/lab/LabGrid/index.tsx | 4 +- src/containers/lab/LabLayout/index.tsx | 42 ++++++++++++------- src/containers/lab/LabNode/index.tsx | 29 ++++++------- src/containers/lab/LabNode/styles.module.scss | 10 +++++ src/containers/main/MainRouter/index.tsx | 10 ++++- src/redux/lab/actions.ts | 12 ++++++ src/redux/lab/api.ts | 8 ++++ src/redux/lab/constants.ts | 6 +++ src/redux/lab/handlers.ts | 20 +++++++++ src/redux/lab/index.ts | 14 +++++++ src/redux/lab/sagas.ts | 21 ++++++++++ src/redux/lab/selectors.ts | 4 ++ src/redux/lab/types.ts | 19 +++++++++ src/redux/store.ts | 7 ++++ 18 files changed, 218 insertions(+), 38 deletions(-) create mode 100644 src/components/node/NodePanelLab/index.tsx create mode 100644 src/components/node/NodePanelLab/styles.module.scss create mode 100644 src/containers/lab/LabNode/styles.module.scss create mode 100644 src/redux/lab/actions.ts create mode 100644 src/redux/lab/api.ts create mode 100644 src/redux/lab/constants.ts create mode 100644 src/redux/lab/handlers.ts create mode 100644 src/redux/lab/index.ts create mode 100644 src/redux/lab/sagas.ts create mode 100644 src/redux/lab/selectors.ts create mode 100644 src/redux/lab/types.ts diff --git a/src/components/node/NodePanelInner/styles.module.scss b/src/components/node/NodePanelInner/styles.module.scss index 58d925fa..c9b9a94b 100644 --- a/src/components/node/NodePanelInner/styles.module.scss +++ b/src/components/node/NodePanelInner/styles.module.scss @@ -31,8 +31,6 @@ .wrap { display: flex; - align-items: center; - justify-content: stretch; position: relative; width: 100%; flex-direction: row; @@ -88,7 +86,7 @@ @include tablet { white-space: nowrap; padding-bottom: 0; - font: $font_20_semibold; + font: $font_16_semibold; } } diff --git a/src/components/node/NodePanelLab/index.tsx b/src/components/node/NodePanelLab/index.tsx new file mode 100644 index 00000000..c33714d4 --- /dev/null +++ b/src/components/node/NodePanelLab/index.tsx @@ -0,0 +1,19 @@ +import React, { FC } from 'react'; +import { INode } from '~/redux/types'; +import styles from './styles.module.scss'; +import { URLS } from '~/constants/urls'; +import { Link } from 'react-router-dom'; + +interface IProps { + node: INode; +} + +const NodePanelLab: FC = ({ node }) => ( +
+
+ {node.title || '...'} +
+
+); + +export { NodePanelLab }; diff --git a/src/components/node/NodePanelLab/styles.module.scss b/src/components/node/NodePanelLab/styles.module.scss new file mode 100644 index 00000000..095dafe5 --- /dev/null +++ b/src/components/node/NodePanelLab/styles.module.scss @@ -0,0 +1,24 @@ +@import "~/styles/variables.scss"; + +.wrap { + padding: $gap; +} + +.title { + text-transform: uppercase; + font: $font_24_semibold; + overflow: hidden; + flex: 1; + text-overflow: ellipsis; + + a { + text-decoration: none; + color: inherit; + } + + @include tablet { + white-space: nowrap; + padding-bottom: 0; + font: $font_16_semibold; + } +} diff --git a/src/constants/api.ts b/src/constants/api.ts index 6f57d689..c9c4c287 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -50,4 +50,7 @@ export const API = { NODES: `/tag/nodes`, AUTOCOMPLETE: `/tag/autocomplete`, }, + LAB: { + NODES: `/lab/`, + }, }; diff --git a/src/containers/lab/LabGrid/index.tsx b/src/containers/lab/LabGrid/index.tsx index 1caa8381..6dc04ef3 100644 --- a/src/containers/lab/LabGrid/index.tsx +++ b/src/containers/lab/LabGrid/index.tsx @@ -1,13 +1,13 @@ import React, { FC } from 'react'; import { useShallowSelect } from '~/utils/hooks/useShallowSelect'; -import { selectFlowNodes } from '~/redux/flow/selectors'; import styles from './styles.module.scss'; import { LabNode } from '~/containers/lab/LabNode'; +import { selectLabListNodes } from '~/redux/lab/selectors'; interface IProps {} const LabGrid: FC = () => { - const nodes = useShallowSelect(selectFlowNodes); + const nodes = useShallowSelect(selectLabListNodes); return (
diff --git a/src/containers/lab/LabLayout/index.tsx b/src/containers/lab/LabLayout/index.tsx index 47a77bcd..087a8546 100644 --- a/src/containers/lab/LabLayout/index.tsx +++ b/src/containers/lab/LabLayout/index.tsx @@ -1,27 +1,37 @@ -import React, { FC } from 'react'; +import React, { FC, useEffect } from 'react'; import styles from './styles.module.scss'; import { Card } from '~/components/containers/Card'; import { Sticky } from '~/components/containers/Sticky'; import { Container } from '~/containers/main/Container'; import { LabGrid } from '~/containers/lab/LabGrid'; +import { useDispatch } from 'react-redux'; +import { labGetList } from '~/redux/lab/actions'; interface IProps {} -const LabLayout: FC = () => ( -
- -
-
- +const LabLayout: FC = () => { + const dispatch = useDispatch(); + + useEffect(() => { + dispatch(labGetList()); + }, [dispatch]); + + return ( +
+ +
+
+ +
+
+ + Test + +
-
- - Test - -
-
- -
-); + +
+ ); +}; export { LabLayout }; diff --git a/src/containers/lab/LabNode/index.tsx b/src/containers/lab/LabNode/index.tsx index 246a119b..5f64c55f 100644 --- a/src/containers/lab/LabNode/index.tsx +++ b/src/containers/lab/LabNode/index.tsx @@ -2,6 +2,9 @@ import React, { FC } from 'react'; import { INode } from '~/redux/types'; import { NodePanelInner } from '~/components/node/NodePanelInner'; import { useNodeBlocks } from '~/utils/hooks/node/useNodeBlocks'; +import styles from './styles.module.scss'; +import { Card } from '~/components/containers/Card'; +import { NodePanelLab } from '~/components/node/NodePanelLab'; interface IProps { node: INode; @@ -10,24 +13,18 @@ interface IProps { const LabNode: FC = ({ node }) => { const { inline, block, head } = useNodeBlocks(node, false); - return ( -
- + console.log(node.id, { inline, block, head }); + + return ( + +
+ +
- {inline} - {block} {head} -
+ {block} + {inline} + ); }; diff --git a/src/containers/lab/LabNode/styles.module.scss b/src/containers/lab/LabNode/styles.module.scss new file mode 100644 index 00000000..8e002f2b --- /dev/null +++ b/src/containers/lab/LabNode/styles.module.scss @@ -0,0 +1,10 @@ +@import "~/styles/variables.scss"; + +.wrap { + min-width: 0; +} + +.head { + background-color: transparentize(black, 0.9); + border-radius: $radius $radius 0 0; +} diff --git a/src/containers/main/MainRouter/index.tsx b/src/containers/main/MainRouter/index.tsx index b5a17270..ac8988dc 100644 --- a/src/containers/main/MainRouter/index.tsx +++ b/src/containers/main/MainRouter/index.tsx @@ -7,21 +7,29 @@ import { ErrorNotFound } from '~/containers/pages/ErrorNotFound'; import { ProfilePage } from '~/containers/profile/ProfilePage'; import { Redirect, Route, Switch, useLocation } from 'react-router'; import { LabLayout } from '~/containers/lab/LabLayout'; +import { useShallowSelect } from '~/utils/hooks/useShallowSelect'; +import { selectAuthUser } from '~/redux/auth/selectors'; interface IProps {} const MainRouter: FC = () => { + const { is_user } = useShallowSelect(selectAuthUser); const location = useLocation(); return ( - + {is_user && ( + <> + + + )} + ); diff --git a/src/redux/lab/actions.ts b/src/redux/lab/actions.ts new file mode 100644 index 00000000..1e1ff97a --- /dev/null +++ b/src/redux/lab/actions.ts @@ -0,0 +1,12 @@ +import { LAB_ACTIONS } from '~/redux/lab/constants'; +import { ILabState } from '~/redux/lab/types'; + +export const labGetList = (after?: string) => ({ + type: LAB_ACTIONS.GET_LIST, + after, +}); + +export const labSetList = (list: Partial) => ({ + type: LAB_ACTIONS.SET_LIST, + list, +}); diff --git a/src/redux/lab/api.ts b/src/redux/lab/api.ts new file mode 100644 index 00000000..5fa97bc0 --- /dev/null +++ b/src/redux/lab/api.ts @@ -0,0 +1,8 @@ +import { api, cleanResult } from '~/utils/api'; +import { API } from '~/constants/api'; +import { GetLabNodesRequest, GetLabNodesResult } from '~/redux/lab/types'; + +export const getLabNodes = ({ after }: GetLabNodesRequest) => + api + .get(API.LAB.NODES, { params: { after } }) + .then(cleanResult); diff --git a/src/redux/lab/constants.ts b/src/redux/lab/constants.ts new file mode 100644 index 00000000..d2e670da --- /dev/null +++ b/src/redux/lab/constants.ts @@ -0,0 +1,6 @@ +const prefix = 'LAB.'; + +export const LAB_ACTIONS = { + GET_LIST: `${prefix}GET_LIST`, + SET_LIST: `${prefix}SET_LIST`, +}; diff --git a/src/redux/lab/handlers.ts b/src/redux/lab/handlers.ts new file mode 100644 index 00000000..b09812e2 --- /dev/null +++ b/src/redux/lab/handlers.ts @@ -0,0 +1,20 @@ +import { LAB_ACTIONS } from '~/redux/lab/constants'; +import { labSetList } from '~/redux/lab/actions'; +import { ILabState } from '~/redux/lab/types'; + +type LabHandler any> = ( + state: Readonly, + payload: ReturnType +) => Readonly; + +const setList: LabHandler = (state, { list }) => ({ + ...state, + list: { + ...state.list, + ...list, + }, +}); + +export const LAB_HANDLERS = { + [LAB_ACTIONS.SET_LIST]: setList, +}; diff --git a/src/redux/lab/index.ts b/src/redux/lab/index.ts new file mode 100644 index 00000000..56879a52 --- /dev/null +++ b/src/redux/lab/index.ts @@ -0,0 +1,14 @@ +import { createReducer } from '~/utils/reducer'; +import { LAB_HANDLERS } from '~/redux/lab/handlers'; +import { ILabState } from '~/redux/lab/types'; + +const INITIAL_STATE: ILabState = { + list: { + is_loading: false, + nodes: [], + count: 0, + error: '', + }, +}; + +export default createReducer(INITIAL_STATE, LAB_HANDLERS); diff --git a/src/redux/lab/sagas.ts b/src/redux/lab/sagas.ts new file mode 100644 index 00000000..5fc48b8b --- /dev/null +++ b/src/redux/lab/sagas.ts @@ -0,0 +1,21 @@ +import { takeLeading, call, put } from 'redux-saga/effects'; +import { labGetList, labSetList } from '~/redux/lab/actions'; +import { LAB_ACTIONS } from '~/redux/lab/constants'; +import { Unwrap } from '~/redux/types'; +import { getLabNodes } from '~/redux/lab/api'; + +function* getList({ after = '' }: ReturnType) { + try { + yield put(labSetList({ is_loading: true })); + const { nodes, count }: Unwrap = yield call(getLabNodes, { after }); + yield put(labSetList({ nodes, count })); + } catch (error) { + yield put(labSetList({ error: error.message })); + } finally { + yield put(labSetList({ is_loading: false })); + } +} + +export default function* labSaga() { + yield takeLeading(LAB_ACTIONS.GET_LIST, getList); +} diff --git a/src/redux/lab/selectors.ts b/src/redux/lab/selectors.ts new file mode 100644 index 00000000..0854ac25 --- /dev/null +++ b/src/redux/lab/selectors.ts @@ -0,0 +1,4 @@ +import { IState } from '~/redux/store'; + +export const selectLab = (state: IState) => state.lab; +export const selectLabListNodes = (state: IState) => state.lab.list.nodes; diff --git a/src/redux/lab/types.ts b/src/redux/lab/types.ts new file mode 100644 index 00000000..7614807b --- /dev/null +++ b/src/redux/lab/types.ts @@ -0,0 +1,19 @@ +import { IError, INode } from '~/redux/types'; + +export type ILabState = Readonly<{ + list: { + is_loading: boolean; + nodes: INode[]; + count: number; + error: IError; + }; +}>; + +export type GetLabNodesRequest = { + after?: string; +}; + +export type GetLabNodesResult = { + nodes: INode[]; + count: number; +}; diff --git a/src/redux/store.ts b/src/redux/store.ts index ea16f709..73e31db9 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -17,6 +17,10 @@ import nodeSaga from '~/redux/node/sagas'; import flow, { IFlowState } from '~/redux/flow/reducer'; import flowSaga from '~/redux/flow/sagas'; +import lab from '~/redux/lab'; +import labSaga from '~/redux/lab/sagas'; +import { ILabState } from '~/redux/lab/types'; + import uploads, { IUploadState } from '~/redux/uploads/reducer'; import uploadSaga from '~/redux/uploads/sagas'; @@ -69,6 +73,7 @@ export interface IState { boris: IBorisState; messages: IMessagesState; tag: ITagState; + lab: ILabState; } export const sagaMiddleware = createSagaMiddleware(); @@ -93,6 +98,7 @@ export const store = createStore( player: persistReducer(playerPersistConfig, player), messages, tag: tag, + lab: lab, }), composeEnhancers(applyMiddleware(routerMiddleware(history), sagaMiddleware)) ); @@ -110,6 +116,7 @@ export function configureStore(): { sagaMiddleware.run(borisSaga); sagaMiddleware.run(messagesSaga); sagaMiddleware.run(tagSaga); + sagaMiddleware.run(labSaga); window.addEventListener('message', message => { if (message && message.data && message.data.type === 'oauth_login' && message.data.token) From 05b4ed19c6b85044db6e3f6d0a4056c89bab6c1b Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Fri, 12 Mar 2021 14:16:45 +0700 Subject: [PATCH 22/37] #23 made sample lab layout --- src/components/lab/LabBanner/index.tsx | 22 ++++++++ .../lab/LabBanner/styles.module.scss | 5 ++ src/components/lab/LabHero/index.tsx | 22 ++++++++ src/components/lab/LabHero/styles.module.scss | 10 ++++ .../lab/LabNode/index.tsx | 0 .../lab/LabNode/styles.module.scss | 1 + src/containers/lab/LabGrid/index.tsx | 2 +- src/containers/lab/LabLayout/index.tsx | 54 ++++++++++++++++++- .../lab/LabLayout/styles.module.scss | 9 ++++ 9 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 src/components/lab/LabBanner/index.tsx create mode 100644 src/components/lab/LabBanner/styles.module.scss create mode 100644 src/components/lab/LabHero/index.tsx create mode 100644 src/components/lab/LabHero/styles.module.scss rename src/{containers => components}/lab/LabNode/index.tsx (100%) rename src/{containers => components}/lab/LabNode/styles.module.scss (99%) diff --git a/src/components/lab/LabBanner/index.tsx b/src/components/lab/LabBanner/index.tsx new file mode 100644 index 00000000..df8f60ea --- /dev/null +++ b/src/components/lab/LabBanner/index.tsx @@ -0,0 +1,22 @@ +import React, { FC } from 'react'; +import styles from './styles.module.scss'; +import { Card } from '~/components/containers/Card'; +import { Placeholder } from '~/components/placeholders/Placeholder'; +import { Group } from '~/components/containers/Group'; + +interface IProps {} + +const LabBanner: FC = () => ( + + + + + + + + + + +); + +export { LabBanner }; diff --git a/src/components/lab/LabBanner/styles.module.scss b/src/components/lab/LabBanner/styles.module.scss new file mode 100644 index 00000000..f235ed41 --- /dev/null +++ b/src/components/lab/LabBanner/styles.module.scss @@ -0,0 +1,5 @@ +@import "~/styles/variables.scss"; + +.wrap { + background: $red_gradient_alt; +} diff --git a/src/components/lab/LabHero/index.tsx b/src/components/lab/LabHero/index.tsx new file mode 100644 index 00000000..1a059815 --- /dev/null +++ b/src/components/lab/LabHero/index.tsx @@ -0,0 +1,22 @@ +import React, { FC } from 'react'; +import { Placeholder } from '~/components/placeholders/Placeholder'; +import { Group } from '~/components/containers/Group'; +import { Icon } from '~/components/input/Icon'; +import styles from './styles.module.scss'; + +interface IProps {} + +const LabHero: FC = () => ( + +
+ +
+ + + + + +
+); + +export { LabHero }; diff --git a/src/components/lab/LabHero/styles.module.scss b/src/components/lab/LabHero/styles.module.scss new file mode 100644 index 00000000..b1a7e9cc --- /dev/null +++ b/src/components/lab/LabHero/styles.module.scss @@ -0,0 +1,10 @@ +@import "~/styles/variables.scss"; + +.wrap { + margin-bottom: $gap; +} + +.star { + fill: #2c2c2c; +} + diff --git a/src/containers/lab/LabNode/index.tsx b/src/components/lab/LabNode/index.tsx similarity index 100% rename from src/containers/lab/LabNode/index.tsx rename to src/components/lab/LabNode/index.tsx diff --git a/src/containers/lab/LabNode/styles.module.scss b/src/components/lab/LabNode/styles.module.scss similarity index 99% rename from src/containers/lab/LabNode/styles.module.scss rename to src/components/lab/LabNode/styles.module.scss index 8e002f2b..0e8e59ab 100644 --- a/src/containers/lab/LabNode/styles.module.scss +++ b/src/components/lab/LabNode/styles.module.scss @@ -8,3 +8,4 @@ background-color: transparentize(black, 0.9); border-radius: $radius $radius 0 0; } + diff --git a/src/containers/lab/LabGrid/index.tsx b/src/containers/lab/LabGrid/index.tsx index 6dc04ef3..b6961b5f 100644 --- a/src/containers/lab/LabGrid/index.tsx +++ b/src/containers/lab/LabGrid/index.tsx @@ -1,7 +1,7 @@ import React, { FC } from 'react'; import { useShallowSelect } from '~/utils/hooks/useShallowSelect'; import styles from './styles.module.scss'; -import { LabNode } from '~/containers/lab/LabNode'; +import { LabNode } from '~/components/lab/LabNode'; import { selectLabListNodes } from '~/redux/lab/selectors'; interface IProps {} diff --git a/src/containers/lab/LabLayout/index.tsx b/src/containers/lab/LabLayout/index.tsx index 087a8546..020df216 100644 --- a/src/containers/lab/LabLayout/index.tsx +++ b/src/containers/lab/LabLayout/index.tsx @@ -6,6 +6,11 @@ import { Container } from '~/containers/main/Container'; import { LabGrid } from '~/containers/lab/LabGrid'; import { useDispatch } from 'react-redux'; import { labGetList } from '~/redux/lab/actions'; +import { Placeholder } from '~/components/placeholders/Placeholder'; +import { Grid } from '~/components/containers/Grid'; +import { Group } from '~/components/containers/Group'; +import { LabHero } from '~/components/lab/LabHero'; +import { LabBanner } from '~/components/lab/LabBanner'; interface IProps {} @@ -25,7 +30,54 @@ const LabLayout: FC = () => {
- Test + + + + + + + +
+ + + +
+ +
+ + + + + + +
+ +
+ + + +
+ + + +
+ +
+ +
+ +
+ +
+ +
+ + + +
+ + +
diff --git a/src/containers/lab/LabLayout/styles.module.scss b/src/containers/lab/LabLayout/styles.module.scss index c204075d..ee69442c 100644 --- a/src/containers/lab/LabLayout/styles.module.scss +++ b/src/containers/lab/LabLayout/styles.module.scss @@ -9,3 +9,12 @@ .panel { margin-top: -7px; } + +.tags { + display: flex; + flex-wrap: wrap; + + & > * { + margin: 0 $gap $gap 0; + } +} From b7276fd6e30e232cca9e1855270550d7511620d1 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Fri, 12 Mar 2021 17:51:14 +0700 Subject: [PATCH 23/37] #23 fixed lab frames with header --- src/components/lab/LabHead/index.tsx | 32 ++++++++++++++++++++++++++ src/components/main/Header/index.tsx | 14 +++++------ src/containers/lab/LabLayout/index.tsx | 29 ++++++++++++++++++++--- 3 files changed, 65 insertions(+), 10 deletions(-) create mode 100644 src/components/lab/LabHead/index.tsx diff --git a/src/components/lab/LabHead/index.tsx b/src/components/lab/LabHead/index.tsx new file mode 100644 index 00000000..25fb6cfd --- /dev/null +++ b/src/components/lab/LabHead/index.tsx @@ -0,0 +1,32 @@ +import React, { FC } from 'react'; +import { Group } from '~/components/containers/Group'; +import { Card } from '~/components/containers/Card'; +import { Placeholder } from '~/components/placeholders/Placeholder'; +import { Filler } from '~/components/containers/Filler'; + +interface IProps {} + +const LabHead: FC = () => ( + + + + + + + + + + + + + + + + + + + + +); + +export { LabHead }; diff --git a/src/components/main/Header/index.tsx b/src/components/main/Header/index.tsx index 69d0dee4..8f1db775 100644 --- a/src/components/main/Header/index.tsx +++ b/src/components/main/Header/index.tsx @@ -82,6 +82,13 @@ const HeaderUnconnected: FC = memo(
+ + ФЛОУ + + {is_user && ( = memo( )} - - ФЛОУ - - = () => {
-
+ + -
+ +
@@ -35,8 +39,13 @@ const LabLayout: FC = () => { - + + + + + +
@@ -52,6 +61,7 @@ const LabLayout: FC = () => {
+
@@ -75,6 +85,19 @@ const LabLayout: FC = () => {
+
+ + + + + + +
+ + + + + From e38090c7554b60d31ceb190446c255a120906db9 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Wed, 17 Mar 2021 11:07:26 +0700 Subject: [PATCH 24/37] #23 added lab disabling switch --- .../editors/EditorPublicSwitch/index.tsx | 17 +++-------------- src/components/main/Header/index.tsx | 2 +- src/react-app-env.d.ts | 1 + 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/components/editors/EditorPublicSwitch/index.tsx b/src/components/editors/EditorPublicSwitch/index.tsx index be6feed0..c654a559 100644 --- a/src/components/editors/EditorPublicSwitch/index.tsx +++ b/src/components/editors/EditorPublicSwitch/index.tsx @@ -6,25 +6,14 @@ import { Button } from '~/components/input/Button'; interface IProps extends IEditorComponentProps {} const EditorPublicSwitch: FC = ({ data, setData }) => { - const tooltip = useRef(null); const onChange = useCallback(() => setData({ ...data, is_promoted: !data.is_promoted }), [ data, setData, ]); - const pop = usePopper(tooltip?.current?.parentElement, tooltip.current, { - placement: 'bottom', - modifiers: [ - { - name: 'offset', - options: { - offset: [0, 4], - }, - }, - ], - }); - - useEffect(() => console.log(pop), [pop]); + if (process.env.REACT_APP_LAB_ENABLED !== '1') { + return null; + } return ( + + + + + + +

Размеры

+ + + + + + + + + +

Варианты

+ + + + + +
+ +); + +export { BorisUIDemo }; diff --git a/src/components/boris/BorisUIDemo/styles.module.scss b/src/components/boris/BorisUIDemo/styles.module.scss new file mode 100644 index 00000000..5d9eacfd --- /dev/null +++ b/src/components/boris/BorisUIDemo/styles.module.scss @@ -0,0 +1,11 @@ +.card { + flex: 3; + align-self: stretch; + position: relative; + z-index: 1; + padding: 20px 30px; +} + +.sample { + flex-wrap: wrap; +} diff --git a/src/components/input/Button/index.tsx b/src/components/input/Button/index.tsx index 1f2a02a6..6d9e3801 100644 --- a/src/components/input/Button/index.tsx +++ b/src/components/input/Button/index.tsx @@ -6,11 +6,15 @@ import React, { createElement, memo, useRef, + useEffect, + useMemo, } from 'react'; import styles from './styles.module.scss'; import { Icon } from '~/components/input/Icon'; import { IIcon } from '~/redux/types'; import { usePopper } from 'react-popper'; +import Tippy from '@tippy.js/react'; +import 'tippy.js/dist/tippy.css'; type IButtonProps = DetailedHTMLProps< ButtonHTMLAttributes, @@ -23,7 +27,6 @@ type IButtonProps = DetailedHTMLProps< seamless?: boolean; transparent?: boolean; title?: string; - non_submitting?: boolean; is_loading?: boolean; stretchy?: boolean; iconOnly?: boolean; @@ -41,7 +44,6 @@ const Button: FC = memo( children, seamless = false, transparent = false, - non_submitting = false, is_loading, title, stretchy, @@ -52,23 +54,9 @@ const Button: FC = memo( round, ...props }) => { - const tooltip = useRef(null); - const pop = usePopper(tooltip?.current?.parentElement, tooltip.current, { - placement: 'top', - modifiers: [ - { - name: 'offset', - options: { - offset: [0, 5], - }, - }, - ], - }); - - return createElement( - seamless || non_submitting ? 'div' : 'button', - { - className: classnames(styles.button, className, styles[size], styles[color], { + const computedClassName = useMemo( + () => + classnames(styles.button, className, styles[size], styles[color], { seamless, transparent, disabled, @@ -79,18 +67,17 @@ const Button: FC = memo( has_icon_right: !!iconRight, round, }), - ...props, - }, - [ - iconLeft && , - title ? {title} : children || null, - iconRight && , - !!label && ( - - {label} - - ), - ] + [seamless, round, disabled, className, is_loading, stretchy, iconLeft, iconRight, size, color] + ); + + return ( + + + ); } ); diff --git a/src/components/input/Button/styles.module.scss b/src/components/input/Button/styles.module.scss index 255b3594..118131c7 100644 --- a/src/components/input/Button/styles.module.scss +++ b/src/components/input/Button/styles.module.scss @@ -184,32 +184,56 @@ font: $font_12_semibold; padding: 0 15px; border-radius: $radius / 2; + + &:global(.round) { + border-radius: 10px; + } } .mini { height: 28px; border-radius: $radius / 2; + + &:global(.round) { + border-radius: 14px; + } } .small { height: 32px; - // border-radius: $radius / 2; svg { width: 24px; height: 24px; } + + &:global(.round) { + border-radius: 16px; + } } + .normal { height: 38px; + + &:global(.round) { + border-radius: 19px; + } } .big { height: 40px; + + &:global(.round) { + border-radius: 20px; + } } .giant { height: 50px; padding: 0 15px; min-width: 50px; + + &:global(.round) { + border-radius: 25px; + } } .disabled { @@ -234,14 +258,13 @@ z-index: 2; border-radius: $input_radius; text-transform: none; - opacity: 0; - pointer-events: none; touch-action: none; transition: opacity 0.1s; border: 1px solid transparentize(white, 0.9); + //visibility: hidden; .button:hover & { - opacity: 1; + visibility: visible; font: $font_14_semibold; } } diff --git a/src/containers/dialogs/EditorDialog/index.tsx b/src/containers/dialogs/EditorDialog/index.tsx index a5a42243..998ccb59 100644 --- a/src/containers/dialogs/EditorDialog/index.tsx +++ b/src/containers/dialogs/EditorDialog/index.tsx @@ -95,7 +95,11 @@ const EditorDialogUnconnected: FC = ({ maxLength={256} /> -
- - - {user.is_user && } + { + + - {node.is_loading_comments ? ( - - ) : ( - - )} - - -
- + + + } diff --git a/src/containers/node/BorisLayout/styles.module.scss b/src/containers/node/BorisLayout/styles.module.scss index f6e3c8ad..44c56d9b 100644 --- a/src/containers/node/BorisLayout/styles.module.scss +++ b/src/containers/node/BorisLayout/styles.module.scss @@ -7,22 +7,6 @@ flex-direction: column; } -.content { - flex: 4; - z-index: 2; - border-radius: $radius; - padding: 0; - background: $node_bg; - box-shadow: inset transparentize(mix($wisegreen, white, 60%), 0.6) 0 1px; - - @include desktop { - flex: 2.5; - } - - @media(max-width: 1024px) { - flex: 2; - } -} .grid { padding: $gap; diff --git a/yarn.lock b/yarn.lock index a3992a4e..b2d4bc5e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1594,6 +1594,14 @@ dependencies: "@babel/runtime" "^7.10.2" +"@tippy.js/react@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@tippy.js/react/-/react-3.1.1.tgz#027e4595e55f31430741fe8e0d92aaddfbe47efd" + integrity sha512-KF45vW/jKh/nBXk/2zzTFslv/T46zOMkIoDJ56ymZ+M00yHttk58J5wZ29oqGqDIUnobWSZD+cFpbR4u/UUvgw== + dependencies: + prop-types "^15.6.2" + tippy.js "^5.1.1" + "@types/aria-query@^4.2.0": version "4.2.0" resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.0.tgz#14264692a9d6e2fa4db3df5e56e94b5e25647ac0" @@ -8330,6 +8338,11 @@ pnp-webpack-plugin@1.6.4: dependencies: ts-pnp "^1.1.6" +popper.js@^1.16.0: + version "1.16.1" + resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" + integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== + portfinder@^1.0.26: version "1.0.28" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" @@ -10972,6 +10985,13 @@ tiny-warning@^1.0.0, tiny-warning@^1.0.2, tiny-warning@^1.0.3: resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== +tippy.js@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-5.2.1.tgz#e08d7332c103a15e427124d710d881fca82365d6" + integrity sha512-66UT6JRVn3dXNCORE+0UvUK3JZqV/VhLlU6HTDm3FmrweUUFUxUGvT8tUQ7ycMp+uhuLAwQw6dBabyC+iKf/MA== + dependencies: + popper.js "^1.16.0" + tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" From 82aeb7f1475cd2a8acc84ba2f44beb4c69acc87c Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Wed, 17 Mar 2021 14:31:42 +0700 Subject: [PATCH 26/37] #23 cleaned button props --- src/components/input/Button/index.tsx | 23 +---------- .../input/Button/styles.module.scss | 41 +------------------ 2 files changed, 4 insertions(+), 60 deletions(-) diff --git a/src/components/input/Button/index.tsx b/src/components/input/Button/index.tsx index 6d9e3801..8e569762 100644 --- a/src/components/input/Button/index.tsx +++ b/src/components/input/Button/index.tsx @@ -1,18 +1,8 @@ import classnames from 'classnames'; -import React, { - ButtonHTMLAttributes, - DetailedHTMLProps, - FC, - createElement, - memo, - useRef, - useEffect, - useMemo, -} from 'react'; +import React, { ButtonHTMLAttributes, DetailedHTMLProps, FC, memo, useMemo } from 'react'; import styles from './styles.module.scss'; import { Icon } from '~/components/input/Icon'; import { IIcon } from '~/redux/types'; -import { usePopper } from 'react-popper'; import Tippy from '@tippy.js/react'; import 'tippy.js/dist/tippy.css'; @@ -24,10 +14,7 @@ type IButtonProps = DetailedHTMLProps< color?: 'primary' | 'secondary' | 'outline' | 'link' | 'gray'; iconLeft?: IIcon; iconRight?: IIcon; - seamless?: boolean; - transparent?: boolean; title?: string; - is_loading?: boolean; stretchy?: boolean; iconOnly?: boolean; label?: string; @@ -42,9 +29,6 @@ const Button: FC = memo( iconLeft, iconRight, children, - seamless = false, - transparent = false, - is_loading, title, stretchy, disabled, @@ -57,17 +41,14 @@ const Button: FC = memo( const computedClassName = useMemo( () => classnames(styles.button, className, styles[size], styles[color], { - seamless, - transparent, disabled, - is_loading, stretchy, icon: ((iconLeft || iconRight) && !title && !children) || iconOnly, has_icon_left: !!iconLeft, has_icon_right: !!iconRight, round, }), - [seamless, round, disabled, className, is_loading, stretchy, iconLeft, iconRight, size, color] + [round, disabled, className, stretchy, iconLeft, iconRight, size, color] ); return ( diff --git a/src/components/input/Button/styles.module.scss b/src/components/input/Button/styles.module.scss index 118131c7..fe57ddd9 100644 --- a/src/components/input/Button/styles.module.scss +++ b/src/components/input/Button/styles.module.scss @@ -34,8 +34,6 @@ align-items: center; justify-content: center; - position: relative; - filter: grayscale(0); transition: opacity 0.25s, filter 0.25s, box-shadow 0.25s; @@ -79,24 +77,6 @@ } } - &:global(.seamless) { - background: transparent; - color: black; - box-shadow: none; - fill: black; - stroke: black; - padding: 0; - } - - &:global(.transparent) { - background: transparent; - color: white; - box-shadow: transparentize(black, 0.5) 0 0 4px; - padding: 0; - fill: black; - stroke: black; - } - &:global(.red) { fill: $red; stroke: $red; @@ -111,8 +91,6 @@ &:global(.grey) { background: transparentize(white, 0.9); color: white; - // background: lighten(white, 0.5); - // filter: grayscale(100%); } &:global(.disabled) { @@ -189,6 +167,7 @@ border-radius: 10px; } } + .mini { height: 28px; border-radius: $radius / 2; @@ -197,6 +176,7 @@ border-radius: 14px; } } + .small { height: 32px; @@ -251,20 +231,3 @@ width: 20px; height: 20px; } - -.tooltip { - padding: 5px 10px; - background-color: darken($content_bg, 4%); - z-index: 2; - border-radius: $input_radius; - text-transform: none; - touch-action: none; - transition: opacity 0.1s; - border: 1px solid transparentize(white, 0.9); - //visibility: hidden; - - .button:hover & { - visibility: visible; - font: $font_14_semibold; - } -} From 32aaa3f7947acfb228ead21b3f9d0dabdc1606de Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Wed, 17 Mar 2021 17:26:22 +0700 Subject: [PATCH 27/37] #23 changed promoted button appearance --- .../editors/EditorPublicSwitch/index.tsx | 19 ++- .../EditorPublicSwitch/styles.module.scss | 108 +++++++++--------- src/components/input/Button/index.tsx | 2 +- .../input/Button/styles.module.scss | 28 +++-- src/containers/dialogs/EditorDialog/index.tsx | 6 +- src/sprites/Sprites.tsx | 4 +- src/styles/_colors.scss | 2 +- 7 files changed, 86 insertions(+), 83 deletions(-) diff --git a/src/components/editors/EditorPublicSwitch/index.tsx b/src/components/editors/EditorPublicSwitch/index.tsx index c654a559..dac7b478 100644 --- a/src/components/editors/EditorPublicSwitch/index.tsx +++ b/src/components/editors/EditorPublicSwitch/index.tsx @@ -1,7 +1,8 @@ -import React, { FC, useCallback, useEffect, useRef } from 'react'; +import React, { FC, useCallback } from 'react'; import { IEditorComponentProps } from '~/redux/node/types'; -import { usePopper } from 'react-popper'; import { Button } from '~/components/input/Button'; +import { Icon } from '~/components/input/Icon'; +import styles from './styles.module.scss'; interface IProps extends IEditorComponentProps {} @@ -17,9 +18,8 @@ const EditorPublicSwitch: FC = ({ data, setData }) => { return ( ); }; diff --git a/src/components/editors/EditorPublicSwitch/styles.module.scss b/src/components/editors/EditorPublicSwitch/styles.module.scss index e41682c0..95aa2412 100644 --- a/src/components/editors/EditorPublicSwitch/styles.module.scss +++ b/src/components/editors/EditorPublicSwitch/styles.module.scss @@ -1,63 +1,63 @@ @import "src/styles/variables"; -.wrap { - @include outer_shadow(); - @include editor_round_button(); - - transition: all 0.5s; - fill: $content_bg; - background-color: $olive; - - &.promoted { - background-color: lighten($content_bg, 4%); - fill: $red; +@keyframes move_1 { + 0% { + transform: scale(0) translate(0, 0); + opacity: 0; } - &:hover { + 50% { + transform: scale(1) translate(5px, -5px); opacity: 1; + } - .tooltip { - opacity: 1; + 100% { + transform: scale(1.2) translate(-5px, -10px); + opacity: 0; + } +} + + +@keyframes move_2 { + 0% { + transform: scale(0) translate(0, 0); + opacity: 0; + } + + 50% { + transform: scale(1) translate(-5px, -5px); + opacity: 1; + } + + 100% { + transform: scale(1.6) translate(5px, -10px); + opacity: 0; + } +} + +.button { + +} + +.lab_wrapper { + position: relative; + bottom: -2px; + + .button:hover & { + &:before,&:after { + content: ' '; + position: absolute; + top: 1px; + left: 10px; + width: 2px; + height: 2px; + box-shadow: white 0 0 0 2px; + border-radius: 4px; + animation: move_1 0.5s infinite linear; + } + + &:after { + animation: move_2 0.5s -0.25s infinite linear; } } - - input { - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; - opacity: 0; - z-index: 1; - cursor: pointer; - } -} - -.icon { - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; - display: flex; - align-items: center; - justify-content: center; -} - -.tooltip { - border-radius: 2px; - background: darken($content_bg, 6%); - padding: $gap; - position: absolute; - font: $font_12_semibold; - bottom: 100%; - right: 0; - transform: translate(0, -$gap); - text-align: center; - touch-action: none; - pointer-events: none; - opacity: 0; - width: 100px; - user-select: none; - transition: all 0.1s; } diff --git a/src/components/input/Button/index.tsx b/src/components/input/Button/index.tsx index 8e569762..e0f3965d 100644 --- a/src/components/input/Button/index.tsx +++ b/src/components/input/Button/index.tsx @@ -11,7 +11,7 @@ type IButtonProps = DetailedHTMLProps< HTMLButtonElement > & { size?: 'mini' | 'normal' | 'big' | 'giant' | 'micro' | 'small'; - color?: 'primary' | 'secondary' | 'outline' | 'link' | 'gray'; + color?: 'primary' | 'secondary' | 'outline' | 'link' | 'gray' | 'lab'; iconLeft?: IIcon; iconRight?: IIcon; title?: string; diff --git a/src/components/input/Button/styles.module.scss b/src/components/input/Button/styles.module.scss index fe57ddd9..0489151c 100644 --- a/src/components/input/Button/styles.module.scss +++ b/src/components/input/Button/styles.module.scss @@ -36,7 +36,7 @@ filter: grayscale(0); - transition: opacity 0.25s, filter 0.25s, box-shadow 0.25s; + transition: opacity 0.25s, filter 0.25s, box-shadow 0.25s, background-color 0.5s; opacity: 0.8; @include outer_shadow(); @@ -77,12 +77,6 @@ } } - &:global(.red) { - fill: $red; - stroke: $red; - color: $red; - } - &:global(.stretchy) { flex: 1; } @@ -123,14 +117,6 @@ padding-right: $gap; } - &.primary { - background: $red_gradient; - } - - &.secondary { - background: $green_gradient; - } - &.outline { background: transparent; box-shadow: inset transparentize(white, 0.8) 0 0 0 2px; @@ -231,3 +217,15 @@ width: 20px; height: 20px; } + +.primary { + background: $red; +} + +.secondary { + background: $wisegreen; +} + +.lab { + background: $blue; +} diff --git a/src/containers/dialogs/EditorDialog/index.tsx b/src/containers/dialogs/EditorDialog/index.tsx index 998ccb59..564b5dfc 100644 --- a/src/containers/dialogs/EditorDialog/index.tsx +++ b/src/containers/dialogs/EditorDialog/index.tsx @@ -95,11 +95,7 @@ const EditorDialogUnconnected: FC = ({ maxLength={256} /> - + + + + + + +

Размеры

+ + + + + + + + + +

Варианты

+ + + + + +
+ +); + +export { BorisUIDemo }; diff --git a/src/components/boris/BorisUIDemo/styles.module.scss b/src/components/boris/BorisUIDemo/styles.module.scss new file mode 100644 index 00000000..5d9eacfd --- /dev/null +++ b/src/components/boris/BorisUIDemo/styles.module.scss @@ -0,0 +1,11 @@ +.card { + flex: 3; + align-self: stretch; + position: relative; + z-index: 1; + padding: 20px 30px; +} + +.sample { + flex-wrap: wrap; +} diff --git a/src/components/editors/EditorPublicSwitch/styles.module.scss b/src/components/editors/EditorPublicSwitch/styles.module.scss index e41682c0..95aa2412 100644 --- a/src/components/editors/EditorPublicSwitch/styles.module.scss +++ b/src/components/editors/EditorPublicSwitch/styles.module.scss @@ -1,63 +1,63 @@ @import "src/styles/variables"; -.wrap { - @include outer_shadow(); - @include editor_round_button(); - - transition: all 0.5s; - fill: $content_bg; - background-color: $olive; - - &.promoted { - background-color: lighten($content_bg, 4%); - fill: $red; +@keyframes move_1 { + 0% { + transform: scale(0) translate(0, 0); + opacity: 0; } - &:hover { + 50% { + transform: scale(1) translate(5px, -5px); opacity: 1; + } - .tooltip { - opacity: 1; + 100% { + transform: scale(1.2) translate(-5px, -10px); + opacity: 0; + } +} + + +@keyframes move_2 { + 0% { + transform: scale(0) translate(0, 0); + opacity: 0; + } + + 50% { + transform: scale(1) translate(-5px, -5px); + opacity: 1; + } + + 100% { + transform: scale(1.6) translate(5px, -10px); + opacity: 0; + } +} + +.button { + +} + +.lab_wrapper { + position: relative; + bottom: -2px; + + .button:hover & { + &:before,&:after { + content: ' '; + position: absolute; + top: 1px; + left: 10px; + width: 2px; + height: 2px; + box-shadow: white 0 0 0 2px; + border-radius: 4px; + animation: move_1 0.5s infinite linear; + } + + &:after { + animation: move_2 0.5s -0.25s infinite linear; } } - - input { - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; - opacity: 0; - z-index: 1; - cursor: pointer; - } -} - -.icon { - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; - display: flex; - align-items: center; - justify-content: center; -} - -.tooltip { - border-radius: 2px; - background: darken($content_bg, 6%); - padding: $gap; - position: absolute; - font: $font_12_semibold; - bottom: 100%; - right: 0; - transform: translate(0, -$gap); - text-align: center; - touch-action: none; - pointer-events: none; - opacity: 0; - width: 100px; - user-select: none; - transition: all 0.1s; } diff --git a/src/components/input/Button/index.tsx b/src/components/input/Button/index.tsx index 1f2a02a6..e0f3965d 100644 --- a/src/components/input/Button/index.tsx +++ b/src/components/input/Button/index.tsx @@ -1,30 +1,20 @@ import classnames from 'classnames'; -import React, { - ButtonHTMLAttributes, - DetailedHTMLProps, - FC, - createElement, - memo, - useRef, -} from 'react'; +import React, { ButtonHTMLAttributes, DetailedHTMLProps, FC, memo, useMemo } from 'react'; import styles from './styles.module.scss'; import { Icon } from '~/components/input/Icon'; import { IIcon } from '~/redux/types'; -import { usePopper } from 'react-popper'; +import Tippy from '@tippy.js/react'; +import 'tippy.js/dist/tippy.css'; type IButtonProps = DetailedHTMLProps< ButtonHTMLAttributes, HTMLButtonElement > & { size?: 'mini' | 'normal' | 'big' | 'giant' | 'micro' | 'small'; - color?: 'primary' | 'secondary' | 'outline' | 'link' | 'gray'; + color?: 'primary' | 'secondary' | 'outline' | 'link' | 'gray' | 'lab'; iconLeft?: IIcon; iconRight?: IIcon; - seamless?: boolean; - transparent?: boolean; title?: string; - non_submitting?: boolean; - is_loading?: boolean; stretchy?: boolean; iconOnly?: boolean; label?: string; @@ -39,10 +29,6 @@ const Button: FC = memo( iconLeft, iconRight, children, - seamless = false, - transparent = false, - non_submitting = false, - is_loading, title, stretchy, disabled, @@ -52,45 +38,27 @@ const Button: FC = memo( round, ...props }) => { - const tooltip = useRef(null); - const pop = usePopper(tooltip?.current?.parentElement, tooltip.current, { - placement: 'top', - modifiers: [ - { - name: 'offset', - options: { - offset: [0, 5], - }, - }, - ], - }); - - return createElement( - seamless || non_submitting ? 'div' : 'button', - { - className: classnames(styles.button, className, styles[size], styles[color], { - seamless, - transparent, + const computedClassName = useMemo( + () => + classnames(styles.button, className, styles[size], styles[color], { disabled, - is_loading, stretchy, icon: ((iconLeft || iconRight) && !title && !children) || iconOnly, has_icon_left: !!iconLeft, has_icon_right: !!iconRight, round, }), - ...props, - }, - [ - iconLeft && , - title ? {title} : children || null, - iconRight && , - !!label && ( - - {label} - - ), - ] + [round, disabled, className, stretchy, iconLeft, iconRight, size, color] + ); + + return ( + + + ); } ); diff --git a/src/components/input/Button/styles.module.scss b/src/components/input/Button/styles.module.scss index 255b3594..0489151c 100644 --- a/src/components/input/Button/styles.module.scss +++ b/src/components/input/Button/styles.module.scss @@ -34,11 +34,9 @@ align-items: center; justify-content: center; - position: relative; - filter: grayscale(0); - transition: opacity 0.25s, filter 0.25s, box-shadow 0.25s; + transition: opacity 0.25s, filter 0.25s, box-shadow 0.25s, background-color 0.5s; opacity: 0.8; @include outer_shadow(); @@ -79,30 +77,6 @@ } } - &:global(.seamless) { - background: transparent; - color: black; - box-shadow: none; - fill: black; - stroke: black; - padding: 0; - } - - &:global(.transparent) { - background: transparent; - color: white; - box-shadow: transparentize(black, 0.5) 0 0 4px; - padding: 0; - fill: black; - stroke: black; - } - - &:global(.red) { - fill: $red; - stroke: $red; - color: $red; - } - &:global(.stretchy) { flex: 1; } @@ -111,8 +85,6 @@ &:global(.grey) { background: transparentize(white, 0.9); color: white; - // background: lighten(white, 0.5); - // filter: grayscale(100%); } &:global(.disabled) { @@ -145,14 +117,6 @@ padding-right: $gap; } - &.primary { - background: $red_gradient; - } - - &.secondary { - background: $green_gradient; - } - &.outline { background: transparent; box-shadow: inset transparentize(white, 0.8) 0 0 0 2px; @@ -184,32 +148,58 @@ font: $font_12_semibold; padding: 0 15px; border-radius: $radius / 2; + + &:global(.round) { + border-radius: 10px; + } } + .mini { height: 28px; border-radius: $radius / 2; + + &:global(.round) { + border-radius: 14px; + } } + .small { height: 32px; - // border-radius: $radius / 2; svg { width: 24px; height: 24px; } + + &:global(.round) { + border-radius: 16px; + } } + .normal { height: 38px; + + &:global(.round) { + border-radius: 19px; + } } .big { height: 40px; + + &:global(.round) { + border-radius: 20px; + } } .giant { height: 50px; padding: 0 15px; min-width: 50px; + + &:global(.round) { + border-radius: 25px; + } } .disabled { @@ -228,20 +218,14 @@ height: 20px; } -.tooltip { - padding: 5px 10px; - background-color: darken($content_bg, 4%); - z-index: 2; - border-radius: $input_radius; - text-transform: none; - opacity: 0; - pointer-events: none; - touch-action: none; - transition: opacity 0.1s; - border: 1px solid transparentize(white, 0.9); - - .button:hover & { - opacity: 1; - font: $font_14_semibold; - } +.primary { + background: $red; +} + +.secondary { + background: $wisegreen; +} + +.lab { + background: $blue; } diff --git a/src/containers/dialogs/EditorDialog/index.tsx b/src/containers/dialogs/EditorDialog/index.tsx index a5a42243..564b5dfc 100644 --- a/src/containers/dialogs/EditorDialog/index.tsx +++ b/src/containers/dialogs/EditorDialog/index.tsx @@ -95,7 +95,7 @@ const EditorDialogUnconnected: FC = ({ maxLength={256} /> -