Merge branch 'feature/refactoring-selectors' into feature/editor-nextjs

This commit is contained in:
Timofey Boyko 2024-01-31 16:22:01 +03:00
commit 4b4ddba58c
795 changed files with 29150 additions and 26310 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

893
.yarn/releases/yarn-4.0.2.cjs vendored Executable file

File diff suppressed because one or more lines are too long

View File

@ -1,13 +1,11 @@
compressionLevel: mixed
enableGlobalCache: false
nodeLinker: node-modules
plugins:
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
spec: "@yarnpkg/plugin-workspace-tools"
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
spec: "@yarnpkg/plugin-interactive-tools"
- path: .yarn/plugins/@yarnpkg/plugin-version.cjs
spec: "@yarnpkg/plugin-version"
- path: .yarn/plugins/@yarnpkg/plugin-licenses-audit.cjs
spec: "https://raw.githubusercontent.com/tophat/yarn-plugin-licenses/master/bundles/@yarnpkg/plugin-licenses-audit.js"
yarnPath: .yarn/releases/yarn-3.2.4.cjs
yarnPath: .yarn/releases/yarn-4.0.2.cjs

355
graph.svg
View File

@ -1,355 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 9.0.0 (20230911.1827)
-->
<!-- Title: G Pages: 1 -->
<svg width="2744pt" height="500pt"
viewBox="0.00 0.00 2743.70 500.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(21.6 478.4)">
<title>G</title>
<polygon fill="#111111" stroke="none" points="-21.6,21.6 -21.6,-478.4 2722.1,-478.4 2722.1,21.6 -21.6,21.6"/>
<!-- client/src/components/panels/InvitePanel/index.js -->
<g id="node1" class="node">
<title>client/src/components/panels/InvitePanel/index.js</title>
<path fill="none" stroke="#ff6c60" d="M325.33,-26.8C325.33,-26.8 30.42,-26.8 30.42,-26.8 26.46,-26.8 22.5,-22.84 22.5,-18.88 22.5,-18.88 22.5,-10.97 22.5,-10.97 22.5,-7.01 26.46,-3.05 30.42,-3.05 30.42,-3.05 325.33,-3.05 325.33,-3.05 329.29,-3.05 333.25,-7.01 333.25,-10.97 333.25,-10.97 333.25,-18.88 333.25,-18.88 333.25,-22.84 329.29,-26.8 325.33,-26.8"/>
<text text-anchor="middle" x="177.88" y="-9.5" font-family="Arial" font-size="14.00" fill="#ff6c60">client/src/components/panels/InvitePanel/index.js</text>
</g>
<!-- client/src/components/panels/InvitePanel/sub&#45;components/InviteInput.js -->
<g id="node2" class="node">
<title>client/src/components/panels/InvitePanel/sub&#45;components/InviteInput.js</title>
<path fill="none" stroke="#ff6c60" d="M828.83,-36.8C828.83,-36.8 399.67,-36.8 399.67,-36.8 395.71,-36.8 391.75,-32.84 391.75,-28.88 391.75,-28.88 391.75,-20.97 391.75,-20.97 391.75,-17.01 395.71,-13.05 399.67,-13.05 399.67,-13.05 828.83,-13.05 828.83,-13.05 832.79,-13.05 836.75,-17.01 836.75,-20.97 836.75,-20.97 836.75,-28.88 836.75,-28.88 836.75,-32.84 832.79,-36.8 828.83,-36.8"/>
<text text-anchor="middle" x="614.25" y="-19.5" font-family="Arial" font-size="14.00" fill="#ff6c60">client/src/components/panels/InvitePanel/sub&#45;components/InviteInput.js</text>
</g>
<!-- client/src/components/panels/InvitePanel/index.js&#45;&gt;client/src/components/panels/InvitePanel/sub&#45;components/InviteInput.js -->
<g id="edge1" class="edge">
<title>client/src/components/panels/InvitePanel/index.js&#45;&gt;client/src/components/panels/InvitePanel/sub&#45;components/InviteInput.js</title>
<path fill="none" stroke="#757575" d="M333.55,-18.49C348.65,-18.83 364.2,-19.19 379.85,-19.55"/>
<polygon fill="#757575" stroke="#757575" points="379.68,-23.05 389.75,-19.78 379.84,-16.05 379.68,-23.05"/>
</g>
<!-- client/src/components/panels/index.js -->
<g id="node3" class="node">
<title>client/src/components/panels/index.js</title>
<path fill="none" stroke="#ff6c60" d="M1154.96,-26.8C1154.96,-26.8 930.54,-26.8 930.54,-26.8 926.58,-26.8 922.62,-22.84 922.62,-18.88 922.62,-18.88 922.62,-10.97 922.62,-10.97 922.62,-7.01 926.58,-3.05 930.54,-3.05 930.54,-3.05 1154.96,-3.05 1154.96,-3.05 1158.92,-3.05 1162.88,-7.01 1162.88,-10.97 1162.88,-10.97 1162.88,-18.88 1162.88,-18.88 1162.88,-22.84 1158.92,-26.8 1154.96,-26.8"/>
<text text-anchor="middle" x="1042.75" y="-9.5" font-family="Arial" font-size="14.00" fill="#ff6c60">client/src/components/panels/index.js</text>
</g>
<!-- client/src/components/panels/InvitePanel/sub&#45;components/InviteInput.js&#45;&gt;client/src/components/panels/index.js -->
<g id="edge2" class="edge">
<title>client/src/components/panels/InvitePanel/sub&#45;components/InviteInput.js&#45;&gt;client/src/components/panels/index.js</title>
<path fill="none" stroke="#757575" d="M837.24,-19.72C862.47,-19.13 887.52,-18.54 911,-17.99"/>
<polygon fill="#757575" stroke="#757575" points="910.97,-21.49 920.89,-17.76 910.81,-14.5 910.97,-21.49"/>
</g>
<!-- client/src/components/panels/index.js&#45;&gt;client/src/components/panels/InvitePanel/index.js -->
<g id="edge4" class="edge">
<title>client/src/components/panels/index.js&#45;&gt;client/src/components/panels/InvitePanel/index.js</title>
<path fill="none" stroke="#757575" d="M922.28,-7.43C894.24,-5.98 864.45,-4.67 836.75,-3.93 639.04,1.37 589.46,1.18 391.75,-3.93 376.42,-4.32 360.48,-4.88 344.52,-5.53"/>
<polygon fill="#757575" stroke="#757575" points="344.83,-2.02 334.99,-5.94 345.13,-9.01 344.83,-2.02"/>
</g>
<!-- client/src/components/panels/SharingPanel/index.js -->
<g id="node4" class="node">
<title>client/src/components/panels/SharingPanel/index.js</title>
<path fill="none" stroke="#ff6c60" d="M1573.33,-26.8C1573.33,-26.8 1264.17,-26.8 1264.17,-26.8 1260.21,-26.8 1256.25,-22.84 1256.25,-18.88 1256.25,-18.88 1256.25,-10.97 1256.25,-10.97 1256.25,-7.01 1260.21,-3.05 1264.17,-3.05 1264.17,-3.05 1573.33,-3.05 1573.33,-3.05 1577.29,-3.05 1581.25,-7.01 1581.25,-10.97 1581.25,-10.97 1581.25,-18.88 1581.25,-18.88 1581.25,-22.84 1577.29,-26.8 1573.33,-26.8"/>
<text text-anchor="middle" x="1418.75" y="-9.5" font-family="Arial" font-size="14.00" fill="#ff6c60">client/src/components/panels/SharingPanel/index.js</text>
</g>
<!-- client/src/components/panels/index.js&#45;&gt;client/src/components/panels/SharingPanel/index.js -->
<g id="edge5" class="edge">
<title>client/src/components/panels/index.js&#45;&gt;client/src/components/panels/SharingPanel/index.js</title>
<path fill="none" stroke="#757575" d="M1163.37,-8.58C1189.29,-8.26 1217.21,-8.13 1244.72,-8.19"/>
<polygon fill="#757575" stroke="#757575" points="1244.54,-11.69 1254.55,-8.23 1244.56,-4.69 1244.54,-11.69"/>
</g>
<!-- client/src/components/panels/SharingPanel/index.js&#45;&gt;client/src/components/panels/index.js -->
<g id="edge3" class="edge">
<title>client/src/components/panels/SharingPanel/index.js&#45;&gt;client/src/components/panels/index.js</title>
<path fill="none" stroke="#757575" d="M1256.06,-21.62C1228.83,-21.74 1200.87,-21.67 1174.55,-21.4"/>
<polygon fill="#757575" stroke="#757575" points="1174.92,-17.9 1164.89,-21.29 1174.84,-24.9 1174.92,-17.9"/>
</g>
<!-- client/src/helpers/desktop.js -->
<g id="node5" class="node">
<title>client/src/helpers/desktop.js</title>
<path fill="none" stroke="#ff6c60" d="M260.83,-87.8C260.83,-87.8 94.92,-87.8 94.92,-87.8 90.96,-87.8 87,-83.84 87,-79.88 87,-79.88 87,-71.97 87,-71.97 87,-68.01 90.96,-64.05 94.92,-64.05 94.92,-64.05 260.83,-64.05 260.83,-64.05 264.79,-64.05 268.75,-68.01 268.75,-71.97 268.75,-71.97 268.75,-79.88 268.75,-79.88 268.75,-83.84 264.79,-87.8 260.83,-87.8"/>
<text text-anchor="middle" x="177.88" y="-70.5" font-family="Arial" font-size="14.00" fill="#ff6c60">client/src/helpers/desktop.js</text>
</g>
<!-- client/src/store/index.js -->
<g id="node6" class="node">
<title>client/src/store/index.js</title>
<path fill="none" stroke="#ff6c60" d="M682.58,-117.8C682.58,-117.8 545.92,-117.8 545.92,-117.8 541.96,-117.8 538,-113.84 538,-109.88 538,-109.88 538,-101.97 538,-101.97 538,-98.01 541.96,-94.05 545.92,-94.05 545.92,-94.05 682.58,-94.05 682.58,-94.05 686.54,-94.05 690.5,-98.01 690.5,-101.97 690.5,-101.97 690.5,-109.88 690.5,-109.88 690.5,-113.84 686.54,-117.8 682.58,-117.8"/>
<text text-anchor="middle" x="614.25" y="-100.5" font-family="Arial" font-size="14.00" fill="#ff6c60">client/src/store/index.js</text>
</g>
<!-- client/src/helpers/desktop.js&#45;&gt;client/src/store/index.js -->
<g id="edge6" class="edge">
<title>client/src/helpers/desktop.js&#45;&gt;client/src/store/index.js</title>
<path fill="none" stroke="#757575" d="M269.14,-82.16C344.68,-87.38 451.78,-94.77 526.36,-99.93"/>
<polygon fill="#757575" stroke="#757575" points="525.85,-103.4 536.07,-100.6 526.33,-96.42 525.85,-103.4"/>
</g>
<!-- client/src/store/HotkeyStore.js -->
<g id="node11" class="node">
<title>client/src/store/HotkeyStore.js</title>
<path fill="none" stroke="#ff6c60" d="M1132.08,-87.8C1132.08,-87.8 953.42,-87.8 953.42,-87.8 949.46,-87.8 945.5,-83.84 945.5,-79.88 945.5,-79.88 945.5,-71.97 945.5,-71.97 945.5,-68.01 949.46,-64.05 953.42,-64.05 953.42,-64.05 1132.08,-64.05 1132.08,-64.05 1136.04,-64.05 1140,-68.01 1140,-71.97 1140,-71.97 1140,-79.88 1140,-79.88 1140,-83.84 1136.04,-87.8 1132.08,-87.8"/>
<text text-anchor="middle" x="1042.75" y="-70.5" font-family="Arial" font-size="14.00" fill="#ff6c60">client/src/store/HotkeyStore.js</text>
</g>
<!-- client/src/store/index.js&#45;&gt;client/src/store/HotkeyStore.js -->
<g id="edge12" class="edge">
<title>client/src/store/index.js&#45;&gt;client/src/store/HotkeyStore.js</title>
<path fill="none" stroke="#757575" d="M690.52,-100.63C758.1,-95.88 858.08,-88.85 934.11,-83.5"/>
<polygon fill="#757575" stroke="#757575" points="933.9,-87.02 943.63,-82.83 933.41,-80.04 933.9,-87.02"/>
</g>
<!-- client/src/pages/FormGallery/TilesView/StyledTileView.js -->
<g id="node7" class="node">
<title>client/src/pages/FormGallery/TilesView/StyledTileView.js</title>
<path fill="none" stroke="#ff6c60" d="M347.83,-159.8C347.83,-159.8 7.92,-159.8 7.92,-159.8 3.96,-159.8 0,-155.84 0,-151.88 0,-151.88 0,-143.97 0,-143.97 0,-140.01 3.96,-136.05 7.92,-136.05 7.92,-136.05 347.83,-136.05 347.83,-136.05 351.79,-136.05 355.75,-140.01 355.75,-143.97 355.75,-143.97 355.75,-151.88 355.75,-151.88 355.75,-155.84 351.79,-159.8 347.83,-159.8"/>
<text text-anchor="middle" x="177.88" y="-142.5" font-family="Arial" font-size="14.00" fill="#ff6c60">client/src/pages/FormGallery/TilesView/StyledTileView.js</text>
</g>
<!-- client/src/pages/FormGallery/TilesView/sub&#45;components/TileContent.js -->
<g id="node8" class="node">
<title>client/src/pages/FormGallery/TilesView/sub&#45;components/TileContent.js</title>
<path fill="none" stroke="#ff6c60" d="M826.96,-159.8C826.96,-159.8 401.54,-159.8 401.54,-159.8 397.58,-159.8 393.62,-155.84 393.62,-151.88 393.62,-151.88 393.62,-143.97 393.62,-143.97 393.62,-140.01 397.58,-136.05 401.54,-136.05 401.54,-136.05 826.96,-136.05 826.96,-136.05 830.92,-136.05 834.88,-140.01 834.88,-143.97 834.88,-143.97 834.88,-151.88 834.88,-151.88 834.88,-155.84 830.92,-159.8 826.96,-159.8"/>
<text text-anchor="middle" x="614.25" y="-142.5" font-family="Arial" font-size="14.00" fill="#ff6c60">client/src/pages/FormGallery/TilesView/sub&#45;components/TileContent.js</text>
</g>
<!-- client/src/pages/FormGallery/TilesView/StyledTileView.js&#45;&gt;client/src/pages/FormGallery/TilesView/sub&#45;components/TileContent.js -->
<g id="edge7" class="edge">
<title>client/src/pages/FormGallery/TilesView/StyledTileView.js&#45;&gt;client/src/pages/FormGallery/TilesView/sub&#45;components/TileContent.js</title>
<path fill="none" stroke="#757575" d="M356.18,-141.28C364.66,-141.23 373.23,-141.2 381.82,-141.19"/>
<polygon fill="#757575" stroke="#757575" points="381.62,-144.69 391.62,-141.18 381.62,-137.69 381.62,-144.69"/>
</g>
<!-- client/src/pages/FormGallery/TilesView/sub&#45;components/TileContent.js&#45;&gt;client/src/pages/FormGallery/TilesView/StyledTileView.js -->
<g id="edge8" class="edge">
<title>client/src/pages/FormGallery/TilesView/sub&#45;components/TileContent.js&#45;&gt;client/src/pages/FormGallery/TilesView/StyledTileView.js</title>
<path fill="none" stroke="#757575" d="M393.13,-154.68C384.62,-154.67 376.11,-154.66 367.66,-154.62"/>
<polygon fill="#757575" stroke="#757575" points="367.71,-151.13 357.69,-154.58 367.68,-158.13 367.71,-151.13"/>
</g>
<!-- client/src/pages/PortalSettings/utils/index.js -->
<g id="node9" class="node">
<title>client/src/pages/PortalSettings/utils/index.js</title>
<path fill="none" stroke="#ff6c60" d="M307.33,-201.8C307.33,-201.8 48.42,-201.8 48.42,-201.8 44.46,-201.8 40.5,-197.84 40.5,-193.88 40.5,-193.88 40.5,-185.97 40.5,-185.97 40.5,-182.01 44.46,-178.05 48.42,-178.05 48.42,-178.05 307.33,-178.05 307.33,-178.05 311.29,-178.05 315.25,-182.01 315.25,-185.97 315.25,-185.97 315.25,-193.88 315.25,-193.88 315.25,-197.84 311.29,-201.8 307.33,-201.8"/>
<text text-anchor="middle" x="177.88" y="-184.5" font-family="Arial" font-size="14.00" fill="#ff6c60">client/src/pages/PortalSettings/utils/index.js</text>
</g>
<!-- client/src/pages/PortalSettings/utils/resetSessionStorage.js -->
<g id="node10" class="node">
<title>client/src/pages/PortalSettings/utils/resetSessionStorage.js</title>
<path fill="none" stroke="#ff6c60" d="M790.21,-201.8C790.21,-201.8 438.29,-201.8 438.29,-201.8 434.33,-201.8 430.38,-197.84 430.38,-193.88 430.38,-193.88 430.38,-185.97 430.38,-185.97 430.38,-182.01 434.33,-178.05 438.29,-178.05 438.29,-178.05 790.21,-178.05 790.21,-178.05 794.17,-178.05 798.12,-182.01 798.12,-185.97 798.12,-185.97 798.12,-193.88 798.12,-193.88 798.12,-197.84 794.17,-201.8 790.21,-201.8"/>
<text text-anchor="middle" x="614.25" y="-184.5" font-family="Arial" font-size="14.00" fill="#ff6c60">client/src/pages/PortalSettings/utils/resetSessionStorage.js</text>
</g>
<!-- client/src/pages/PortalSettings/utils/index.js&#45;&gt;client/src/pages/PortalSettings/utils/resetSessionStorage.js -->
<g id="edge9" class="edge">
<title>client/src/pages/PortalSettings/utils/index.js&#45;&gt;client/src/pages/PortalSettings/utils/resetSessionStorage.js</title>
<path fill="none" stroke="#757575" d="M315.72,-183.6C348.48,-183.24 384.08,-183.11 418.89,-183.21"/>
<polygon fill="#757575" stroke="#757575" points="418.63,-186.71 428.65,-183.25 418.66,-179.71 418.63,-186.71"/>
</g>
<!-- client/src/pages/PortalSettings/utils/resetSessionStorage.js&#45;&gt;client/src/pages/PortalSettings/utils/index.js -->
<g id="edge10" class="edge">
<title>client/src/pages/PortalSettings/utils/resetSessionStorage.js&#45;&gt;client/src/pages/PortalSettings/utils/index.js</title>
<path fill="none" stroke="#757575" d="M430.16,-196.6C395.71,-196.75 360.09,-196.67 326.88,-196.36"/>
<polygon fill="#757575" stroke="#757575" points="327.27,-192.87 317.23,-196.26 327.19,-199.87 327.27,-192.87"/>
</g>
<!-- client/src/store/HotkeyStore.js&#45;&gt;client/src/helpers/desktop.js -->
<g id="edge11" class="edge">
<title>client/src/store/HotkeyStore.js&#45;&gt;client/src/helpers/desktop.js</title>
<path fill="none" stroke="#757575" d="M945.26,-75.93C780.93,-75.93 448.24,-75.93 280.48,-75.93"/>
<polygon fill="#757575" stroke="#757575" points="280.69,-72.43 270.69,-75.93 280.69,-79.43 280.69,-72.43"/>
</g>
<!-- common/store/AuthStore.js -->
<g id="node12" class="node">
<title>common/store/AuthStore.js</title>
<path fill="none" stroke="#ff6c60" d="M260.08,-279.8C260.08,-279.8 95.67,-279.8 95.67,-279.8 91.71,-279.8 87.75,-275.84 87.75,-271.88 87.75,-271.88 87.75,-263.97 87.75,-263.97 87.75,-260.01 91.71,-256.05 95.67,-256.05 95.67,-256.05 260.08,-256.05 260.08,-256.05 264.04,-256.05 268,-260.01 268,-263.97 268,-263.97 268,-271.88 268,-271.88 268,-275.84 264.04,-279.8 260.08,-279.8"/>
<text text-anchor="middle" x="177.88" y="-262.5" font-family="Arial" font-size="14.00" fill="#ff6c60">common/store/AuthStore.js</text>
</g>
<!-- common/store/CurrentQuotaStore.js -->
<g id="node13" class="node">
<title>common/store/CurrentQuotaStore.js</title>
<path fill="none" stroke="#ff6c60" d="M723.83,-285.8C723.83,-285.8 504.67,-285.8 504.67,-285.8 500.71,-285.8 496.75,-281.84 496.75,-277.88 496.75,-277.88 496.75,-269.97 496.75,-269.97 496.75,-266.01 500.71,-262.05 504.67,-262.05 504.67,-262.05 723.83,-262.05 723.83,-262.05 727.79,-262.05 731.75,-266.01 731.75,-269.97 731.75,-269.97 731.75,-277.88 731.75,-277.88 731.75,-281.84 727.79,-285.8 723.83,-285.8"/>
<text text-anchor="middle" x="614.25" y="-268.5" font-family="Arial" font-size="14.00" fill="#ff6c60">common/store/CurrentQuotaStore.js</text>
</g>
<!-- common/store/AuthStore.js&#45;&gt;common/store/CurrentQuotaStore.js -->
<g id="edge13" class="edge">
<title>common/store/AuthStore.js&#45;&gt;common/store/CurrentQuotaStore.js</title>
<path fill="none" stroke="#757575" d="M268.35,-263.58C330.93,-263.14 415.45,-264.1 485.15,-265.94"/>
<polygon fill="#757575" stroke="#757575" points="485.05,-269.44 495.14,-266.21 485.24,-262.44 485.05,-269.44"/>
</g>
<!-- common/store/CurrentTariffStatusStore.js -->
<g id="node14" class="node">
<title>common/store/CurrentTariffStatusStore.js</title>
<path fill="none" stroke="#ff6c60" d="M738.83,-243.8C738.83,-243.8 489.67,-243.8 489.67,-243.8 485.71,-243.8 481.75,-239.84 481.75,-235.88 481.75,-235.88 481.75,-227.97 481.75,-227.97 481.75,-224.01 485.71,-220.05 489.67,-220.05 489.67,-220.05 738.83,-220.05 738.83,-220.05 742.79,-220.05 746.75,-224.01 746.75,-227.97 746.75,-227.97 746.75,-235.88 746.75,-235.88 746.75,-239.84 742.79,-243.8 738.83,-243.8"/>
<text text-anchor="middle" x="614.25" y="-226.5" font-family="Arial" font-size="14.00" fill="#ff6c60">common/store/CurrentTariffStatusStore.js</text>
</g>
<!-- common/store/AuthStore.js&#45;&gt;common/store/CurrentTariffStatusStore.js -->
<g id="edge14" class="edge">
<title>common/store/AuthStore.js&#45;&gt;common/store/CurrentTariffStatusStore.js</title>
<path fill="none" stroke="#757575" d="M262.37,-255.55C321.08,-249.37 401.12,-242.42 469.94,-237.41"/>
<polygon fill="#757575" stroke="#757575" points="470.08,-240.91 479.81,-236.7 469.58,-233.93 470.08,-240.91"/>
</g>
<!-- common/store/CurrentQuotaStore.js&#45;&gt;common/store/AuthStore.js -->
<g id="edge15" class="edge">
<title>common/store/CurrentQuotaStore.js&#45;&gt;common/store/AuthStore.js</title>
<path fill="none" stroke="#757575" d="M496.65,-278.38C428.99,-278.44 344.61,-277.19 279.8,-275.12"/>
<polygon fill="#757575" stroke="#757575" points="279.97,-271.63 269.86,-274.79 279.74,-278.62 279.97,-271.63"/>
</g>
<!-- common/store/CurrentTariffStatusStore.js&#45;&gt;common/store/AuthStore.js -->
<g id="edge16" class="edge">
<title>common/store/CurrentTariffStatusStore.js&#45;&gt;common/store/AuthStore.js</title>
<path fill="none" stroke="#757575" d="M529.78,-244.3C458.49,-251.81 355.73,-260.44 279.82,-265.36"/>
<polygon fill="#757575" stroke="#757575" points="279.62,-261.87 269.86,-266 280.06,-268.86 279.62,-261.87"/>
</g>
<!-- components/ColorTheme/ColorTheme.js -->
<g id="node15" class="node">
<title>components/ColorTheme/ColorTheme.js</title>
<path fill="none" stroke="#ff6c60" d="M300.58,-341.8C300.58,-341.8 55.17,-341.8 55.17,-341.8 51.21,-341.8 47.25,-337.84 47.25,-333.88 47.25,-333.88 47.25,-325.97 47.25,-325.97 47.25,-322.01 51.21,-318.05 55.17,-318.05 55.17,-318.05 300.58,-318.05 300.58,-318.05 304.54,-318.05 308.5,-322.01 308.5,-325.97 308.5,-325.97 308.5,-333.88 308.5,-333.88 308.5,-337.84 304.54,-341.8 300.58,-341.8"/>
<text text-anchor="middle" x="177.88" y="-324.5" font-family="Arial" font-size="14.00" fill="#ff6c60">components/ColorTheme/ColorTheme.js</text>
</g>
<!-- components/ColorTheme/styled/index.js -->
<g id="node16" class="node">
<title>components/ColorTheme/styled/index.js</title>
<path fill="none" stroke="#ff6c60" d="M735.08,-414.8C735.08,-414.8 493.42,-414.8 493.42,-414.8 489.46,-414.8 485.5,-410.84 485.5,-406.88 485.5,-406.88 485.5,-398.97 485.5,-398.97 485.5,-395.01 489.46,-391.05 493.42,-391.05 493.42,-391.05 735.08,-391.05 735.08,-391.05 739.04,-391.05 743,-395.01 743,-398.97 743,-398.97 743,-406.88 743,-406.88 743,-410.84 739.04,-414.8 735.08,-414.8"/>
<text text-anchor="middle" x="614.25" y="-397.5" font-family="Arial" font-size="14.00" fill="#ff6c60">components/ColorTheme/styled/index.js</text>
</g>
<!-- components/ColorTheme/ColorTheme.js&#45;&gt;components/ColorTheme/styled/index.js -->
<g id="edge17" class="edge">
<title>components/ColorTheme/ColorTheme.js&#45;&gt;components/ColorTheme/styled/index.js</title>
<path fill="none" stroke="#757575" d="M252.07,-342.23C328.51,-355.07 448.25,-375.2 528.68,-388.71"/>
<polygon fill="#757575" stroke="#757575" points="527.82,-392.12 538.26,-390.32 528.98,-385.22 527.82,-392.12"/>
</g>
<!-- components/ColorTheme/styled/mainButton.js -->
<g id="node18" class="node">
<title>components/ColorTheme/styled/mainButton.js</title>
<path fill="none" stroke="#ff6c60" d="M1181.96,-456.8C1181.96,-456.8 903.54,-456.8 903.54,-456.8 899.58,-456.8 895.62,-452.84 895.62,-448.88 895.62,-448.88 895.62,-440.97 895.62,-440.97 895.62,-437.01 899.58,-433.05 903.54,-433.05 903.54,-433.05 1181.96,-433.05 1181.96,-433.05 1185.92,-433.05 1189.88,-437.01 1189.88,-440.97 1189.88,-440.97 1189.88,-448.88 1189.88,-448.88 1189.88,-452.84 1185.92,-456.8 1181.96,-456.8"/>
<text text-anchor="middle" x="1042.75" y="-439.5" font-family="Arial" font-size="14.00" fill="#ff6c60">components/ColorTheme/styled/mainButton.js</text>
</g>
<!-- components/ColorTheme/styled/index.js&#45;&gt;components/ColorTheme/styled/mainButton.js -->
<g id="edge19" class="edge">
<title>components/ColorTheme/styled/index.js&#45;&gt;components/ColorTheme/styled/mainButton.js</title>
<path fill="none" stroke="#757575" d="M740.91,-415.3C792.52,-420.38 852.42,-426.28 905.12,-431.47"/>
<polygon fill="#757575" stroke="#757575" points="904.45,-434.92 914.75,-432.42 905.14,-427.96 904.45,-434.92"/>
</g>
<!-- components/ColorTheme/styled/mobileProgressBar.js -->
<g id="node19" class="node">
<title>components/ColorTheme/styled/mobileProgressBar.js</title>
<path fill="none" stroke="#ff6c60" d="M1204.83,-414.8C1204.83,-414.8 880.67,-414.8 880.67,-414.8 876.71,-414.8 872.75,-410.84 872.75,-406.88 872.75,-406.88 872.75,-398.97 872.75,-398.97 872.75,-395.01 876.71,-391.05 880.67,-391.05 880.67,-391.05 1204.83,-391.05 1204.83,-391.05 1208.79,-391.05 1212.75,-395.01 1212.75,-398.97 1212.75,-398.97 1212.75,-406.88 1212.75,-406.88 1212.75,-410.84 1208.79,-414.8 1204.83,-414.8"/>
<text text-anchor="middle" x="1042.75" y="-397.5" font-family="Arial" font-size="14.00" fill="#ff6c60">components/ColorTheme/styled/mobileProgressBar.js</text>
</g>
<!-- components/ColorTheme/styled/index.js&#45;&gt;components/ColorTheme/styled/mobileProgressBar.js -->
<g id="edge20" class="edge">
<title>components/ColorTheme/styled/index.js&#45;&gt;components/ColorTheme/styled/mobileProgressBar.js</title>
<path fill="none" stroke="#757575" d="M743.21,-402.93C780.25,-402.93 821.4,-402.93 861.02,-402.93"/>
<polygon fill="#757575" stroke="#757575" points="860.91,-406.43 870.91,-402.93 860.91,-399.43 860.91,-406.43"/>
</g>
<!-- components/ColorTheme/index.js -->
<g id="node17" class="node">
<title>components/ColorTheme/index.js</title>
<path fill="none" stroke="#ff6c60" d="M2692.58,-376.8C2692.58,-376.8 2489.92,-376.8 2489.92,-376.8 2485.96,-376.8 2482,-372.84 2482,-368.88 2482,-368.88 2482,-360.97 2482,-360.97 2482,-357.01 2485.96,-353.05 2489.92,-353.05 2489.92,-353.05 2692.58,-353.05 2692.58,-353.05 2696.54,-353.05 2700.5,-357.01 2700.5,-360.97 2700.5,-360.97 2700.5,-368.88 2700.5,-368.88 2700.5,-372.84 2696.54,-376.8 2692.58,-376.8"/>
<text text-anchor="middle" x="2591.25" y="-359.5" font-family="Arial" font-size="14.00" fill="#ff6c60">components/ColorTheme/index.js</text>
</g>
<!-- components/ColorTheme/index.js&#45;&gt;components/ColorTheme/ColorTheme.js -->
<g id="edge18" class="edge">
<title>components/ColorTheme/index.js&#45;&gt;components/ColorTheme/ColorTheme.js</title>
<path fill="none" stroke="#757575" d="M2515.55,-352.59C2493.24,-349.3 2468.68,-346.07 2446,-343.93 2252.78,-325.7 2203.82,-324.93 2009.75,-324.93 1041.75,-324.93 1041.75,-324.93 1041.75,-324.93 787.55,-324.93 491.22,-327.12 320.31,-328.6"/>
<polygon fill="#757575" stroke="#757575" points="320.46,-325.1 310.49,-328.69 320.52,-332.1 320.46,-325.1"/>
</g>
<!-- components/main&#45;button/styled&#45;main&#45;button.js -->
<g id="node20" class="node">
<title>components/main&#45;button/styled&#45;main&#45;button.js</title>
<path fill="none" stroke="#ff6c60" d="M1558.33,-456.8C1558.33,-456.8 1279.17,-456.8 1279.17,-456.8 1275.21,-456.8 1271.25,-452.84 1271.25,-448.88 1271.25,-448.88 1271.25,-440.97 1271.25,-440.97 1271.25,-437.01 1275.21,-433.05 1279.17,-433.05 1279.17,-433.05 1558.33,-433.05 1558.33,-433.05 1562.29,-433.05 1566.25,-437.01 1566.25,-440.97 1566.25,-440.97 1566.25,-448.88 1566.25,-448.88 1566.25,-452.84 1562.29,-456.8 1558.33,-456.8"/>
<text text-anchor="middle" x="1418.75" y="-439.5" font-family="Arial" font-size="14.00" fill="#ff6c60">components/main&#45;button/styled&#45;main&#45;button.js</text>
</g>
<!-- components/ColorTheme/styled/mainButton.js&#45;&gt;components/main&#45;button/styled&#45;main&#45;button.js -->
<g id="edge21" class="edge">
<title>components/ColorTheme/styled/mainButton.js&#45;&gt;components/main&#45;button/styled&#45;main&#45;button.js</title>
<path fill="none" stroke="#757575" d="M1190.22,-444.93C1213.01,-444.93 1236.64,-444.93 1259.67,-444.93"/>
<polygon fill="#757575" stroke="#757575" points="1259.41,-448.43 1269.41,-444.93 1259.41,-441.43 1259.41,-448.43"/>
</g>
<!-- components/main&#45;button&#45;mobile/styled&#45;main&#45;button.js -->
<g id="node21" class="node">
<title>components/main&#45;button&#45;mobile/styled&#45;main&#45;button.js</title>
<path fill="none" stroke="#ff6c60" d="M1580.83,-414.8C1580.83,-414.8 1256.67,-414.8 1256.67,-414.8 1252.71,-414.8 1248.75,-410.84 1248.75,-406.88 1248.75,-406.88 1248.75,-398.97 1248.75,-398.97 1248.75,-395.01 1252.71,-391.05 1256.67,-391.05 1256.67,-391.05 1580.83,-391.05 1580.83,-391.05 1584.79,-391.05 1588.75,-395.01 1588.75,-398.97 1588.75,-398.97 1588.75,-406.88 1588.75,-406.88 1588.75,-410.84 1584.79,-414.8 1580.83,-414.8"/>
<text text-anchor="middle" x="1418.75" y="-397.5" font-family="Arial" font-size="14.00" fill="#ff6c60">components/main&#45;button&#45;mobile/styled&#45;main&#45;button.js</text>
</g>
<!-- components/ColorTheme/styled/mobileProgressBar.js&#45;&gt;components/main&#45;button&#45;mobile/styled&#45;main&#45;button.js -->
<g id="edge22" class="edge">
<title>components/ColorTheme/styled/mobileProgressBar.js&#45;&gt;components/main&#45;button&#45;mobile/styled&#45;main&#45;button.js</title>
<path fill="none" stroke="#757575" d="M1213.24,-402.93C1221.19,-402.93 1229.18,-402.93 1237.15,-402.93"/>
<polygon fill="#757575" stroke="#757575" points="1236.9,-406.43 1246.9,-402.93 1236.9,-399.43 1236.9,-406.43"/>
</g>
<!-- components/drop&#45;down/index.js -->
<g id="node24" class="node">
<title>components/drop&#45;down/index.js</title>
<path fill="none" stroke="#ff6c60" d="M1834.96,-456.8C1834.96,-456.8 1643.54,-456.8 1643.54,-456.8 1639.58,-456.8 1635.62,-452.84 1635.62,-448.88 1635.62,-448.88 1635.62,-440.97 1635.62,-440.97 1635.62,-437.01 1639.58,-433.05 1643.54,-433.05 1643.54,-433.05 1834.96,-433.05 1834.96,-433.05 1838.92,-433.05 1842.88,-437.01 1842.88,-440.97 1842.88,-440.97 1842.88,-448.88 1842.88,-448.88 1842.88,-452.84 1838.92,-456.8 1834.96,-456.8"/>
<text text-anchor="middle" x="1739.25" y="-439.5" font-family="Arial" font-size="14.00" fill="#ff6c60">components/drop&#45;down/index.js</text>
</g>
<!-- components/main&#45;button/styled&#45;main&#45;button.js&#45;&gt;components/drop&#45;down/index.js -->
<g id="edge30" class="edge">
<title>components/main&#45;button/styled&#45;main&#45;button.js&#45;&gt;components/drop&#45;down/index.js</title>
<path fill="none" stroke="#757575" d="M1566.41,-444.93C1585.75,-444.93 1605.33,-444.93 1624.01,-444.93"/>
<polygon fill="#757575" stroke="#757575" points="1624.01,-448.43 1634.01,-444.93 1624.01,-441.43 1624.01,-448.43"/>
</g>
<!-- components/drop&#45;down&#45;item/index.js -->
<g id="node22" class="node">
<title>components/drop&#45;down&#45;item/index.js</title>
<path fill="none" stroke="#ff6c60" d="M2119.83,-418.8C2119.83,-418.8 1897.67,-418.8 1897.67,-418.8 1893.71,-418.8 1889.75,-414.84 1889.75,-410.88 1889.75,-410.88 1889.75,-402.97 1889.75,-402.97 1889.75,-399.01 1893.71,-395.05 1897.67,-395.05 1897.67,-395.05 2119.83,-395.05 2119.83,-395.05 2123.79,-395.05 2127.75,-399.01 2127.75,-402.97 2127.75,-402.97 2127.75,-410.88 2127.75,-410.88 2127.75,-414.84 2123.79,-418.8 2119.83,-418.8"/>
<text text-anchor="middle" x="2008.75" y="-401.5" font-family="Arial" font-size="14.00" fill="#ff6c60">components/drop&#45;down&#45;item/index.js</text>
</g>
<!-- components/main&#45;button&#45;mobile/styled&#45;main&#45;button.js&#45;&gt;components/drop&#45;down&#45;item/index.js -->
<g id="edge27" class="edge">
<title>components/main&#45;button&#45;mobile/styled&#45;main&#45;button.js&#45;&gt;components/drop&#45;down&#45;item/index.js</title>
<path fill="none" stroke="#757575" d="M1589.04,-404.08C1681.09,-404.7 1793.16,-405.47 1878.18,-406.05"/>
<polygon fill="#757575" stroke="#757575" points="1877.93,-409.54 1887.96,-406.11 1877.98,-402.54 1877.93,-409.54"/>
</g>
<!-- components/main&#45;button&#45;mobile/styled&#45;main&#45;button.js&#45;&gt;components/drop&#45;down/index.js -->
<g id="edge28" class="edge">
<title>components/main&#45;button&#45;mobile/styled&#45;main&#45;button.js&#45;&gt;components/drop&#45;down/index.js</title>
<path fill="none" stroke="#757575" d="M1521.21,-415.27C1543.47,-418.05 1566.91,-421.04 1588.75,-423.93 1605.59,-426.16 1623.48,-428.6 1640.82,-431.01"/>
<polygon fill="#757575" stroke="#757575" points="1640.22,-434.46 1650.61,-432.38 1641.19,-427.53 1640.22,-434.46"/>
</g>
<!-- components/floating&#45;button/index.js -->
<g id="node26" class="node">
<title>components/floating&#45;button/index.js</title>
<path fill="none" stroke="#ff6c60" d="M1845.83,-376.8C1845.83,-376.8 1632.67,-376.8 1632.67,-376.8 1628.71,-376.8 1624.75,-372.84 1624.75,-368.88 1624.75,-368.88 1624.75,-360.97 1624.75,-360.97 1624.75,-357.01 1628.71,-353.05 1632.67,-353.05 1632.67,-353.05 1845.83,-353.05 1845.83,-353.05 1849.79,-353.05 1853.75,-357.01 1853.75,-360.97 1853.75,-360.97 1853.75,-368.88 1853.75,-368.88 1853.75,-372.84 1849.79,-376.8 1845.83,-376.8"/>
<text text-anchor="middle" x="1739.25" y="-359.5" font-family="Arial" font-size="14.00" fill="#ff6c60">components/floating&#45;button/index.js</text>
</g>
<!-- components/main&#45;button&#45;mobile/styled&#45;main&#45;button.js&#45;&gt;components/floating&#45;button/index.js -->
<g id="edge29" class="edge">
<title>components/main&#45;button&#45;mobile/styled&#45;main&#45;button.js&#45;&gt;components/floating&#45;button/index.js</title>
<path fill="none" stroke="#757575" d="M1523.16,-390.59C1555.23,-386.76 1590.75,-382.52 1623.54,-378.61"/>
<polygon fill="#757575" stroke="#757575" points="1623.53,-382.14 1633.04,-377.48 1622.7,-375.19 1623.53,-382.14"/>
</g>
<!-- components/toggle&#45;button/index.js -->
<g id="node23" class="node">
<title>components/toggle&#45;button/index.js</title>
<path fill="none" stroke="#ff6c60" d="M2408.08,-418.8C2408.08,-418.8 2201.67,-418.8 2201.67,-418.8 2197.71,-418.8 2193.75,-414.84 2193.75,-410.88 2193.75,-410.88 2193.75,-402.97 2193.75,-402.97 2193.75,-399.01 2197.71,-395.05 2201.67,-395.05 2201.67,-395.05 2408.08,-395.05 2408.08,-395.05 2412.04,-395.05 2416,-399.01 2416,-402.97 2416,-402.97 2416,-410.88 2416,-410.88 2416,-414.84 2412.04,-418.8 2408.08,-418.8"/>
<text text-anchor="middle" x="2304.88" y="-401.5" font-family="Arial" font-size="14.00" fill="#ff6c60">components/toggle&#45;button/index.js</text>
</g>
<!-- components/drop&#45;down&#45;item/index.js&#45;&gt;components/toggle&#45;button/index.js -->
<g id="edge23" class="edge">
<title>components/drop&#45;down&#45;item/index.js&#45;&gt;components/toggle&#45;button/index.js</title>
<path fill="none" stroke="#757575" d="M2128.11,-406.93C2145.87,-406.93 2164.22,-406.93 2182.05,-406.93"/>
<polygon fill="#757575" stroke="#757575" points="2181.86,-410.43 2191.86,-406.93 2181.86,-403.43 2181.86,-410.43"/>
</g>
<!-- components/toggle&#45;button/index.js&#45;&gt;components/ColorTheme/index.js -->
<g id="edge31" class="edge">
<title>components/toggle&#45;button/index.js&#45;&gt;components/ColorTheme/index.js</title>
<path fill="none" stroke="#757575" d="M2389.66,-394.55C2422.92,-389.64 2461.35,-383.96 2495.61,-378.9"/>
<polygon fill="#757575" stroke="#757575" points="2495.7,-382.43 2505.08,-377.51 2494.67,-375.5 2495.7,-382.43"/>
</g>
<!-- components/drop&#45;down/index.js&#45;&gt;components/drop&#45;down&#45;item/index.js -->
<g id="edge24" class="edge">
<title>components/drop&#45;down/index.js&#45;&gt;components/drop&#45;down&#45;item/index.js</title>
<path fill="none" stroke="#757575" d="M1827.1,-432.59C1853.51,-428.84 1882.72,-424.69 1909.81,-420.84"/>
<polygon fill="#757575" stroke="#757575" points="1909.97,-424.35 1919.38,-419.48 1908.99,-417.42 1909.97,-424.35"/>
</g>
<!-- components/floating&#45;button/floating&#45;button.js -->
<g id="node25" class="node">
<title>components/floating&#45;button/floating&#45;button.js</title>
<path fill="none" stroke="#ff6c60" d="M2438.08,-376.8C2438.08,-376.8 2171.67,-376.8 2171.67,-376.8 2167.71,-376.8 2163.75,-372.84 2163.75,-368.88 2163.75,-368.88 2163.75,-360.97 2163.75,-360.97 2163.75,-357.01 2167.71,-353.05 2171.67,-353.05 2171.67,-353.05 2438.08,-353.05 2438.08,-353.05 2442.04,-353.05 2446,-357.01 2446,-360.97 2446,-360.97 2446,-368.88 2446,-368.88 2446,-372.84 2442.04,-376.8 2438.08,-376.8"/>
<text text-anchor="middle" x="2304.88" y="-359.5" font-family="Arial" font-size="14.00" fill="#ff6c60">components/floating&#45;button/floating&#45;button.js</text>
</g>
<!-- components/floating&#45;button/floating&#45;button.js&#45;&gt;components/ColorTheme/index.js -->
<g id="edge25" class="edge">
<title>components/floating&#45;button/floating&#45;button.js&#45;&gt;components/ColorTheme/index.js</title>
<path fill="none" stroke="#757575" d="M2446.4,-364.93C2454.39,-364.93 2462.39,-364.93 2470.29,-364.93"/>
<polygon fill="#757575" stroke="#757575" points="2470.28,-368.43 2480.28,-364.93 2470.28,-361.43 2470.28,-368.43"/>
</g>
<!-- components/floating&#45;button/index.js&#45;&gt;components/floating&#45;button/floating&#45;button.js -->
<g id="edge26" class="edge">
<title>components/floating&#45;button/index.js&#45;&gt;components/floating&#45;button/floating&#45;button.js</title>
<path fill="none" stroke="#757575" d="M1853.97,-364.93C1939.72,-364.93 2058.19,-364.93 2152.03,-364.93"/>
<polygon fill="#757575" stroke="#757575" points="2151.84,-368.43 2161.84,-364.93 2151.84,-361.43 2151.84,-368.43"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 33 KiB

View File

@ -144317,6 +144317,126 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>WebhookCreated</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
<approved>false</approved>
</translation>
<translation>
<language>az-Latn-AZ</language>
<approved>false</approved>
</translation>
<translation>
<language>bg-BG</language>
<approved>false</approved>
</translation>
<translation>
<language>cs-CZ</language>
<approved>false</approved>
</translation>
<translation>
<language>de-DE</language>
<approved>false</approved>
</translation>
<translation>
<language>el-GR</language>
<approved>false</approved>
</translation>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-ES</language>
<approved>false</approved>
</translation>
<translation>
<language>fi-FI</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-FR</language>
<approved>false</approved>
</translation>
<translation>
<language>hy-AM</language>
<approved>false</approved>
</translation>
<translation>
<language>it-IT</language>
<approved>false</approved>
</translation>
<translation>
<language>ja-JP</language>
<approved>false</approved>
</translation>
<translation>
<language>ko-KR</language>
<approved>false</approved>
</translation>
<translation>
<language>lo-LA</language>
<approved>false</approved>
</translation>
<translation>
<language>lv-LV</language>
<approved>false</approved>
</translation>
<translation>
<language>nl-NL</language>
<approved>false</approved>
</translation>
<translation>
<language>pl-PL</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-BR</language>
<approved>false</approved>
</translation>
<translation>
<language>pt-PT</language>
<approved>false</approved>
</translation>
<translation>
<language>ro-RO</language>
<approved>false</approved>
</translation>
<translation>
<language>ru-RU</language>
<approved>false</approved>
</translation>
<translation>
<language>sk-SK</language>
<approved>false</approved>
</translation>
<translation>
<language>sl-SI</language>
<approved>false</approved>
</translation>
<translation>
<language>tr-TR</language>
<approved>false</approved>
</translation>
<translation>
<language>uk-UA</language>
<approved>false</approved>
</translation>
<translation>
<language>vi-VN</language>
<approved>false</approved>
</translation>
<translation>
<language>zh-CN</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>WebhookCreationHint</name>
<description/>

View File

@ -1,6 +1,6 @@
{
"name": "docspace",
"version": "2.0.1",
"version": "2.0.2",
"private": true,
"workspaces": {
"packages": [
@ -8,8 +8,8 @@
]
},
"engines": {
"node": ">=18",
"yarn": ">=3"
"node": ">=20",
"yarn": ">=4"
},
"scripts": {
"build": "node ./common/scripts/before-build.js && yarn workspaces foreach -vptiR --from '{@docspace/client,@docspace/login,@docspace/editor,@docspace/management}' run build",
@ -44,5 +44,5 @@
"shx": "^0.3.4",
"terser": "^5.16.6"
},
"packageManager": "yarn@3.2.4"
"packageManager": "yarn@4.0.2"
}

View File

@ -0,0 +1,15 @@
module.exports = {
extends: "../shared/.eslintrc.cjs",
parserOptions: {
project: "tsconfig.eslint.json",
tsconfigRootDir: __dirname,
sourceType: "module",
},
ignorePatterns: [
"./tsconfig.json",
"coverage/**",
"storybook-static/**",
"*.js",
],
};

View File

@ -0,0 +1,3 @@
{
"extends": "../shared/.prettierrc.json"
}

View File

@ -1,5 +1,5 @@
interface Window {
zESettings?: any;
zESettings?: unknown;
zE?: {
apply: Function;
};

View File

@ -1,6 +1,6 @@
{
"name": "@docspace/client",
"version": "2.0.1",
"version": "2.0.2",
"private": true,
"homepage": "",
"scripts": {
@ -59,6 +59,7 @@
},
"devDependencies": {
"@babel/core": "^7.21.3",
"@babel/eslint-parser": "^7.21.8",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-proposal-export-default-from": "^7.18.10",
"@babel/plugin-transform-runtime": "^7.21.0",
@ -66,16 +67,30 @@
"@babel/preset-react": "^7.18.6",
"@babel/preset-typescript": "^7.21.0",
"@svgr/webpack": "^5.5.0",
"@types/eslint": "^8.44.7",
"@typescript-eslint/eslint-plugin": "^6.12.0",
"@typescript-eslint/parser": "^6.12.0",
"babel-loader": "^8.3.0",
"clean-webpack-plugin": "^4.0.0",
"copy-webpack-plugin": "^9.1.0",
"css-loader": "^6.7.3",
"eslint": "^8.54.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^17.1.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-import": "^2.29.0",
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-prettier": "^5.0.1",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-storybook": "^0.6.15",
"external-remotes-plugin": "^1.0.0",
"file-loader": "^6.2.0",
"html-loader": "^4.2.0",
"html-webpack-plugin": "5.5.0",
"json-loader": "^0.5.7",
"playwright": "^1.32.0",
"prettier": "^3.1.0",
"sass": "^1.59.3",
"sass-loader": "^12.6.0",
"serve": "14.2.0",

View File

@ -38,7 +38,7 @@
"BackupCreatedSuccess": "تم إنشاء النسخة الاحتياطية بنجاح.",
"BackupList": "قائمة النسخ الاحتياطي",
"BackupListWarningText": "إذا قمت بحذف أي عناصر من القائمة ، فسيتم أيضًا حذف الملفات المقابلة لها. لا يمكن التراجع عن هذا الإجراء. لحذف جميع الملفات استخدم الرابط:",
"BetaLabel": "بيتا",
"BetaLabel": "BETA",
"BlockingTime": "وقت الحظر (بالثانية)",
"Branding": "العلامة التجارية",
"BrandingSectionDescription": "حدد معلومات شركتك، وأضف روابط إلى الموارد الخارجية وعناوين البريد الإلكتروني المعروضة في واجهة DocSpace.",

View File

@ -8,12 +8,16 @@
"CustomRoomTitle": "Custom room",
"FillingFormsRoomDescription": "Build, share and fill document templates or work with the ready presets to quickly create documents of any type.",
"FillingFormsRoomTitle": "Filling forms room",
"FormRoomDescription": "Share forms with anyone and collect the complete forms in the Complete folder. Users can fill out any form multiple times creating separate final files. In Basic form rooms, you can't add multiple user roles to the forms.",
"FormRoomTitle": "Basic form room",
"Icon": "Icon",
"MakeRoomPrivateDescription": "All files in this room will be encrypted.",
"MakeRoomPrivateLimitationsWarningDescription": "With this feature, you can invite only existing DocSpace users. After creating a room, you will not be able to change the list of users.",
"MakeRoomPrivateTitle": "Make the Room Private",
"PublicRoomBarDescription": "This room is available to anyone with the link. External users will have View Only permission for all the files.",
"PublicRoomDescription": "Invite users via external links to view documents without registration. You can also embed this room into any web interface.",
"PublicRoomSystemFoldersDescription": "System folders store copies of forms at different stages of completion. Forms that are being filled are stored in In progress folder, and completed forms are stored in Complete folder.",
"PublicRoomSystemFoldersTitle": "System Folders",
"ReviewRoomDescription": "Request a review or comments on the documents",
"ReviewRoomTitle": "Review room",
"RoomEditing": "Room editing",

View File

@ -15,6 +15,8 @@
"ArchiveEmptyScreenUser": "Rooms that have been archived will appear here.",
"Archives": "Archives",
"AssignOwner": "Assign Owner",
"BadgeAlertDescription": "Several roles are specified in this form. Forms with multiple roles are not available for filling in this type of room",
"BadgeMyDraftTitle": "My draft",
"BackToParentFolderButton": "Back to parent folder",
"ByAuthor": "Author",
"ByCreation": "Created",
@ -56,6 +58,14 @@
"EmptyFilterSubheadingText": "No files to be displayed for this filter here",
"EmptyFolderDecription": "Drop files here or create new ones",
"EmptyFolderDescriptionUser": "Files and folders uploaded by admins will appear here.",
"EmptyFolderHeader": "No files in this folder",
"EmptyFormFolderDoneHeaderText": "No finished forms yet",
"EmptyFormFolderDoneDescriptionText": "This section will display all forms that are complete.",
"EmptyFormFolderProgressHeaderText": "Nothing here yet",
"EmptyFormFolderProgressDescriptionText": "This section will display the forms in progress.",
"EmptyFormSubFolderHeaderText": "No files in this folder yet",
"EmptyFormSubFolderDoneDescriptionText": "Here you will find forms which have been completely filled out by other users.",
"EmptyFormSubFolderProgressDescriptionText": "Here you will find forms in progress, i.e. forms which users have started to fill out but haven't completed. ",
"EmptyRecycleBin": "Empty Trash",
"EmptyRootRoomHeader": "Welcome to DocSpace",
"EmptyScreenFolder": "No docs here yet",
@ -72,6 +82,7 @@
"Folder": "Folder",
"FolderRemoved": "Folder moved to Trash",
"FolderRenamed": "The folder '{{folderTitle}}' is renamed to '{{newFoldedTitle}}'",
"FormRoom": "Form room",
"Forms": "Forms",
"FormsTemplates": "Forms templates",
"GeneralLink": "General link",
@ -106,6 +117,7 @@
"MoveToFolderMessage": "You can't move the folder to its subfolder",
"MoveToPublicRoom": "This room and all its contents are available to anyone with the link. Do you want to continue?",
"MoveToPublicRoomTitle": "Move to Public room",
"MyDocuments": "My documents",
"New": "New",
"NewRoom": "New room",
"NoAccessRoomDescription": "You will be redirected to the My Rooms automatically in 5 seconds.",
@ -128,7 +140,9 @@
"PrivateRoomHeader": "Welcome to ONLYOFFICE private room where every symbol you type is encrypted",
"PrivateRoomSupport": "Work in Private Room is available via {{organizationName}} desktop app. <3>Instructions</3>",
"PublicRoom": "Public room",
"RecentlyAccessible": "Recently accessible via link",
"RecentEmptyContainerDescription": "Your last viewed or edited docs will be displayed in this section.",
"RecentViaLinkEmptyContainerDescription": "Here you will find a list of the recently opened files shared with you via an external link.",
"RecycleBinAction": "Empty trash",
"RemovedFromFavorites": "Removed from favorites",
"RemoveFromFavorites": "Remove from favorites",
@ -152,6 +166,8 @@
"SelectorEmptyScreenHeader": "No files and folders here yet",
"SendByEmail": "Send by email",
"Share": "Share",
"ShareFolder": "Share folder",
"ShareFolderDescription": "A new room will be created and all the contents of the selected folder will be copied there. Afterwards, you can invite other users to collaborate on the files within a room.",
"ShareRoom": "Share room",
"ShowLinkActions": "Show link actions",
"ShowVersionHistory": "Show version history",

View File

@ -1,19 +1,35 @@
{
"AddGroupsForSharingButton": "Add groups",
"AddShareMessage": "Add message",
"AdditionalLinks": "Additional links",
"AdditionalLinkRemove": "Additional link remove",
"AnyoneWithLink": "Anyone with the link",
"Comment": "Comment",
"CopyExternalLink": "Copy external link",
"CreateAndCopy": "Create and copy",
"CustomFilter": "Custom filter",
"DenyAccess": "Deny access",
"DoсSpaceUsersOnly": "DoсSpace users only",
"Editing": "Editing",
"EncryptedFileSharing": "File <strong>{{title}}</strong> successfully shared",
"ExternalLink": "External link",
"FormFilling": "Form filling",
"GeneralAccessLink": "General access link",
"GeneralAccessLinkCopied": "General link successfully copied to clipboard",
"GeneralAccessLinkCreated": "General link for public viewing successfully created and copied to clipboard",
"GeneralAccessLinkRemove": "General access link remove",
"InternalLink": "Internal link",
"LinkAccessDenied": "Access to the link has been denied",
"LinkName": "Link name",
"LinkExpireAfter": "The link will expire after <1>{{date}}</1>",
"LinkExpired": "The link has expired.",
"LinkIsValid": "The link is valid for <1>{{date}}</1>",
"Notify users": "Notify users",
"ReadOnly": "Read only",
"ShareEmailBody": "You have been granted access to the {{itemName}} document. Click the link below to open the document right now: {{shareLink}}.",
"ShareEmailSubject": "You have been granted access to the {{itemName}} document",
"ShareDocument": "Share this document",
"ShareDocumentDescription": "Provide access to the document and set the permission levels.",
"ShareVia": "Share via",
"SharingSettingsTitle": "Sharing settings"
}

View File

@ -45,6 +45,7 @@
"UnselectAll": "Unselect all",
"URL": "URL",
"ViewRawPayload": "View raw payload",
"WebhookCreated": "Webhook created",
"WebhookCreationHint": "This webhook will be assigned to all events in DocSpace",
"WebhookDetails": "Webhook details",
"WebhookEditedSuccessfully": "Webhook configuration edited successfully",

View File

@ -38,7 +38,7 @@
"BackupCreatedSuccess": "Պահուստային պատճենը հաջողությամբ ստեղծվել է:",
"BackupList": "Պահուստի ցուցակ",
"BackupListWarningText": "Եթե ​​ցանկից որևէ միավոր ջնջեք, դրանց համապատասխան ֆայլերը նույնպես կջնջվեն: Այս գործողությունը հնարավոր չէ հետարկել:Բոլոր ֆայլերը ջնջելու համար օգտագործեք հղումը.",
"BetaLabel": "ԲԵՏԱ",
"BetaLabel": "BETA",
"BlockingTime": "Արգելափակման ժամանակը (վրկ)",
"Branding": "Բրենդինգ",
"BrandingSectionDescription": "Նշեք ձեր ընկերության տվյալները, ավելացրեք հղումներ դեպի արտաքին ռեսուրսներ և էլփոստի հասցեներ, որոնք ցուցադրվում են DocSpace ինտերֆեյսում:",

View File

@ -38,7 +38,7 @@
"BackupCreatedSuccess": "백업 복사본 생성에 성공했습니다.",
"BackupList": "백업 목록",
"BackupListWarningText": "목록에서 항목을 삭제하면 그에 상응하는 파일도 삭제됩니다. 이 작업은 취소할 수 없습니다. 모든 파일을 삭제하려면 다음 링크를 사용하시기 바랍니다:",
"BetaLabel": "베타",
"BetaLabel": "BETA",
"BlockingTime": "차단 시간(초)",
"Branding": "브랜딩",
"BrandingSectionDescription": "회사 정보를 지정하고 DocSpace 인터페이스 내에 표시되는 이메일 주소 및 외부 리소스에 대한 링크를 추가하세요.",

View File

@ -35,6 +35,7 @@
"BackupCreatedSuccess": "ສຳເນົາສໍາຮອງໄດ້ຖືກສ້າງສຳເລັດແລ້ວ.",
"BackupList": "ສໍາຮອງຂໍ້ມູນ ລາຍການ",
"BackupListWarningText": "ຖ້າທ່ານລຶບລາຍການໃດໆອອກຈາກບັນຊີລາຍຊື່, ໄຟລ໌ທີ່ສອດຄ້ອງກັນຂອງພວກມັນຈະຖືກລຶບຖິ້ມ. ການດໍາເນີນການນີ້ບໍ່ສາມາດຍົກເລີກໄດ້. ເພື່ອລຶບໄຟລ໌ທັງຫມົດໃຫ້ໃຊ້ການເຊື່ອມຕໍ່:",
"BetaLabel": "BETA",
"Branding": "ຍີ່ຫໍ້",
"BrandingSectionDescription": "ລະບຸຂໍ້ມູນບໍລິສັດຂອງທ່ານ, ເພີ່ມການເຊື່ອມຕໍ່ກັບຊັບພະຍາກອນພາຍນອກ ແລະທີ່ຢູ່ອີເມວທີ່ສະແດງຢູ່ໃນ ສ່ວນຕິດຕໍ່ DocSpace.",
"BrandingSubtitle": "ໃຊ້ຕົວເລືອກນີ້ເພື່ອສະໜອງປະສົບການໃນຍີ່ຫໍ້ໃຫ້ກັບຜູ້ໃຊ້.",

View File

@ -38,7 +38,7 @@
"BackupCreatedSuccess": "Резервная копия успешно создана.",
"BackupList": "Список резервных копий",
"BackupListWarningText": "При удалении любых элементов из списка соответствующие им файлы тоже будут удалены. Это действие необратимо. Для удаления всех файлов используйте ссылку:",
"BetaLabel": "БЕТА",
"BetaLabel": "BETA",
"BlockingTime": "Время блокировки (сек)",
"Branding": "Брендинг",
"BrandingSectionDescription": "Укажите информацию о своей компании, добавьте ссылки на внешние ресурсы и адреса электронной почты, отображаемые в интерфейсе DocSpace.",

View File

@ -45,6 +45,7 @@
"UnselectAll": "Отменить выбор для всех",
"URL": "URL",
"ViewRawPayload": "Просмотр исходной полезной нагрузки",
"WebhookCreated": "Вебхук создан",
"WebhookCreationHint": "Этот вебхук будет назначен всем событиям в DocSpace",
"WebhookDetails": "Сведения о вебхуке",
"WebhookEditedSuccessfully": "Конфигурация вебхука успешно отредактирована",

View File

@ -38,7 +38,7 @@
"BackupCreatedSuccess": "备份副本已成功创建。",
"BackupList": "备份列表",
"BackupListWarningText": "若您从列表中删除任何项目,其相应的文件也将被删除。此操作无法撤消。若想删除所有文件,请使用以下链接:",
"BetaLabel": "测试版",
"BetaLabel": "BETA",
"BlockingTime": "锁定时间(秒)",
"Branding": "品牌",
"BrandingSectionDescription": "在协作空间界面中展示您的公司信息,添加外部资源链接与邮件地址。",

View File

@ -3,7 +3,7 @@ import { inject, observer } from "mobx-react";
import { useLocation, Outlet } from "react-router-dom";
import { withTranslation } from "react-i18next";
import Article from "@docspace/common/components/Article";
import Article from "@docspace/shared/components/article";
import {
updateTempContent,
showLoader,
@ -20,6 +20,7 @@ import {
ArticleHeaderContent,
ArticleMainButtonContent,
} from "./components/Article";
import ArticleWrapper from "./components/ArticleWrapper";
const ClientArticle = React.memo(
({
@ -29,7 +30,7 @@ const ClientArticle = React.memo(
showArticleLoader,
}) => {
return (
<Article
<ArticleWrapper
withMainButton={withMainButton}
onLogoClickAction={() => {
setIsFilterLoading(true, false);
@ -48,7 +49,7 @@ const ClientArticle = React.memo(
<Article.Body>
<ArticleBodyContent />
</Article.Body>
</Article>
</ArticleWrapper>
);
}
);
@ -160,7 +161,15 @@ const ClientContent = (props) => {
};
const Client = inject(
({ auth, clientLoadingStore, filesStore, peopleStore, pluginStore }) => {
({
authStore,
clientLoadingStore,
filesStore,
peopleStore,
pluginStore,
userStore,
settingsStore,
}) => {
const {
frameConfig,
isFrame,
@ -171,11 +180,11 @@ const Client = inject(
enablePlugins,
isDesktopClientInit,
setIsDesktopClientInit,
} = auth.settingsStore;
} = settingsStore;
if (!auth.userStore.user) return;
if (!userStore.user) return;
const { isVisitor } = auth.userStore.user;
const { isVisitor } = userStore.user;
const {
isLoading,
@ -194,11 +203,11 @@ const Client = inject(
setIsDesktopClientInit,
isFrame,
showMenu: frameConfig?.showMenu,
user: auth.userStore.user,
isAuthenticated: auth.isAuthenticated,
user: userStore.user,
isAuthenticated: authStore.isAuthenticated,
encryptionKeys: encryptionKeys,
isEncryption: isEncryptionSupport,
isLoaded: auth.isLoaded && clientLoadingStore.isLoaded,
isLoaded: authStore.isLoaded && clientLoadingStore.isLoaded,
setIsLoaded: clientLoadingStore.setIsLoaded,
withMainButton,
setIsFilterLoading: setIsSectionFilterLoading,

View File

@ -36,8 +36,7 @@ const DocspaceLogo = (props) => {
);
};
export default inject(({ auth }) => {
const { settingsStore } = auth;
export default inject(({ settingsStore }) => {
const { whiteLabelLogoUrls, theme } = settingsStore;
return {

View File

@ -111,23 +111,26 @@ export default function withBadges(WrappedComponent) {
isAdmin,
isVisitor,
isDesktopClient,
sectionWidth,
viewAs,
isMutedBadge,
isArchiveFolderRoot,
isArchiveFolder,
isPublicRoom,
isRecentTab,
} = this.props;
const { fileStatus, access, mute } = item;
const newItems =
item.new ||
(!mute && (fileStatus & FileStatus.IsNew) === FileStatus.IsNew);
const showNew = !!newItems;
const showNew = !!newItems && !isPublicRoom;
const accessToEdit =
access === ShareAccessRights.FullAccess ||
access === ShareAccessRights.None; // TODO: fix access type for owner (now - None)
const canEditing = access === ShareAccessRights.Editing;
const badgesComponent = (
<Badges
t={t}
@ -137,7 +140,6 @@ export default function withBadges(WrappedComponent) {
isVisitor={isVisitor}
showNew={showNew}
newItems={newItems}
sectionWidth={sectionWidth}
isTrashFolder={isTrashFolder}
isPrivacyFolder={isPrivacyFolder}
isArchiveFolderRoot={isArchiveFolderRoot}
@ -153,6 +155,8 @@ export default function withBadges(WrappedComponent) {
isMutedBadge={isMutedBadge}
onCopyPrimaryLink={this.onCopyPrimaryLink}
isArchiveFolder={isArchiveFolder}
isRecentTab={isRecentTab}
canEditing={canEditing}
/>
);
@ -165,13 +169,15 @@ export default function withBadges(WrappedComponent) {
return inject(
(
{
auth,
authStore,
treeFoldersStore,
filesActionsStore,
versionHistoryStore,
dialogsStore,
filesStore,
publicRoomStore,
userStore,
settingsStore,
},
{ item }
) => {
@ -180,9 +186,10 @@ export default function withBadges(WrappedComponent) {
isPrivacyFolder,
isArchiveFolderRoot,
isArchiveFolder,
isRecentTab,
} = treeFoldersStore;
const { markAsRead, setPinAction, setMuteAction } = filesActionsStore;
const { isTabletView, isDesktopClient, theme } = auth.settingsStore;
const { isTabletView, isDesktopClient, theme } = settingsStore;
const { setIsVerHistoryPanel, fetchFileVersions } = versionHistoryStore;
const {
setNewFilesPanelVisible,
@ -199,8 +206,8 @@ export default function withBadges(WrappedComponent) {
return {
isArchiveFolderRoot,
theme,
isAdmin: auth.isAdmin,
isVisitor: auth?.userStore?.user?.isVisitor || !auth?.userStore?.user,
isAdmin: authStore.isAdmin,
isVisitor: userStore?.user?.isVisitor || !userStore?.user,
isTrashFolder: isRecycleBinFolder,
isPrivacyFolder,
homepage: config.homepage,
@ -218,6 +225,8 @@ export default function withBadges(WrappedComponent) {
isMutedBadge,
getPrimaryLink,
isArchiveFolder,
isPublicRoom: publicRoomStore.isPublicRoom,
isRecentTab,
};
}
)(observer(WithBadges));

View File

@ -112,10 +112,11 @@ export default function withContent(WrappedContent) {
{
filesStore,
treeFoldersStore,
auth,
settingsStore,
dialogsStore,
uploadDataStore,
publicRoomStore,
userStore,
},
{ item }
) => {
@ -140,10 +141,8 @@ export default function withContent(WrappedContent) {
const { isRecycleBinFolder, isPrivacyFolder, isArchiveFolder } =
treeFoldersStore;
const { replaceFileStream, setEncryptionAccess } = auth;
const { culture, personal, folderFormValidation, isDesktopClient } =
auth.settingsStore;
settingsStore;
const {
setConvertPasswordDialogVisible,
@ -166,12 +165,11 @@ export default function withContent(WrappedContent) {
isArchiveFolder,
openDocEditor,
renameFolder,
replaceFileStream,
setEncryptionAccess,
setIsLoading,
updateFile,
viewAs,
viewer: auth.userStore.user,
viewer: userStore.user,
setConvertPasswordDialogVisible,
setConvertItem,
setFormCreationInfo,

View File

@ -53,10 +53,12 @@ export default function withFileActions(WrappedFileItem) {
};
onDrop = (items) => {
const { isTrashFolder, dragging, setDragging } = this.props;
const { isTrashFolder, dragging, setDragging, isDisabledDropItem } =
this.props;
const { fileExst, id } = this.props.item;
if (isTrashFolder) return dragging && setDragging(false);
if (isTrashFolder || isDisabledDropItem)
return dragging && setDragging(false);
if (!fileExst) {
this.onDropZoneUpload(items, id);
@ -81,6 +83,7 @@ export default function withFileActions(WrappedFileItem) {
isSelected,
setSelection,
currentDeviceType,
isDisabledItemId,
} = this.props;
const { isThirdPartyFolder } = item;
@ -200,7 +203,7 @@ export default function withFileActions(WrappedFileItem) {
item.foldersCount === 0
) {
setParentId(item.parentId);
setRoomType(item.roomType);
// setRoomType(item.roomType);
}
openFileAction(item);
@ -249,10 +252,16 @@ export default function withFileActions(WrappedFileItem) {
itemIndex,
currentDeviceType,
isDisabledDropItem,
} = this.props;
const { access, id } = item;
const isDragging = isFolder && access < 2 && !isTrashFolder && !isPrivacy;
const isDragging =
!isDisabledDropItem &&
isFolder &&
access < 2 &&
!isTrashFolder &&
!isPrivacy;
let className = isDragging ? " droppable" : "";
if (draggable) className += " draggable";
@ -310,7 +319,7 @@ export default function withFileActions(WrappedFileItem) {
return inject(
(
{
auth,
settingsStore,
filesActionsStore,
dialogsStore,
treeFoldersStore,
@ -364,7 +373,10 @@ export default function withFileActions(WrappedFileItem) {
(x) => x.id === item.id && x.fileExst === item.fileExst
);
const draggable = !isRecycleBinFolder && selectedItem;
const isDisabledDropItem = !item.security.Create;
const draggable =
!isRecycleBinFolder && selectedItem && !isDisabledDropItem;
const isFolder = selectedItem ? false : !item.isFolder ? false : true;
@ -447,7 +459,8 @@ export default function withFileActions(WrappedFileItem) {
withShiftSelect,
setSelection,
currentDeviceType: auth.settingsStore.currentDeviceType,
currentDeviceType: settingsStore.currentDeviceType,
isDisabledDropItem,
};
}
)(observer(WithFileActions));

View File

@ -379,15 +379,17 @@ const withHotkeys = (Component) => {
return inject(
({
auth,
settingsStore,
filesStore,
dialogsStore,
settingsStore,
filesSettingsStore,
filesActionsStore,
hotkeyStore,
mediaViewerDataStore,
treeFoldersStore,
selectedFolderStore,
userStore,
currentTariffStatusStore,
}) => {
const {
setSelected,
@ -435,10 +437,10 @@ const withHotkeys = (Component) => {
} = filesActionsStore;
const { visible: mediaViewerIsVisible } = mediaViewerDataStore;
const { setHotkeyPanelVisible } = auth.settingsStore;
const { isGracePeriod } = auth.currentTariffStatusStore;
const { setHotkeyPanelVisible } = settingsStore;
const { isGracePeriod } = currentTariffStatusStore;
const isVisitor = auth.userStore.user?.isVisitor;
const isVisitor = userStore.user?.isVisitor;
const {
isFavoritesFolder,
@ -458,7 +460,7 @@ const withHotkeys = (Component) => {
setHotkeyPanelVisible,
setDeleteDialogVisible,
setSelectFileDialogVisible,
confirmDelete: settingsStore.confirmDelete,
confirmDelete: filesSettingsStore.confirmDelete,
deleteAction,
isAvailableOption,

View File

@ -51,23 +51,24 @@ const withLoader = (WrappedComponent) => (Loader) => {
return inject(
({
auth,
authStore,
filesStore,
peopleStore,
clientLoadingStore,
publicRoomStore,
settingsStore,
}) => {
const { viewAs, isLoadingFilesFind, isInit } = filesStore;
const { viewAs: accountsViewAs } = peopleStore;
const { firstLoad, isLoading, showBodyLoader } = clientLoadingStore;
const { settingsStore } = auth;
const { setIsBurgerLoading } = settingsStore;
const { isPublicRoom } = publicRoomStore;
return {
firstLoad: isPublicRoom ? false : firstLoad,
isLoaded: isPublicRoom ? true : auth.isLoaded,
isLoaded: isPublicRoom ? true : authStore.isLoaded,
isLoading,
viewAs,
setIsBurgerLoading,

View File

@ -107,14 +107,14 @@ const withLoading = (WrappedComponent) => {
setting === "language-and-time-zone"
? isLoadedCustomizationSettingLngTZSettings
: setting === "welcome-page-settings"
? isLoadedCustomizationSettingWelcomePageSettings
: setting === "dns-settings"
? isLoadedCustomizationSettingDNSSettings
: setting === "portal-renaming"
? isLoadedCustomizationSettingPortalRenaming
: viewMobile
? isLoadedCustomizationNavbarSettings
: isLoadedCustomizationSettings;
? isLoadedCustomizationSettingWelcomePageSettings
: setting === "dns-settings"
? isLoadedCustomizationSettingDNSSettings
: setting === "portal-renaming"
? isLoadedCustomizationSettingPortalRenaming
: viewMobile
? isLoadedCustomizationNavbarSettings
: isLoadedCustomizationSettings;
return (
<WrappedComponent
@ -125,7 +125,7 @@ const withLoading = (WrappedComponent) => {
);
};
return inject(({ common, auth }) => {
return inject(({ common, settingsStore }) => {
const {
isLoadedArticleBody,
isLoadedSectionHeader,
@ -139,7 +139,7 @@ const withLoading = (WrappedComponent) => {
} = common;
const { isBurgerLoading, setIsBurgerLoading, enablePortalRename } =
auth.settingsStore;
settingsStore;
return {
isLoadedArticleBody,

View File

@ -135,8 +135,7 @@ export default function withContent(WrappedContent) {
);
};
return inject(({ auth, peopleStore }, { item }) => {
const { userStore, settingsStore } = auth;
return inject(({ settingsStore, peopleStore, userStore }, { item }) => {
const { theme, standalone } = settingsStore;
const { selectGroup } = peopleStore.selectedGroupStore;

View File

@ -53,6 +53,16 @@ export default function withQuickButtons(WrappedComponent) {
.catch((err) => toastr.error(err));
};
onClickShare = async () => {
const { t, item, getPrimaryFileLink, setShareChanged } = this.props;
const primaryLink = await getPrimaryFileLink(item.id);
if (primaryLink) {
copy(primaryLink.sharedTo.shareLink);
toastr.success(t("Files:LinkSuccessfullyCopied"));
setShareChanged(true);
}
};
onCopyPrimaryLink = async () => {
const { t, item, getPrimaryLink } = this.props;
const primaryLink = await getPrimaryLink(item.id);
@ -74,6 +84,7 @@ export default function withQuickButtons(WrappedComponent) {
viewAs,
folderCategory,
isPublicRoom,
isPersonalRoom,
isArchiveFolder,
} = this.props;
@ -87,9 +98,11 @@ export default function withQuickButtons(WrappedComponent) {
viewAs={viewAs}
isDisabled={isLoading}
isPublicRoom={isPublicRoom}
isPersonalRoom={isPersonalRoom}
onClickLock={this.onClickLock}
onClickDownload={this.onClickDownload}
onClickFavorite={this.onClickFavorite}
onClickShare={this.onClickShare}
folderCategory={folderCategory}
onCopyPrimaryLink={this.onCopyPrimaryLink}
isArchiveFolder={isArchiveFolder}
@ -107,12 +120,14 @@ export default function withQuickButtons(WrappedComponent) {
return inject(
({
auth,
authStore,
settingsStore,
filesActionsStore,
dialogsStore,
publicRoomStore,
treeFoldersStore,
filesStore,
infoPanelStore,
}) => {
const { lockFileAction, setFavoriteAction, onSelectItem } =
filesActionsStore;
@ -120,6 +135,7 @@ export default function withQuickButtons(WrappedComponent) {
isPersonalFolderRoot,
isArchiveFolderRoot,
isTrashFolder,
isPersonalRoom,
isArchiveFolder,
} = treeFoldersStore;
@ -129,18 +145,22 @@ export default function withQuickButtons(WrappedComponent) {
isTrashFolder || isArchiveFolderRoot || isPersonalFolderRoot;
const { isPublicRoom } = publicRoomStore;
const { getPrimaryFileLink, setShareChanged } = infoPanelStore;
return {
theme: auth.settingsStore.theme,
isAdmin: auth.isAdmin,
theme: settingsStore.theme,
isAdmin: authStore.isAdmin,
lockFileAction,
setFavoriteAction,
onSelectItem,
setSharingPanelVisible,
folderCategory,
isPublicRoom,
isPersonalRoom,
getPrimaryLink: filesStore.getPrimaryLink,
isArchiveFolder,
getPrimaryFileLink,
setShareChanged,
};
}
)(observer(WithQuickButtons));

View File

@ -407,96 +407,101 @@ const Shell = ({ items = [], page = "home", ...rest }) => {
);
};
const ShellWrapper = inject(({ auth, backup, clientLoadingStore }) => {
const { i18n } = useTranslation();
const ShellWrapper = inject(
({ authStore, settingsStore, backup, clientLoadingStore, userStore }) => {
const { i18n } = useTranslation();
const { init, isLoaded, settingsStore, setProductVersion, language } = auth;
const { init, isLoaded, setProductVersion, language } = authStore;
const {
personal,
roomsMode,
isDesktopClient,
firebaseHelper,
setModuleInfo,
setCheckedMaintenance,
setMaintenanceExist,
setSnackbarExist,
socketHelper,
setTheme,
whiteLabelLogoUrls,
standalone,
currentDeviceType,
} = settingsStore;
const {
personal,
roomsMode,
isDesktopClient,
firebaseHelper,
setModuleInfo,
setCheckedMaintenance,
setMaintenanceExist,
setSnackbarExist,
socketHelper,
setTheme,
whiteLabelLogoUrls,
standalone,
currentDeviceType,
isFrame,
frameConfig,
} = settingsStore;
const isBase = settingsStore.theme.isBase;
const { setPreparationPortalDialogVisible } = backup;
const isBase = settingsStore.theme.isBase;
const { setPreparationPortalDialogVisible } = backup;
const userTheme = isDesktopClient
? auth?.userStore?.user?.theme
? auth?.userStore?.user?.theme
: window.RendererProcessVariable?.theme?.type === "dark"
? "Dark"
: "Base"
: auth?.userStore?.user?.theme;
const userTheme = isDesktopClient
? userStore?.user?.theme
? userStore?.user?.theme
: window.RendererProcessVariable?.theme?.type === "dark"
? "Dark"
: "Base"
: userStore?.user?.theme;
return {
loadBaseInfo: async () => {
await init(false, i18n);
return {
loadBaseInfo: async () => {
await init(false, i18n);
setModuleInfo(config.homepage, "home");
setProductVersion(config.version);
setModuleInfo(config.homepage, "home");
setProductVersion(config.version);
if (isDesktopClient) {
document.body.classList.add("desktop");
}
},
language,
isLoaded,
if (isDesktopClient) {
document.body.classList.add("desktop");
}
},
language,
isLoaded,
isDesktop: isDesktopClient,
FirebaseHelper: firebaseHelper,
personal,
setCheckedMaintenance,
setMaintenanceExist,
socketHelper,
setPreparationPortalDialogVisible,
isBase,
setTheme,
roomsMode,
setSnackbarExist,
userTheme: userTheme,
userId: auth?.userStore?.user?.id,
whiteLabelLogoUrls,
standalone,
currentDeviceType,
isDesktop: isDesktopClient,
FirebaseHelper: firebaseHelper,
personal,
setCheckedMaintenance,
setMaintenanceExist,
socketHelper,
setPreparationPortalDialogVisible,
isBase,
setTheme,
roomsMode,
setSnackbarExist,
userTheme: isFrame ? frameConfig?.theme : userTheme,
userId: userStore?.user?.id,
whiteLabelLogoUrls,
standalone,
currentDeviceType,
showArticleLoader: clientLoadingStore.showArticleLoader,
};
})(observer(Shell));
const ThemeProviderWrapper = inject(({ auth, loginStore }) => {
const { settingsStore } = auth;
let currentColorScheme = false;
const { theme } = settingsStore;
const { i18n } = useTranslation();
if (loginStore) {
currentColorScheme = loginStore.currentColorScheme;
} else if (auth) {
currentColorScheme = settingsStore.currentColorScheme || false;
showArticleLoader: clientLoadingStore.showArticleLoader,
};
}
)(observer(Shell));
const { timezone } = settingsStore;
const ThemeProviderWrapper = inject(
({ authStore, settingsStore, loginStore }) => {
let currentColorScheme = false;
const { theme } = settingsStore;
const { i18n } = useTranslation();
window.theme = theme;
window.timezone = timezone;
if (loginStore) {
currentColorScheme = loginStore.currentColorScheme;
} else if (authStore) {
currentColorScheme = settingsStore.currentColorScheme || false;
}
return {
theme: { ...theme, interfaceDirection: i18n.dir() },
currentColorScheme,
timezone,
};
})(observer(ThemeProvider));
const { timezone } = settingsStore;
window.theme = theme;
window.timezone = timezone;
return {
theme: { ...theme, interfaceDirection: i18n.dir() },
currentColorScheme,
timezone,
};
}
)(observer(ThemeProvider));
export default () => (
<MobxProvider {...store}>

View File

@ -29,8 +29,8 @@ const PureAccountsItem = ({ showText, isActive, onClick, t }) => {
const AccountsItem = withTranslation(["Common"])(PureAccountsItem);
export default inject(({ auth }) => {
const { showText } = auth.settingsStore;
export default inject(({ settingsStore }) => {
const { showText } = settingsStore;
return {
showText,

View File

@ -36,8 +36,7 @@ const BonusItem = ({ showText, toggleArticleOpen }) => {
);
};
export default inject(({ auth }) => {
const { settingsStore } = auth;
export default inject(({ settingsStore }) => {
const { showText, toggleArticleOpen } = settingsStore;
return {
showText,

View File

@ -236,10 +236,13 @@ const Items = ({
return true;
}
if (
(item.rootFolderType === FolderType.TRASH && startDrag && !isArchive) ||
item.rootFolderType === FolderType.USER
) {
if (item.rootFolderType === FolderType.TRASH && startDrag && !isArchive) {
return draggableItems.some(
(draggableItem) => draggableItem.security.Delete
);
}
if (item.rootFolderType === FolderType.USER) {
return (
folderAccess === ShareAccessRights.None ||
folderAccess === ShareAccessRights.FullAccess ||
@ -381,7 +384,7 @@ Items.propTypes = {
export default inject(
({
auth,
authStore,
treeFoldersStore,
selectedFolderStore,
filesStore,
@ -389,13 +392,11 @@ export default inject(
uploadDataStore,
dialogsStore,
clientLoadingStore,
userStore,
settingsStore,
}) => {
const {
settingsStore,
isCommunity,
isPaymentPageAvailable,
currentDeviceType,
} = auth;
const { isCommunity, isPaymentPageAvailable, currentDeviceType } =
authStore;
const { showText, docSpace } = settingsStore;
const {
@ -426,9 +427,9 @@ export default inject(
const { setEmptyTrashDialogVisible } = dialogsStore;
return {
isAdmin: auth.isAdmin,
isVisitor: auth.userStore.user.isVisitor,
isCollaborator: auth.userStore.user.isCollaborator,
isAdmin: authStore.isAdmin,
isVisitor: userStore.user.isVisitor,
isCollaborator: userStore.user.isCollaborator,
myId: myFolderId,
commonId: commonFolderId,
isPrivacy: isPrivacyFolder,

View File

@ -28,8 +28,8 @@ const SettingsItem = withTranslation(["FilesSettings", "Common"])(
PureSettingsItem
);
export default inject(({ auth }) => {
export default inject(({ settingsStore }) => {
return {
showText: auth.settingsStore.showText,
showText: settingsStore.showText,
};
})(observer(SettingsItem));

View File

@ -15,10 +15,10 @@ import AccountsFilter from "@docspace/shared/api/people/filter";
import Banner from "./Banner";
import Loaders from "@docspace/common/components/Loaders";
import { getCategoryUrl } from "SRC_DIR/helpers/utils";
import { CategoryType } from "SRC_DIR/helpers/constants";
import { ArticleFolderLoader } from "@docspace/shared/skeletons/article";
import { MEDIA_VIEW_URL } from "@docspace/shared/constants";
const StyledBlock = styled.div`
padding: 0 20px;
@ -221,7 +221,7 @@ const ArticleBodyContent = (props) => {
return setActiveItemId(rootFolderId || roomsFolderId);
}
if (location.pathname.includes("/products/files/#preview")) {
if (location.pathname.includes(MEDIA_VIEW_URL)) {
setActiveItemId(rootFolderId);
}
}, [
@ -239,7 +239,7 @@ const ArticleBodyContent = (props) => {
setIsBurgerLoading(showArticleLoader);
}, [showArticleLoader]);
if (showArticleLoader) return <Loaders.ArticleFolder />;
if (showArticleLoader) return <ArticleFolderLoader />;
return (
<>
@ -264,12 +264,13 @@ const ArticleBodyContent = (props) => {
export default inject(
({
auth,
settingsStore,
filesStore,
treeFoldersStore,
dialogsStore,
selectedFolderStore,
clientLoadingStore,
userStore,
}) => {
const { clearFiles, setSelection } = filesStore;
const {
@ -302,13 +303,13 @@ export default inject(
theme,
setIsBurgerLoading,
currentDeviceType,
} = auth.settingsStore;
} = settingsStore;
return {
toggleArticleOpen,
showText,
showArticleLoader,
isVisitor: auth.userStore.user.isVisitor,
isVisitor: userStore.user.isVisitor,
setNewFilesPanelVisible,

View File

@ -1,19 +1,20 @@
import React from "react";
import Loaders from "@docspace/common/components/Loaders";
import { inject, observer } from "mobx-react";
import { withTranslation } from "react-i18next";
import withLoader from "../../../HOCs/withLoader";
import { ArticleHeaderLoader } from "@docspace/shared/skeletons/article";
const ArticleHeaderContent = ({ currentModuleName }) => {
return <>{currentModuleName}</>;
};
export default inject(({ auth }) => {
export default inject(({ authStore }) => {
return {
currentModuleName: (auth.product && auth.product.title) || "",
currentModuleName: (authStore.product && authStore.product.title) || "",
};
})(
withTranslation([])(
withLoader(observer(ArticleHeaderContent))(<Loaders.ArticleHeader />)
withLoader(observer(ArticleHeaderContent))(<ArticleHeaderLoader />)
)
);

View File

@ -22,7 +22,6 @@ import { toastr } from "@docspace/shared/components/toast";
import { Button } from "@docspace/shared/components/button";
import { withTranslation } from "react-i18next";
import Loaders from "@docspace/common/components/Loaders";
import { encryptionUploadDialog } from "../../../helpers/desktop";
import { useNavigate, useLocation } from "react-router-dom";
@ -34,6 +33,7 @@ import styled, { css } from "styled-components";
import { resendInvitesAgain } from "@docspace/shared/api/people";
import { getCorrectFourValuesStyle } from "@docspace/shared/utils";
import { ArticleButtonLoader } from "@docspace/shared/skeletons/article";
const StyledButton = styled(Button)`
font-weight: 700;
@ -42,28 +42,30 @@ const StyledButton = styled(Button)`
opacity: ${(props) => (props.isDisabled ? 0.6 : 1)};
background-color: ${({ $currentColorScheme }) =>
$currentColorScheme.main.accent} !important;
background: ${({ $currentColorScheme }) => $currentColorScheme.main.accent};
border: ${({ $currentColorScheme }) => $currentColorScheme.main.accent};
$currentColorScheme.main?.accent} !important;
background: ${({ $currentColorScheme }) => $currentColorScheme.main?.accent};
border: ${({ $currentColorScheme }) => $currentColorScheme.main?.accent};
${(props) =>
!props.isDisabled &&
css`
:hover {
background-color: ${({ $currentColorScheme }) =>
$currentColorScheme.main.accent};
$currentColorScheme.main?.accent};
opacity: 0.85;
background: ${({ $currentColorScheme }) =>
$currentColorScheme.main.accent};
border: ${({ $currentColorScheme }) => $currentColorScheme.main.accent};
$currentColorScheme.main?.accent};
border: ${({ $currentColorScheme }) =>
$currentColorScheme.main?.accent};
}
:active {
background-color: ${({ $currentColorScheme }) =>
$currentColorScheme.main.accent};
$currentColorScheme.main?.accent};
background: ${({ $currentColorScheme }) =>
$currentColorScheme.main.accent};
border: ${({ $currentColorScheme }) => $currentColorScheme.main.accent};
$currentColorScheme.main?.accent};
border: ${({ $currentColorScheme }) =>
$currentColorScheme.main?.accent};
opacity: 1;
filter: brightness(90%);
cursor: pointer;
@ -71,7 +73,7 @@ const StyledButton = styled(Button)`
`}
.button-content {
color: ${({ $currentColorScheme }) => $currentColorScheme.text.accent};
color: ${({ $currentColorScheme }) => $currentColorScheme.text?.accent};
position: relative;
display: flex;
justify-content: space-between;
@ -512,7 +514,7 @@ const ArticleMainButtonContent = (props) => {
}
if (showArticleLoader)
return isMobileArticle ? null : <Loaders.ArticleButton height="32px" />;
return isMobileArticle ? null : <ArticleButtonLoader height="32px" />;
return (
<>
@ -587,7 +589,7 @@ const ArticleMainButtonContent = (props) => {
export default inject(
({
auth,
settingsStore,
filesStore,
dialogsStore,
uploadDataStore,
@ -597,6 +599,8 @@ export default inject(
oformsStore,
pluginStore,
versionHistoryStore,
userStore,
currentTariffStatusStore,
}) => {
const { showArticleLoader } = clientLoadingStore;
const { mainButtonMobileVisible } = filesStore;
@ -621,15 +625,15 @@ export default inject(
} = dialogsStore;
const { enablePlugins, currentColorScheme, currentDeviceType } =
auth.settingsStore;
settingsStore;
const { isVisible: versionHistoryPanelVisible } = versionHistoryStore;
const security = selectedFolderStore.security;
const currentFolderId = selectedFolderStore.id;
const { isAdmin, isOwner } = auth.userStore.user;
const { isGracePeriod } = auth.currentTariffStatusStore;
const { isAdmin, isOwner } = userStore.user;
const { isGracePeriod } = currentTariffStatusStore;
const { setOformFromFolderId, oformsFilter } = oformsStore;
const { mainButtonItemsList } = pluginStore;
@ -637,8 +641,8 @@ export default inject(
return {
isGracePeriod,
setInviteUsersWarningDialogVisible,
showText: auth.settingsStore.showText,
isMobileArticle: auth.settingsStore.isMobileArticle,
showText: settingsStore.showText,
isMobileArticle: settingsStore.isMobileArticle,
showArticleLoader,
isPrivacy: isPrivacyFolder,

View File

@ -0,0 +1,147 @@
import { inject, observer } from "mobx-react";
import Article from "@docspace/shared/components/article";
import { ArticleProps } from "@docspace/shared/components/article/Article.types";
const ArticleWrapper = (props: ArticleProps) => {
return <Article {...props} />;
};
export default inject(
({
authStore,
uploadDataStore,
profileActionsStore,
dialogsStore,
userStore,
bannerStore,
currentTariffStatusStore,
currentQuotaStore,
settingsStore,
}: any) => {
const {
isLiveChatAvailable,
isPaymentPageAvailable,
isTeamTrainingAlertAvailable,
isSubmitToGalleryAlertAvailable,
isEnterprise,
} = authStore;
const { getActions, getUserRole, onProfileClick } = profileActionsStore;
const { withSendAgain, user } = userStore;
const { isBannerVisible } = bannerStore;
const { primaryProgressDataStore, secondaryProgressDataStore } =
uploadDataStore;
const { email, displayName } = user;
const isAdmin = user?.isAdmin;
const { visible: primaryProgressDataVisible } = primaryProgressDataStore;
const { visible: secondaryProgressDataStoreVisible } =
secondaryProgressDataStore;
const showProgress =
primaryProgressDataVisible || secondaryProgressDataStoreVisible;
const {
showText,
setShowText,
articleOpen,
setIsMobileArticle,
toggleShowText,
toggleArticleOpen,
currentColorScheme,
setArticleOpen,
mainBarVisible,
zendeskKey,
isMobileArticle,
currentDeviceType,
standalone,
articleAlertsData,
incrementIndexOfArticleAlertsData,
isBurgerLoading,
whiteLabelLogoUrls,
removeAlertFromArticleAlertsData,
bookTrainingEmail,
} = settingsStore;
const { setSubmitToGalleryDialogVisible } = dialogsStore;
const { isFreeTariff, isNonProfit, isTrial, currentTariffPlanTitle } =
currentQuotaStore;
const {
isGracePeriod,
isLicenseExpiring,
isLicenseDateExpired,
trialDaysLeft,
paymentDate,
} = currentTariffStatusStore;
return {
bookTrainingEmail,
onProfileClick,
user,
getUserRole,
getActions,
currentTariffPlanTitle,
email,
displayName,
zendeskKey,
isMobileArticle,
showProgress,
isBurgerLoading,
whiteLabelLogoUrls,
isEnterprise,
isTrial,
isLicenseDateExpired,
trialDaysLeft,
paymentDate,
toggleArticleOpen,
articleAlertsData,
incrementIndexOfArticleAlertsData,
showText,
isNonProfit,
isGracePeriod,
isFreeTariff,
isPaymentPageAvailable,
isTeamTrainingAlertAvailable,
isSubmitToGalleryAlertAvailable,
isLicenseExpiring,
standalone,
setShowText,
articleOpen,
setIsMobileArticle,
toggleShowText,
removeAlertFromArticleAlertsData,
setSubmitToGalleryDialogVisible,
currentColorScheme,
setArticleOpen,
withSendAgain,
mainBarVisible,
isBannerVisible,
isLiveChatAvailable,
currentDeviceType,
isAdmin,
};
}
)(observer(ArticleWrapper));

View File

@ -1,26 +1,23 @@
import UnpinReactSvgUrl from "PUBLIC_DIR/images/unpin.react.svg?url";
import styled from "styled-components";
import React, { useState } from "react";
import UnpinReactSvgUrl from "PUBLIC_DIR/images/unpin.react.svg?url";
import RefreshReactSvgUrl from "PUBLIC_DIR/images/refresh.react.svg?url";
import FormFillRectSvgUrl from "PUBLIC_DIR/images/form.fill.rect.svg?url";
import AccessEditFormReactSvgUrl from "PUBLIC_DIR/images/access.edit.form.react.svg?url";
import FileActionsConvertEditDocReactSvgUrl from "PUBLIC_DIR/images/file.actions.convert.edit.doc.react.svg?url";
import LinkReactSvgUrl from "PUBLIC_DIR/images/link.react.svg?url";
import TabletLinkReactSvgUrl from "PUBLIC_DIR/images/tablet-link.reat.svg?url";
import RefreshReactSvgUrl from "PUBLIC_DIR/images/refresh.react.svg?url";
import Refresh12ReactSvgUrl from "PUBLIC_DIR/images/icons/12/refresh.react.svg?url";
import Mute12ReactSvgUrl from "PUBLIC_DIR/images/icons/12/mute.react.svg?url";
import Mute16ReactSvgUrl from "PUBLIC_DIR/images/icons/16/mute.react.svg?url";
import React, { useState } from "react";
import styled from "styled-components";
import { isMobile as isMobileDevice } from "react-device-detect";
import { Badge } from "@docspace/shared/components/badge";
import { ColorTheme, ThemeId } from "@docspace/shared/components/color-theme";
import {
FileStatus,
RoomsType,
ShareAccessRights,
} from "@docspace/shared/enums";
import { RoomsType, ShareAccessRights } from "@docspace/shared/enums";
import { Base } from "@docspace/shared/themes";
import { isTablet, isDesktop, size, classNames } from "@docspace/shared/utils";
@ -68,7 +65,6 @@ const Badges = ({
t,
theme,
newItems,
sectionWidth,
item,
isTrashFolder,
isPrivacyFolder,
@ -87,6 +83,8 @@ const Badges = ({
isVisitor,
onCopyPrimaryLink,
isArchiveFolder,
isRecentTab,
canEditing,
}) => {
const {
id,
@ -101,6 +99,7 @@ const Badges = ({
mute,
rootFolderId,
new: newCount,
hasDraft,
} = item;
const showEditBadge = !locked || item.access === 0;
@ -108,6 +107,7 @@ const Badges = ({
const isForm = fileExst === ".oform";
const isPdf = fileExst === ".pdf";
const isTile = viewAs === "tile";
const isViewTable = viewAs === "table";
const countVersions = versionGroup > 999 ? "999+" : versionGroup;
@ -190,7 +190,23 @@ const Badges = ({
return fileExst ? (
<div className="badges additional-badges file__badges">
{isEditing && !isVisitor && !isPdf && (
{hasDraft && (
<BadgeWrapper isTile={isTile}>
<Badge
noHover
isVersionBadge
className="badge-version badge-version-current tablet-badge icons-group"
backgroundColor={theme.filesBadges.badgeBackgroundColor}
label={t("BadgeMyDraftTitle")}
title={t("BadgeMyDraftTitle")}
{...versionBadgeProps}
style={{
width: "max-content",
}}
/>
</BadgeWrapper>
)}
{isEditing && !isVisitor && !isPdf && !(isRecentTab && !canEditing) && (
<ColorTheme
themeId={ThemeId.IconButton}
isEditing={isEditing}
@ -239,6 +255,17 @@ const Badges = ({
/>
</BadgeWrapper>
)}
{/* {isForm && (
<BadgeWrapper isTile={isTile}>
<HelpButton
color="#F2675A"
place="bottom"
size={isViewTable ? 12 : 16}
className="bagde_alert icons-group"
tooltipContent={t("BadgeAlertDescription")}
/>
</BadgeWrapper>
)} */}
</div>
) : (
<div

View File

@ -43,8 +43,8 @@ const BreakpointWarning = ({
);
};
export default inject(({ auth }) => {
export default inject(({ settingsStore }) => {
return {
theme: auth.settingsStore.theme,
theme: settingsStore.theme,
};
})(observer(withTranslation(["Settings"])(BreakpointWarning)));

View File

@ -0,0 +1,111 @@
import { FolderType } from "@docspace/shared/enums";
import EmptyScreenPersonalUrl from "PUBLIC_DIR/images/empty_screen_personal.svg?url";
import EmptyScreenPersonalDarkUrl from "PUBLIC_DIR/images/empty_screen_personal_dark.svg?url";
import EmptyScreenCorporateSvgUrl from "PUBLIC_DIR/images/empty_screen_corporate.svg?url";
import EmptyScreenCorporateDarkSvgUrl from "PUBLIC_DIR/images/empty_screen_corporate_dark.svg?url";
import EmptyScreenRoleSvgUrl from "PUBLIC_DIR/images/empty_screen_role.svg?url";
import EmptyScreenRoleDarkSvgUrl from "PUBLIC_DIR/images/empty_screen_role_dark.svg?url";
import EmptyScreenDoneSvgUrl from "PUBLIC_DIR/images/empty_screen_done.svg?url";
import EmptyScreenDoneDarkSvgUrl from "PUBLIC_DIR/images/empty_screen_done_dark.svg?url";
type ThemeType = "light" | "dark";
type FolderTypeOf = typeof FolderType;
type FolderTypeValueOfType = FolderTypeOf[keyof FolderTypeOf];
enum EmptyScreenTypeEnum {
Done = "emptyScreenDone",
InProgress = "emptyScreenInProgress",
Corporate = "emptyScreenCorporate",
Default = "emptyScreenDefault",
SubFolderDone = "emptyScreenSubFolderDone",
SubFolderinProgress = "emptyScreenSubFolderinProgress",
}
export const headerIconsUrl: Record<
ThemeType,
Record<EmptyScreenTypeEnum, string>
> = {
light: {
[EmptyScreenTypeEnum.Done]: EmptyScreenDoneSvgUrl,
[EmptyScreenTypeEnum.InProgress]: EmptyScreenRoleSvgUrl,
[EmptyScreenTypeEnum.Default]: EmptyScreenPersonalUrl,
[EmptyScreenTypeEnum.Corporate]: EmptyScreenCorporateSvgUrl,
[EmptyScreenTypeEnum.SubFolderDone]: EmptyScreenPersonalUrl,
[EmptyScreenTypeEnum.SubFolderinProgress]: EmptyScreenPersonalUrl,
},
dark: {
[EmptyScreenTypeEnum.Done]: EmptyScreenDoneDarkSvgUrl,
[EmptyScreenTypeEnum.InProgress]: EmptyScreenRoleDarkSvgUrl,
[EmptyScreenTypeEnum.Default]: EmptyScreenPersonalDarkUrl,
[EmptyScreenTypeEnum.Corporate]: EmptyScreenCorporateDarkSvgUrl,
[EmptyScreenTypeEnum.SubFolderDone]: EmptyScreenPersonalDarkUrl,
[EmptyScreenTypeEnum.SubFolderinProgress]: EmptyScreenPersonalDarkUrl,
},
};
export const translateHeaderKey: Record<EmptyScreenTypeEnum, string> = {
[EmptyScreenTypeEnum.Done]: "EmptyFormFolderDoneHeaderText",
[EmptyScreenTypeEnum.InProgress]: "EmptyFormFolderProgressHeaderText",
[EmptyScreenTypeEnum.Default]: "EmptyScreenFolder",
[EmptyScreenTypeEnum.Corporate]: "RoomCreated",
[EmptyScreenTypeEnum.SubFolderDone]: "EmptyFormSubFolderHeaderText",
[EmptyScreenTypeEnum.SubFolderinProgress]: "EmptyFormSubFolderHeaderText",
};
export const translateDescriptionKey: Record<EmptyScreenTypeEnum, string> = {
[EmptyScreenTypeEnum.Done]: "EmptyFormFolderDoneDescriptionText",
[EmptyScreenTypeEnum.InProgress]: "EmptyFormFolderProgressDescriptionText",
[EmptyScreenTypeEnum.Default]: "EmptyFolderDescriptionUser",
[EmptyScreenTypeEnum.Corporate]: "EmptyFolderDecription",
[EmptyScreenTypeEnum.SubFolderDone]: "EmptyFormSubFolderDoneDescriptionText",
[EmptyScreenTypeEnum.SubFolderinProgress]:
"EmptyFormSubFolderProgressDescriptionText",
};
export const getThemeMode = (theme: { isBase: boolean }): ThemeType => {
return theme.isBase ? "light" : "dark";
};
export const getEmptyScreenType = (
type: FolderTypeValueOfType | null,
displayRoomCondition: boolean
): EmptyScreenTypeEnum => {
switch (true) {
case type === FolderType.Done:
return EmptyScreenTypeEnum.Done;
case type === FolderType.InProgress:
return EmptyScreenTypeEnum.InProgress;
case type === FolderType.SubFolderDone:
return EmptyScreenTypeEnum.SubFolderDone;
case type === FolderType.SubFolderInProgress:
return EmptyScreenTypeEnum.SubFolderinProgress;
case displayRoomCondition:
return EmptyScreenTypeEnum.Corporate;
default:
return EmptyScreenTypeEnum.Default;
}
};
export const getHeaderText = (
type: FolderTypeValueOfType | null,
displayRoomCondition: boolean,
t: Function
): string => {
const emptyType = getEmptyScreenType(type, displayRoomCondition);
const key = translateHeaderKey[emptyType];
return t(key);
};
export const getDescriptionText = (
type: FolderTypeValueOfType | null,
canCreateFiles: boolean,
t: Function
) => {
const emptyType = getEmptyScreenType(type, canCreateFiles);
const key = translateDescriptionKey[emptyType];
return t(key);
};

View File

@ -91,7 +91,7 @@ const EmptyFilterContainer = ({
export default inject(
({
auth,
settingsStore,
filesStore,
selectedFolderStore,
treeFoldersStore,
@ -110,7 +110,7 @@ export default inject(
isArchiveFolder,
isRoomsFolder,
setClearSearch: filesStore.setClearSearch,
theme: auth.settingsStore.theme,
theme: settingsStore.theme,
isPublicRoom,
publicRoomKey,

View File

@ -1,67 +1,68 @@
import EmptyScreenPersonalUrl from "PUBLIC_DIR/images/empty_screen_personal.svg?url";
import EmptyScreenPersonalDarkUrl from "PUBLIC_DIR/images/empty_screen_personal_dark.svg?url";
import EmptyScreenCorporateSvgUrl from "PUBLIC_DIR/images/empty_screen_corporate.svg?url";
import EmptyScreenCorporateDarkSvgUrl from "PUBLIC_DIR/images/empty_screen_corporate_dark.svg?url";
import { useCallback, useMemo } from "react";
import { inject, observer } from "mobx-react";
import { withTranslation } from "react-i18next";
import EmptyContainer from "./EmptyContainer";
import CommonButtons from "./sub-components/CommonButtons";
import {
getDescriptionText,
getEmptyScreenType,
getHeaderText,
getThemeMode,
headerIconsUrl,
} from "./EmptyContainer.helper";
const EmptyFolderContainer = ({
t,
onCreate,
type, // folder type
linkStyles,
sectionWidth,
canCreateFiles,
theme,
roomType,
//isLoading,
isArchiveFolderRoot,
isEmptyPage,
}) => {
//const location = useLocation();
// const isRoom =
// isLoading && location?.state?.isRoom ? location?.state?.isRoom : !!roomType;
const isRoom = !!roomType;
const displayRoomCondition = isRoom && !isArchiveFolderRoot;
const buttons = <CommonButtons onCreate={onCreate} linkStyles={linkStyles} />;
const emptyScreenCorporateSvg = theme.isBase
? EmptyScreenCorporateSvgUrl
: EmptyScreenCorporateDarkSvgUrl;
const emptyScreenAltSvg = theme.isBase
? EmptyScreenPersonalUrl
: EmptyScreenPersonalDarkUrl;
const getIcon = useCallback(() => {
const themeMode = getThemeMode(theme);
const emptyScreenType = getEmptyScreenType(type, displayRoomCondition);
const icon = headerIconsUrl[themeMode][emptyScreenType];
return icon;
}, [theme.isBase, displayRoomCondition, type]);
const imageSrc = useMemo(getIcon, [getIcon]);
const headerText = useMemo(
() => getHeaderText(type, displayRoomCondition, t),
[t, displayRoomCondition, type]
);
const descriptionText = useMemo(
() => getDescriptionText(type, canCreateFiles, t),
[t, canCreateFiles, type]
);
return (
<EmptyContainer
headerText={
displayRoomCondition ? t("RoomCreated") : t("EmptyScreenFolder")
}
descriptionText={
canCreateFiles
? t("EmptyFolderDecription")
: t("EmptyFolderDescriptionUser")
}
imageSrc={
displayRoomCondition ? emptyScreenCorporateSvg : emptyScreenAltSvg
}
headerText={headerText}
descriptionText={descriptionText}
buttons={buttons}
sectionWidth={sectionWidth}
imageSrc={imageSrc}
isEmptyPage={isEmptyPage}
sectionWidth={sectionWidth}
/>
);
};
export default inject(
({
auth,
settingsStore,
accessRightsStore,
selectedFolderStore,
clientLoadingStore,
@ -83,7 +84,7 @@ export default inject(
roomType,
canCreateFiles,
isArchiveFolderRoot,
theme: auth.settingsStore.theme,
theme: settingsStore.theme,
isEmptyPage,
};
}

View File

@ -83,19 +83,19 @@ const RoomNoAccessContainer = (props) => {
);
};
export default inject(({ auth, filesStore, clientLoadingStore }) => {
export default inject(({ settingsStore, filesStore, clientLoadingStore }) => {
const { setIsSectionFilterLoading } = clientLoadingStore;
const setIsLoading = (param) => {
setIsSectionFilterLoading(param);
};
const { isEmptyPage } = filesStore;
const { isFrame } = auth.settingsStore;
const { isFrame, theme } = settingsStore;
return {
setIsLoading,
isEmptyPage,
theme: auth.settingsStore.theme,
theme,
isFrame,
};
})(withTranslation(["Files"])(observer(RoomNoAccessContainer)));

View File

@ -75,7 +75,7 @@ const RootFolderContainer = (props) => {
const noFilesHeader = t("NoFilesHereYet");
const trashDescription = t("TrashEmptyDescription");
const favoritesDescription = t("FavoritesEmptyContainerDescription");
const recentDescription = t("RecentEmptyContainerDescription");
const recentDescription = t("RecentViaLinkEmptyContainerDescription");
const roomsDescription =
isVisitor || isCollaborator
@ -294,7 +294,7 @@ const RootFolderContainer = (props) => {
const goToPersonalButtons = (
<div className="empty-folder_container-links">
<img
className="empty-folder_container-image"
className="empty-folder_container-icon"
src={PersonSvgUrl}
alt="person_icon"
onClick={onGoToPersonal}
@ -332,14 +332,15 @@ const RootFolderContainer = (props) => {
export default inject(
({
auth,
settingsStore,
filesStore,
treeFoldersStore,
selectedFolderStore,
clientLoadingStore,
userStore,
}) => {
const { isDesktopClient, isEncryptionSupport, organizationName, theme } =
auth.settingsStore;
settingsStore;
const { setIsSectionFilterLoading } = clientLoadingStore;
@ -356,8 +357,8 @@ export default inject(
theme,
isPrivacyFolder,
isDesktop: isDesktopClient,
isVisitor: auth?.userStore?.user?.isVisitor,
isCollaborator: auth?.userStore?.user?.isCollaborator,
isVisitor: userStore?.user?.isVisitor,
isCollaborator: userStore?.user?.isCollaborator,
isEncryptionSupport,
organizationName,
privacyInstructions,

View File

@ -20,6 +20,7 @@ const EmptyContainer = ({
//isLoading,
parentId,
theme,
type,
sectionWidth,
isRoomNotFoundOrMoved,
@ -80,23 +81,25 @@ const EmptyContainer = ({
sectionWidth={sectionWidth}
onCreate={onCreate}
linkStyles={linkStyles}
type={type}
/>
);
};
export default inject(
({
auth,
settingsStore,
filesStore,
dialogsStore,
selectedFolderStore,
clientLoadingStore,
currentTariffStatusStore,
}) => {
const { isErrorRoomNotAvailable, isFiltered } = filesStore;
const { isLoading } = clientLoadingStore;
const { isGracePeriod } = auth.currentTariffStatusStore;
const { isGracePeriod } = currentTariffStatusStore;
const { setInviteUsersWarningDialogVisible } = dialogsStore;
@ -106,7 +109,7 @@ export default inject(
isErrorRoomNotAvailable;
return {
theme: auth.settingsStore.theme,
theme: settingsStore.theme,
isFiltered,
isLoading,
@ -114,6 +117,7 @@ export default inject(
isRoomNotFoundOrMoved,
isGracePeriod,
setInviteUsersWarningDialogVisible,
type: selectedFolderStore.type,
};
}
)(observer(EmptyContainer));

View File

@ -229,12 +229,12 @@ const CommonButtons = (props) => {
export default inject(
({
auth,
accessRightsStore,
treeFoldersStore,
selectedFolderStore,
contextOptionsStore,
clientLoadingStore,
settingsStore,
}) => {
const {
navigationPath,
@ -277,7 +277,7 @@ export default inject(
onClickInviteUsers,
folderId,
theme: auth.settingsStore.theme,
theme: settingsStore.theme,
isArchiveFolderRoot,
};
}

View File

@ -2,7 +2,6 @@ import React from "react";
import { useTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import {
SharingPanel,
UploadPanel,
VersionHistoryPanel,
ChangeOwnerPanel,
@ -33,6 +32,7 @@ import {
SettingsPluginDialog,
PluginDialog,
DeletePluginDialog,
ShareFolderDialog,
} from "../dialogs";
import ConvertPasswordDialog from "../dialogs/ConvertPasswordDialog";
import ArchiveDialog from "../dialogs/ArchiveDialog";
@ -46,7 +46,6 @@ import ChangeRoomOwnerPanel from "../panels/ChangeRoomOwnerPanel";
const Panels = (props) => {
const {
uploadPanelVisible,
sharingPanelVisible,
ownerPanelVisible,
copyPanelVisible,
moveToPanelVisible,
@ -89,6 +88,7 @@ const Panels = (props) => {
leaveRoomDialogVisible,
changeRoomOwnerIsVisible,
deletePluginDialogVisible,
shareFolderDialogVisible,
} = props;
const { t } = useTranslation(["Translations", "Common"]);
@ -114,12 +114,6 @@ const Panels = (props) => {
<PluginDialog isVisible={pluginDialogVisible} key={"plugin-dialog"} />
),
uploadPanelVisible && <UploadPanel key="upload-panel" />,
sharingPanelVisible && (
<SharingPanel
key="sharing-panel"
uploadPanelVisible={uploadPanelVisible}
/>
),
ownerPanelVisible && <ChangeOwnerPanel key="change-owner-panel" />,
(moveToPanelVisible ||
copyPanelVisible ||
@ -199,12 +193,13 @@ const Panels = (props) => {
changeRoomOwnerIsVisible && (
<ChangeRoomOwnerPanel key="change-room-owner" />
),
shareFolderDialogVisible && <ShareFolderDialog key="share-folder-dialog" />,
];
};
export default inject(
({
auth,
settingsStore,
dialogsStore,
uploadDataStore,
versionHistoryStore,
@ -213,7 +208,6 @@ export default inject(
pluginStore,
}) => {
const {
sharingPanelVisible,
ownerPanelVisible,
copyPanelVisible,
moveToPanelVisible,
@ -252,13 +246,14 @@ export default inject(
backupToPublicRoomVisible,
leaveRoomDialogVisible,
changeRoomOwnerIsVisible,
shareFolderDialogVisible,
} = dialogsStore;
const { preparationPortalDialogVisible } = backup;
const { uploadPanelVisible } = uploadDataStore;
const { isVisible: versionHistoryPanelVisible } = versionHistoryStore;
const { hotkeyPanelVisible } = auth.settingsStore;
const { hotkeyPanelVisible } = settingsStore;
const { confirmDialogIsLoading } = createEditRoomStore;
const {
@ -269,7 +264,6 @@ export default inject(
return {
preparationPortalDialogVisible,
sharingPanelVisible,
uploadPanelVisible,
ownerPanelVisible,
copyPanelVisible,
@ -312,6 +306,7 @@ export default inject(
leaveRoomDialogVisible,
changeRoomOwnerIsVisible,
deletePluginDialogVisible,
shareFolderDialogVisible,
};
}
)(observer(Panels));

View File

@ -1,129 +1,7 @@
export type Security = {
Copy: boolean;
CopyTo: boolean;
Create: boolean;
Delete: boolean;
Duplicate: boolean;
EditAccess: boolean;
EditRoom: boolean;
Move: boolean;
MoveTo: boolean;
Mute: boolean;
Pin: boolean;
Read: boolean;
Rename: boolean;
};
export type Item = {
id: number | string;
parentId: number | string;
rootFolderType: number | string;
title: string;
label: string;
filesCount?: number;
foldersCount?: number;
avatar?: string;
icon?: string;
isFolder: boolean;
isDisabled?: boolean;
security: Security;
roomType: number;
fileExst?: string;
};
export type BreadCrumb = {
label: string;
id: number | string;
isRoom: boolean;
};
type setItems = (value: Item[] | null) => Item[];
export type useLoadersHelperProps = {
items: Item[] | null;
};
export type setItemsCallback = (value: Item[] | null) => Item[] | null;
export type setBreadCrumbsCallback = (
value: BreadCrumb[] | []
) => BreadCrumb[] | [];
export type setTotalCallback = (value: number) => number;
export type useSocketHelperProps = {
socketHelper: any;
socketSubscribers: Set<string>;
setItems: (callback: setItemsCallback) => void;
setBreadCrumbs: (callback: setBreadCrumbsCallback) => void;
setTotal: (callback: setTotalCallback) => void;
disabledItems: string[] | number[];
filterParam?: string;
getIcon: (size: number, fileExst: string) => string;
};
export type useRootHelperProps = {
setBreadCrumbs: (items: BreadCrumb[]) => void;
setIsBreadCrumbsLoading: (value: boolean) => void;
setTotal: (value: number) => void;
setItems: (items: Item[] | setItems) => void;
treeFolders?: Item[];
setIsNextPageLoading: (value: boolean) => void;
setHasNextPage: (value: boolean) => void;
onSetBaseFolderPath?: (
value: number | string | undefined | BreadCrumb[]
) => void;
isUserOnly?: boolean;
};
export type useRoomsHelperProps = {
setBreadCrumbs: (items: BreadCrumb[]) => void;
setIsBreadCrumbsLoading: (value: boolean) => void;
setIsNextPageLoading: (value: boolean) => void;
setHasNextPage: (value: boolean) => void;
setTotal: (value: number) => void;
setItems: (items: Item[] | setItems) => void;
isFirstLoad: boolean;
setIsRoot: (value: boolean) => void;
searchValue?: string;
isRoomsOnly: boolean;
onSetBaseFolderPath?: (
value: number | string | undefined | BreadCrumb[]
) => void;
};
export type useFilesHelpersProps = {
roomsFolderId?: number;
setBreadCrumbs: (items: BreadCrumb[]) => void;
setIsBreadCrumbsLoading: (value: boolean) => void;
setIsSelectedParentFolder: (value: boolean) => void;
setIsNextPageLoading: (value: boolean) => void;
setHasNextPage: (value: boolean) => void;
setTotal: (value: number) => void;
setItems: (items: Item[] | setItems) => void;
isFirstLoad: boolean;
selectedItemId: string | number | undefined;
setIsRoot: (value: boolean) => void;
searchValue?: string;
disabledItems: string[] | number[];
setSelectedItemSecurity: (value: Security) => void;
isThirdParty: boolean;
onSelectTreeNode?: (treeNode: any) => void;
setSelectedTreeNode: (treeNode: any) => void;
filterParam?: string;
getRootData?: () => Promise<void>;
onSetBaseFolderPath?: (
value: number | string | undefined | BreadCrumb[]
) => void;
isRoomsOnly: boolean;
rootThirdPartyId?: string;
getRoomList?: (
startIndex: number,
isInit?: boolean,
search?: string | null,
isErrorPath?: boolean
) => void;
getIcon: (size: number, fileExst: string) => string;
t: any;
};
import { TFile, TFolder } from "@docspace/shared/api/files/types";
import { TBreadCrumb } from "@docspace/shared/components/selector/Selector.types";
import { DeviceType } from "@docspace/shared/enums";
import SocketIOHelper from "@docspace/shared/utils/socket";
export type FilesSelectorProps = {
isPanelVisible: boolean;
@ -148,63 +26,64 @@ export type FilesSelectorProps = {
filterParam?: string;
currentFolderId?: number;
currentFolderId: number;
fromFolderId?: number;
parentId?: number;
rootFolderType?: number;
parentId: number;
rootFolderType: number;
treeFolders?: Item[];
treeFolders?: TFolder[];
theme: any;
selection: any[];
selection: TFile[];
disabledItems: string[] | number[];
setMoveToPanelVisible: (value: boolean) => void;
setRestorePanelVisible: (value: boolean) => void;
setCopyPanelVisible: (value: boolean) => void;
setRestoreAllPanelVisible: (value: boolean) => void;
setMovingInProgress: (value: boolean) => void;
setIsDataReady?: (value: boolean) => void;
setSelected: (selected: "close" | "none", clearBuffer?: boolean) => void;
setConflictDialogData: (conflicts: any, operationData: any) => void;
itemOperationToFolder: (operationData: any) => Promise<void>;
setConflictDialogData: (conflicts: unknown, operationData: unknown) => void;
itemOperationToFolder: (operationData: unknown) => Promise<void>;
clearActiveOperations: (
folderIds: string[] | number[],
fileIds: string[] | number[]
fileIds: string[] | number[],
) => void;
checkFileConflicts: (
selectedItemId: string | number | undefined,
folderIds: string[] | number[],
fileIds: string[] | number[]
) => Promise<any>;
fileIds: string[] | number[],
) => Promise<unknown>;
onSetBaseFolderPath?: (
value: number | string | undefined | BreadCrumb[]
value: number | string | undefined | TBreadCrumb[],
) => void;
onSetNewFolderPath?: (value: number | string | undefined) => void;
onSelectFolder?: (
value: number | string | undefined,
breadCrumbs: BreadCrumb[]
breadCrumbs: TBreadCrumb[],
) => void;
onSelectTreeNode?: (treeNode: any) => void;
onSelectTreeNode?: (treeNode: unknown) => void;
onSave?: (
e: any,
e: unknown,
folderId: string | number,
fileTitle: string,
openNewTab: boolean
openNewTab: boolean,
) => void;
onSelectFile?: (
fileInfo: {
id: string | number;
title: string;
path?: string[];
fileExst?: string;
inPublic?: boolean;
},
breadCrumbs: BreadCrumb[]
breadCrumbs: TBreadCrumb[],
) => void;
setInfoPanelIsMobileHidden: (arg: boolean) => void;
withFooterInput?: boolean;
withFooterCheckbox?: boolean;
withFooterInput: boolean;
withFooterCheckbox: boolean;
footerInputHeader?: string;
currentFooterInputValue?: string;
footerCheckboxLabel?: string;
@ -214,14 +93,15 @@ export type FilesSelectorProps = {
includeFolder?: boolean;
socketHelper: any;
socketHelper: SocketIOHelper;
socketSubscribers: Set<string>;
currentDeviceType: "mobile" | "tablet" | "desktop";
currentDeviceType: DeviceType;
embedded: boolean;
withHeader: boolean;
withCancelButton: boolean;
settings: any;
id?: string | number;
roomsFolderId?: number;
};

View File

@ -6,11 +6,11 @@ import store from "client/store";
import FilesSelector from "./";
import i18n from "./i18n";
import { FilesSelectorProps } from "./FilesSelector.types";
const { auth: authStore, settingsStore } = store;
const { authStore, filesSettingsStore } = store;
const FilesSelectorWrapper = (props: FilesSelectorProps) => {
React.useEffect(() => {
const { setFilesSettings } = settingsStore;
const { setFilesSettings } = filesSettingsStore;
const { settings } = props;
authStore.init(true);
settings && setFilesSettings(settings);

View File

@ -1,148 +0,0 @@
import React from "react";
// @ts-ignore
import { getRooms } from "@docspace/shared/api/rooms";
// @ts-ignore
import RoomsFilter from "@docspace/shared/api/rooms/filter";
// @ts-ignore
import { RoomsType } from "@docspace/shared/enums";
// @ts-ignore
import { iconSize32 } from "@docspace/shared/utils/image-helpers";
import { PAGE_COUNT, defaultBreadCrumb } from "../utils";
import { BreadCrumb, Item, useRoomsHelperProps } from "../FilesSelector.types";
const getRoomLogo = (roomType: number) => {
let path = "";
switch (roomType) {
case RoomsType.CustomRoom:
path = "custom.svg";
break;
case RoomsType.EditingRoom:
path = "editing.svg";
break;
case RoomsType.PublicRoom:
path = "public.svg";
break;
}
return iconSize32.get(path);
};
export const convertRoomsToItems = (rooms: any) => {
const items = rooms.map((room: any) => {
const {
id,
title,
roomType,
logo,
filesCount,
foldersCount,
security,
parentId,
rootFolderType,
} = room;
const icon = logo.medium ? logo.medium : getRoomLogo(roomType);
return {
id,
label: title,
title,
icon,
filesCount,
foldersCount,
security,
parentId,
rootFolderType,
isFolder: true,
roomType,
color: logo.color,
};
});
return items;
};
const useRoomsHelper = ({
setIsNextPageLoading,
setHasNextPage,
setTotal,
setItems,
setBreadCrumbs,
setIsRoot,
isFirstLoad,
setIsBreadCrumbsLoading,
searchValue,
isRoomsOnly,
onSetBaseFolderPath,
}: useRoomsHelperProps) => {
const getRoomList = React.useCallback(
async (
startIndex: number,
isInit?: boolean,
search?: string | null,
isErrorPath?: boolean
) => {
setIsNextPageLoading(true);
const filterValue = search
? search
: search === null
? ""
: searchValue || "";
const page = startIndex / PAGE_COUNT;
const filter = RoomsFilter.getDefault();
filter.page = page;
filter.pageCount = PAGE_COUNT;
filter.filterValue = filterValue;
const rooms = await getRooms(filter);
const { folders, total, count, current } = rooms;
const { title, id } = current;
if (isInit) {
const breadCrumbs: BreadCrumb[] = [{ label: title, id, isRoom: true }];
!isRoomsOnly && breadCrumbs.unshift({ ...defaultBreadCrumb });
onSetBaseFolderPath &&
onSetBaseFolderPath(isErrorPath ? [] : breadCrumbs);
setBreadCrumbs(breadCrumbs);
setIsBreadCrumbsLoading(false);
}
const itemList: Item[] = convertRoomsToItems(folders);
setHasNextPage(count === PAGE_COUNT);
if (isFirstLoad || startIndex === 0) {
setTotal(total);
setItems(itemList);
} else {
setItems((prevState: Item[] | null) => {
if (prevState) return [...prevState, ...itemList];
return [...itemList];
});
}
setIsNextPageLoading(false);
setIsRoot(false);
},
[isFirstLoad, searchValue]
);
return { getRoomList };
};
export default useRoomsHelper;

View File

@ -1,236 +0,0 @@
import React from "react";
import { convertFilesToItems, convertFoldersToItems } from "./useFilesHelper";
import {
Item,
setItemsCallback,
useSocketHelperProps,
} from "../FilesSelector.types";
import { convertRoomsToItems } from "./useRoomsHelper";
const useSocketHelper = ({
socketHelper,
socketSubscribers,
setItems,
setBreadCrumbs,
setTotal,
disabledItems,
filterParam,
getIcon,
}: useSocketHelperProps) => {
const subscribedId = React.useRef<null | number>(null);
const subscribe = (id: number) => {
const roomParts = `DIR-${id}`;
if (socketSubscribers.has(roomParts)) return (subscribedId.current = id);
if (subscribedId.current && !socketSubscribers.has(roomParts)) {
unsubscribe(subscribedId.current, false);
}
socketHelper.emit({
command: "subscribe",
data: {
roomParts: `DIR-${id}`,
individual: true,
},
});
subscribedId.current = id;
};
const unsubscribe = (id: number, clear = true) => {
if (clear) {
subscribedId.current = null;
}
if (id && !socketSubscribers.has(`DIR-${id}`)) {
socketHelper.emit({
command: "unsubscribe",
data: {
roomParts: `DIR-${id}`,
individual: true,
},
});
}
};
const addItem = React.useCallback((opt: any) => {
if (!opt?.data) return;
const data = JSON.parse(opt.data);
if (
data.folderId
? data.folderId !== subscribedId.current
: data.parentId !== subscribedId.current
)
return;
let item: null | Item = null;
if (opt?.type === "file") {
item = convertFilesToItems([data], getIcon, filterParam)[0];
} else if (opt?.type === "folder") {
item = !!data.roomType
? convertRoomsToItems([data])[0]
: convertFoldersToItems([data], disabledItems, filterParam)[0];
}
const callback: setItemsCallback = (value: Item[] | null) => {
if (!item || !value) return value;
if (opt.type === "folder") {
setTotal((value) => value + 1);
return [item, ...value];
}
if (opt.type === "file") {
let idx = 0;
for (let i = 0; i < value.length - 1; i++) {
if (!value[i].isFolder) break;
idx = i + 1;
}
const newValue = [...value];
newValue.splice(idx, 0, item);
setTotal((value) => value + 1);
return newValue;
}
return value;
};
setItems(callback);
}, []);
const updateItem = React.useCallback((opt: any) => {
if (!opt?.data) return;
const data = JSON.parse(opt.data);
if (
((data.folderId && data.folderId !== subscribedId.current) ||
(data.parentId && data.parentId !== subscribedId.current)) &&
data.id !== subscribedId.current
)
return;
let item: null | Item = null;
if (opt?.type === "file") {
item = convertFilesToItems([data], getIcon, filterParam)[0];
} else if (opt?.type === "folder") {
item = !!data.roomType
? convertRoomsToItems([data])[0]
: convertFoldersToItems([data], disabledItems, filterParam)[0];
}
if (item?.id === subscribedId.current) {
return setBreadCrumbs((value) => {
if (!value) return value;
const newValue = [...value];
if (newValue[newValue.length - 1].id === item?.id) {
newValue[newValue.length - 1].label = item.label;
}
return newValue;
});
}
const callback: setItemsCallback = (value: Item[] | null) => {
if (!item || !value) return value;
if (opt.type === "folder") {
const idx = value.findIndex((v) => v.id === item?.id && v.isFolder);
if (idx > -1) {
const newValue = [...value];
newValue.splice(idx, 1, item);
return newValue;
}
setBreadCrumbs((breadCrumbsValue) => {
return breadCrumbsValue;
});
}
if (opt.type === "file") {
const idx = value.findIndex((v) => v.id === item?.id && !v.isFolder);
if (idx > -1) {
const newValue = [...value];
newValue.splice(idx, 1, item);
return [...newValue];
}
}
return value;
};
setItems(callback);
}, []);
const deleteItem = React.useCallback((opt: any) => {
const callback: setItemsCallback = (value: Item[] | null) => {
if (!value) return value;
if (opt.type === "folder") {
const newValue = value.filter((v) => +v.id !== +opt?.id || !v.isFolder);
if (newValue.length !== value.length) {
setTotal((value) => value - 1);
}
return newValue;
}
if (opt.type === "file") {
const newValue = value.filter((v) => +v.id !== +opt?.id || v.isFolder);
if (newValue.length !== value.length) {
setTotal((value) => value - 1);
}
return newValue;
}
return value;
};
setItems(callback);
}, []);
React.useEffect(() => {
socketHelper.on("s:modify-folder", async (opt: any) => {
switch (opt?.cmd) {
case "create":
addItem(opt);
break;
case "update":
updateItem(opt);
break;
case "delete":
deleteItem(opt);
break;
}
});
}, [addItem, updateItem, deleteItem]);
return { subscribe, unsubscribe };
};
export default useSocketHelper;

View File

@ -1,45 +1,41 @@
/* eslint-disable no-restricted-syntax */
import React from "react";
import { inject, observer } from "mobx-react";
import { useTranslation } from "react-i18next";
// @ts-ignore
import Loaders from "@docspace/common/components/Loaders";
import { FolderType, RoomsType } from "@docspace/shared/enums";
import { DeviceType } from "@docspace/shared/enums";
import { Selector } from "@docspace/shared/components/selector";
import { Aside } from "@docspace/shared/components/aside";
import { Backdrop } from "@docspace/shared/components/backdrop";
import { Portal } from "@docspace/shared/components/portal";
import { FolderType } from "@docspace/shared/enums";
import FilesSelector from "@docspace/shared/selectors/Files";
import { toastr } from "@docspace/shared/components/toast";
import EmptyScreenFilterAltSvgUrl from "PUBLIC_DIR/images/empty_screen_filter_alt.svg?url";
import EmptyScreenFilterAltDarkSvgUrl from "PUBLIC_DIR/images/empty_screen_filter_alt_dark.svg?url";
import EmptyScreenAltSvgUrl from "PUBLIC_DIR/images/empty_screen_alt.svg?url";
import EmptyScreenAltSvgDarkUrl from "PUBLIC_DIR/images/empty_screen_alt_dark.svg?url";
import { SettingsStore } from "@docspace/shared/store/SettingsStore";
import {
BreadCrumb,
FilesSelectorProps,
Item,
Security,
} from "./FilesSelector.types";
TFileSecurity,
TFolder,
TFolderSecurity,
} from "@docspace/shared/api/files/types";
import { TBreadCrumb } from "@docspace/shared/components/selector/Selector.types";
import { TData } from "@docspace/shared/components/toast/Toast.type";
import { TSelectedFileInfo } from "@docspace/shared/selectors/Files/FilesSelector.types";
import { TRoomSecurity } from "@docspace/shared/api/rooms/types";
import { TTranslation } from "@docspace/shared/types";
import useRootHelper from "./helpers/useRootHelper";
import useRoomsHelper from "./helpers/useRoomsHelper";
import useLoadersHelper from "./helpers/useLoadersHelper";
import useFilesHelper from "./helpers/useFilesHelper";
import SelectedFolderStore from "SRC_DIR/store/SelectedFolderStore";
import FilesActionStore from "SRC_DIR/store/FilesActionsStore";
import UploadDataStore from "SRC_DIR/store/UploadDataStore";
import TreeFoldersStore from "SRC_DIR/store/TreeFoldersStore";
import DialogsStore from "SRC_DIR/store/DialogsStore";
import FilesStore from "SRC_DIR/store/FilesStore";
import InfoPanelStore from "SRC_DIR/store/InfoPanelStore";
import { FilesSelectorProps } from "./FilesSelector.types";
import { getAcceptButtonLabel, getHeaderLabel, getIsDisabled } from "./utils";
import useSocketHelper from "./helpers/useSocketHelper";
const FilesSelector = ({
const FilesSelectorWrapper = ({
isPanelVisible = false,
// withoutImmediatelyClose = false,
isThirdParty = false,
isRoomsOnly = false,
isUserOnly = false,
isEditorDialog = false,
rootThirdPartyId,
filterParam,
@ -58,8 +54,6 @@ const FilesSelector = ({
treeFolders,
theme,
selection,
disabledItems,
setConflictDialogData,
@ -75,7 +69,8 @@ const FilesSelector = ({
onSelectFolder,
onSetBaseFolderPath,
//onSetNewFolderPath,
// onSetNewFolderPath,
setIsDataReady,
onSelectTreeNode,
onSave,
onSelectFile,
@ -106,239 +101,15 @@ const FilesSelector = ({
roomsFolderId,
}: FilesSelectorProps) => {
const { t } = useTranslation(["Files", "Common", "Translations"]);
const [breadCrumbs, setBreadCrumbs] = React.useState<BreadCrumb[]>([]);
const [items, setItems] = React.useState<Item[] | null>(null);
const [selectedItemType, setSelectedItemType] = React.useState<
"rooms" | "files" | undefined
>(undefined);
const [selectedItemId, setSelectedItemId] = React.useState<
number | string | undefined
>(undefined);
const [selectedItemSecurity, setSelectedItemSecurity] = React.useState<
Security | undefined
>(undefined);
const [selectedTreeNode, setSelectedTreeNode] = React.useState(null);
const [selectedFileInfo, setSelectedFileInfo] = React.useState<{
id: number | string;
title: string;
path?: string[];
fileExst?: string;
} | null>(null);
const [total, setTotal] = React.useState<number>(0);
const [hasNextPage, setHasNextPage] = React.useState<boolean>(false);
const [isSelectedParentFolder, setIsSelectedParentFolder] =
React.useState<boolean>(false);
const [searchValue, setSearchValue] = React.useState<string>("");
const { t }: { t: TTranslation } = useTranslation([
"Files",
"Common",
"Translations",
]);
const [isRequestRunning, setIsRequestRunning] =
React.useState<boolean>(false);
const { subscribe, unsubscribe } = useSocketHelper({
socketHelper,
socketSubscribers,
setItems,
setBreadCrumbs,
setTotal,
disabledItems,
filterParam,
getIcon,
});
const {
setIsBreadCrumbsLoading,
isNextPageLoading,
setIsNextPageLoading,
isFirstLoad,
setIsFirstLoad,
showBreadCrumbsLoader,
showLoader,
} = useLoadersHelper({ items });
const { isRoot, setIsRoot, getRootData } = useRootHelper({
setIsBreadCrumbsLoading,
setBreadCrumbs,
setTotal,
setItems,
treeFolders,
setHasNextPage,
setIsNextPageLoading,
onSetBaseFolderPath,
isUserOnly,
});
const { getRoomList } = useRoomsHelper({
setIsBreadCrumbsLoading,
setBreadCrumbs,
setIsNextPageLoading,
setHasNextPage,
setTotal,
setItems,
isFirstLoad,
setIsRoot,
searchValue,
isRoomsOnly,
onSetBaseFolderPath,
});
const { getFileList } = useFilesHelper({
setIsBreadCrumbsLoading,
setBreadCrumbs,
setIsNextPageLoading,
setHasNextPage,
setTotal,
setItems,
selectedItemId,
isFirstLoad,
setIsRoot,
searchValue,
disabledItems,
setSelectedItemSecurity,
isThirdParty,
onSelectTreeNode,
setSelectedTreeNode,
filterParam,
getRootData,
onSetBaseFolderPath,
isRoomsOnly,
rootThirdPartyId,
getRoomList,
getIcon,
t,
setIsSelectedParentFolder,
roomsFolderId,
});
const onSelectAction = (item: Item) => {
if (item.isFolder) {
setIsFirstLoad(true);
setItems(null);
setBreadCrumbs((value) => [
...value,
{
label: item.label,
id: item.id,
isRoom:
item.parentId === 0 && item.rootFolderType === FolderType.Rooms,
roomType: item.roomType,
},
]);
setSelectedItemId(item.id);
setSearchValue("");
if (item.parentId === 0 && item.rootFolderType === FolderType.Rooms) {
setSelectedItemType("rooms");
getRoomList(0, false, null);
} else {
setSelectedItemType("files");
getFileList(0, item.id, false, null);
}
} else {
setSelectedFileInfo({
id: item.id,
title: item.title,
fileExst: item.fileExst,
});
}
};
React.useEffect(() => {
if (!selectedItemId) return;
if (selectedItemId && isRoot) return unsubscribe(+selectedItemId);
subscribe(+selectedItemId);
}, [selectedItemId, isRoot]);
React.useEffect(() => {
const getRoomSettings = () => {
setSelectedItemType("rooms");
getRoomList(0, true);
};
const needRoomList = isRoomsOnly && !currentFolderId;
if (needRoomList) {
getRoomSettings();
return;
}
if (!currentFolderId) {
getRootData();
return;
}
setSelectedItemId(currentFolderId);
if (
needRoomList ||
(!isThirdParty &&
parentId === roomsFolderId &&
rootFolderType === FolderType.Rooms)
) {
getRoomSettings();
return;
}
setSelectedItemType("files");
getFileList(0, currentFolderId, true);
}, []);
const onClickBreadCrumb = (item: BreadCrumb) => {
if (!isFirstLoad) {
setSearchValue("");
setIsFirstLoad(true);
if (+item.id === 0) {
setSelectedItemSecurity(undefined);
setSelectedItemType(undefined);
getRootData();
} else {
setItems(null);
const idx = breadCrumbs.findIndex(
(value) => value.id.toString() === item.id.toString()
);
const maxLength = breadCrumbs.length - 1;
let foundParentId = false,
currentFolderIndex = -1;
const newBreadCrumbs = breadCrumbs.map((item, index) => {
if (!foundParentId) {
currentFolderIndex = disabledItems.findIndex(
(id) => id === item?.id
);
}
if (index !== maxLength && currentFolderIndex !== -1) {
foundParentId = true;
!isSelectedParentFolder && setIsSelectedParentFolder(true);
}
if (index === maxLength && !foundParentId && isSelectedParentFolder)
setIsSelectedParentFolder(false);
return { ...item };
});
newBreadCrumbs.splice(idx + 1, newBreadCrumbs.length - idx - 1);
setBreadCrumbs(newBreadCrumbs);
setSelectedItemId(item.id);
if (item.isRoom) {
setSelectedItemType("rooms");
getRoomList(0, false, null);
} else {
setSelectedItemType("files");
getFileList(0, item.id, false, null);
}
}
}
};
const onCloseAction = () => {
setInfoPanelIsMobileHidden(false);
@ -363,47 +134,24 @@ const FilesSelector = ({
onCloseAction();
};
const onSearchAction = (value: string) => {
setIsFirstLoad(true);
setItems(null);
if (selectedItemType === "rooms") {
getRoomList(0, false, value === "" ? null : value);
} else {
getFileList(0, selectedItemId, false, value === "" ? null : value);
}
const getFilesArchiveError = (name: string) =>
t("Files:ArchivedRoomAction", { name });
setSearchValue(value);
};
const onClearSearchAction = () => {
setIsFirstLoad(true);
setItems(null);
if (selectedItemType === "rooms") {
getRoomList(0, false, null);
} else {
getFileList(0, selectedItemId, false, null);
}
setSearchValue("");
};
const onAcceptAction = (
items: any,
accessRights: any,
const onAccept = async (
selectedItemId: string | number | undefined,
folderTitle: string,
isPublic: boolean,
breadCrumbs: TBreadCrumb[],
fileName: string,
isChecked: boolean
isChecked: boolean,
selectedTreeNode: TFolder,
selectedFileInfo: TSelectedFileInfo,
) => {
const isPublic =
breadCrumbs.findIndex((f: any) => f.roomType === RoomsType.PublicRoom) >
-1;
if ((isMove || isCopy || isRestore || isRestoreAll) && !isEditorDialog) {
const folderTitle = breadCrumbs[breadCrumbs.length - 1].label;
const fileIds: number[] = [];
const folderIds: number[] = [];
let fileIds: any[] = [];
let folderIds: any[] = [];
for (let item of selection) {
for (const item of selection) {
if (item.fileExst || item.contentLength) {
fileIds.push(item.id);
} else if (item.id === selectedItemId) {
@ -432,27 +180,30 @@ const FilesSelector = ({
return;
}
setIsRequestRunning(true);
setSelectedItems();
checkFileConflicts(selectedItemId, folderIds, fileIds)
.then(async (conflicts: any) => {
if (conflicts.length) {
setConflictDialogData(conflicts, operationData);
setIsRequestRunning(false);
} else {
setIsRequestRunning(false);
onCloseAndDeselectAction();
const move = !isCopy;
if (move) setMovingInProgress(move);
sessionStorage.setItem("filesSelectorPath", `${selectedItemId}`);
await itemOperationToFolder(operationData);
}
})
.catch((e: any) => {
toastr.error(e);
try {
const conflicts = (await checkFileConflicts(
selectedItemId,
folderIds,
fileIds,
)) as [];
if (conflicts.length) {
setConflictDialogData(conflicts, operationData);
setIsRequestRunning(false);
clearActiveOperations(fileIds, folderIds);
});
} else {
setIsRequestRunning(false);
onCloseAndDeselectAction();
const move = !isCopy;
if (move) setMovingInProgress(move);
sessionStorage.setItem("filesSelectorPath", `${selectedItemId}`);
await itemOperationToFolder(operationData);
}
} catch (e: unknown) {
toastr.error(e as TData);
setIsRequestRunning(false);
clearActiveOperations(fileIds, folderIds);
}
} else {
toastr.error(t("Common:ErrorEmptyList"));
}
@ -467,16 +218,14 @@ const FilesSelector = ({
return;
}
//setIsRequestRunning(true);
//onSetNewFolderPath && onSetNewFolderPath(breadCrumbs);
onSelectFolder && onSelectFolder(selectedItemId, breadCrumbs);
onSave &&
selectedItemId &&
if (onSelectFolder) onSelectFolder(selectedItemId, breadCrumbs);
if (onSave && selectedItemId)
onSave(null, selectedItemId, fileName, isChecked);
onSelectTreeNode && onSelectTreeNode(selectedTreeNode);
onSelectFile && onSelectFile(selectedFileInfo, breadCrumbs);
if (onSelectTreeNode) onSelectTreeNode(selectedTreeNode);
if (onSelectFile && selectedFileInfo)
onSelectFile(selectedFileInfo, breadCrumbs);
onCloseAndDeselectAction();
//!withoutImmediatelyClose && onCloseAction();
}
};
@ -487,7 +236,7 @@ const FilesSelector = ({
isMove,
isSelect,
filterParam,
isRestore
isRestore,
);
const acceptButtonLabel = getAcceptButtonLabel(
@ -497,82 +246,80 @@ const FilesSelector = ({
isMove,
isSelect,
filterParam,
isRestore
isRestore,
);
const isDisabled = getIsDisabled(
isFirstLoad,
isSelectedParentFolder,
fromFolderId == selectedItemId,
selectedItemType === "rooms",
isRoot,
isCopy,
isMove,
isRestoreAll,
isRequestRunning,
selectedItemSecurity,
filterParam,
!!selectedFileInfo,
includeFolder,
isRestore
);
const getIsDisabledAction = (
isFirstLoad: boolean,
isSelectedParentFolder: boolean,
selectedItemId: string | number | undefined,
selectedItemType: "rooms" | "files" | undefined,
isRoot: boolean,
selectedItemSecurity:
| TFileSecurity
| TFolderSecurity
| TRoomSecurity
| undefined,
selectedFileInfo: TSelectedFileInfo,
) => {
return getIsDisabled(
isFirstLoad,
isSelectedParentFolder,
fromFolderId === selectedItemId,
selectedItemType === "rooms",
isRoot,
isCopy,
isMove,
isRestoreAll,
isRequestRunning,
selectedItemSecurity,
filterParam,
!!selectedFileInfo,
includeFolder,
isRestore,
);
};
const SelectorBody = (
<Selector
return (
<FilesSelector
socketHelper={socketHelper}
socketSubscribers={socketSubscribers}
disabledItems={disabledItems}
filterParam={filterParam}
getIcon={getIcon}
setIsDataReady={setIsDataReady}
treeFolders={treeFolders}
onSetBaseFolderPath={onSetBaseFolderPath}
isUserOnly={isUserOnly}
isRoomsOnly={isRoomsOnly}
isThirdParty={isThirdParty}
rootThirdPartyId={rootThirdPartyId}
roomsFolderId={roomsFolderId}
currentFolderId={currentFolderId}
parentId={parentId}
rootFolderType={rootFolderType}
currentDeviceType={currentDeviceType}
onClose={onCloseAction}
onCloseAction={onCloseAction}
onAccept={onAccept}
getIsDisabled={getIsDisabledAction}
withHeader={withHeader}
headerLabel={headerLabel}
withoutBackButton
searchPlaceholder={t("Common:Search")}
searchValue={searchValue}
onSearch={onSearchAction}
onClearSearch={onClearSearchAction}
items={items ? items : []}
onSelect={onSelectAction}
acceptButtonLabel={acceptButtonLabel}
onAccept={onAcceptAction}
withCancelButton={withCancelButton}
cancelButtonLabel={t("Common:CancelButton")}
onCancel={onCloseAction}
emptyScreenImage={
theme.isBase ? EmptyScreenAltSvgUrl : EmptyScreenAltSvgDarkUrl
}
emptyScreenHeader={t("SelectorEmptyScreenHeader")}
emptyScreenDescription=""
searchEmptyScreenImage={
theme.isBase
? EmptyScreenFilterAltSvgUrl
: EmptyScreenFilterAltDarkSvgUrl
}
searchEmptyScreenHeader={t("Common:NotFoundTitle")}
searchEmptyScreenDescription={t("EmptyFilterDescriptionText")}
withBreadCrumbs
breadCrumbs={breadCrumbs}
onSelectBreadCrumb={onClickBreadCrumb}
isLoading={showLoader}
isBreadCrumbsLoading={showBreadCrumbsLoader}
withSearch={!isRoot && items ? items.length > 0 : !isRoot && isFirstLoad}
rowLoader={
<Loaders.SelectorRowLoader
isMultiSelect={false}
isUser={isRoot}
isContainer={showLoader}
/>
}
searchLoader={<Loaders.SelectorSearchLoader />}
breadCrumbsLoader={<Loaders.SelectorBreadCrumbsLoader />}
alwaysShowFooter={true}
isNextPageLoading={isNextPageLoading}
hasNextPage={hasNextPage}
totalItems={total}
loadNextPage={
isRoot ? null : selectedItemType === "rooms" ? getRoomList : getFileList
}
disableAcceptButton={isDisabled}
isPanelVisible={isPanelVisible}
embedded={embedded}
withFooterInput={withFooterInput}
withFooterCheckbox={withFooterCheckbox}
footerInputHeader={footerInputHeader}
currentFooterInputValue={currentFooterInputValue}
footerCheckboxLabel={footerCheckboxLabel}
footerInputHeader={footerInputHeader || ""}
currentFooterInputValue={currentFooterInputValue || ""}
footerCheckboxLabel={footerCheckboxLabel || ""}
descriptionText={
!filterParam || filterParam === "ALL"
? ""
@ -584,50 +331,40 @@ const FilesSelector = ({
cancelButtonId={
isMove || isCopy || isRestore ? "select-file-modal-cancel" : ""
}
getFilesArchiveError={getFilesArchiveError}
/>
);
const selectorComponent = embedded ? (
SelectorBody
) : (
<>
<Backdrop
visible={isPanelVisible}
isAside
withBackground
zIndex={309}
onClick={onCloseAction}
/>
<Aside
visible={isPanelVisible}
withoutBodyScroll
zIndex={310}
onClose={onCloseAction}
>
{SelectorBody}
</Aside>
</>
);
return currentDeviceType === DeviceType.mobile && !embedded ? (
<Portal visible={isPanelVisible} element={<div>{selectorComponent}</div>} />
) : (
selectorComponent
);
};
export default inject(
(
{
auth,
settingsStore,
selectedFolderStore,
filesActionsStore,
uploadDataStore,
treeFoldersStore,
dialogsStore,
filesStore,
}: any,
{ isCopy, isRestoreAll, isMove, isRestore, isPanelVisible, id }: any
infoPanelStore,
}: {
settingsStore: SettingsStore;
selectedFolderStore: SelectedFolderStore;
filesActionsStore: FilesActionStore;
uploadDataStore: UploadDataStore;
treeFoldersStore: TreeFoldersStore;
dialogsStore: DialogsStore;
filesStore: FilesStore;
infoPanelStore: InfoPanelStore;
},
{
isCopy,
isRestoreAll,
isMove,
isRestore,
isPanelVisible,
id,
}: FilesSelectorProps,
) => {
const { id: selectedId, parentId, rootFolderType } = selectedFolderStore;
@ -653,10 +390,9 @@ export default inject(
setBackupToPublicRoomVisible,
} = dialogsStore;
const { setIsMobileHidden: setInfoPanelIsMobileHidden } =
auth.infoPanelStore;
const { setIsMobileHidden: setInfoPanelIsMobileHidden } = infoPanelStore;
const { theme, socketHelper, currentDeviceType } = auth.settingsStore;
const { socketHelper, currentDeviceType } = settingsStore;
const socketSubscribesId = socketHelper.socketSubscribers;
@ -669,8 +405,8 @@ export default inject(
filesSettingsStore,
} = filesStore;
const { getIcon } = filesSettingsStore;
const { isVisible: infoPanelIsVisible, selection: infoPanelSelection } =
auth.infoPanelStore;
const { isVisible: infoPanelIsVisible, infoPanelSelection } =
infoPanelStore;
const selections =
isMove || isCopy || isRestoreAll || isRestore
@ -689,27 +425,27 @@ export default inject(
? filesList
: isCopy
? selections
: selections.filter((f: any) => f && !f?.isEditing);
: selections.filter((f) => f && !f?.isEditing);
const disabledItems: any[] = [];
const disabledItems: (string | number)[] = [];
selectionsWithoutEditing.forEach((item: any) => {
selectionsWithoutEditing.forEach((item) => {
if ((item?.isFolder || item?.parentId) && item?.id) {
disabledItems.push(item.id);
}
});
const includeFolder =
selectionsWithoutEditing.filter((i: any) => i.isFolder).length > 0;
selectionsWithoutEditing.filter((i) => i.isFolder).length > 0;
const fromFolderId = id
? id
: rootFolderType === FolderType.Archive ||
rootFolderType === FolderType.TRASH
const fromFolderId =
id ||
(rootFolderType === FolderType.Archive ||
rootFolderType === FolderType.TRASH
? undefined
: selectedId === selectionsWithoutEditing[0]?.id
? parentId
: selectedId;
: selectedId);
const currentFolderId =
sessionPath && (isMove || isCopy || isRestore || isRestoreAll)
@ -722,16 +458,16 @@ export default inject(
parentId,
rootFolderType,
treeFolders,
isPanelVisible: isPanelVisible
? isPanelVisible
: (moveToPanelVisible ||
copyPanelVisible ||
restorePanelVisible ||
restoreAllPanelVisible) &&
!conflictResolveDialogVisible,
isPanelVisible:
isPanelVisible ||
((moveToPanelVisible ||
copyPanelVisible ||
restorePanelVisible ||
restoreAllPanelVisible) &&
!conflictResolveDialogVisible),
setMoveToPanelVisible,
setRestorePanelVisible,
theme,
selection: selectionsWithoutEditing,
disabledItems,
setConflictDialogData,
@ -754,5 +490,5 @@ export default inject(
roomsFolderId,
};
}
)(observer(FilesSelector));
},
)(observer(FilesSelectorWrapper));

View File

@ -1,25 +1,19 @@
import { TTranslation } from "@docspace/shared/types";
import { FilesSelectorFilterTypes } from "@docspace/shared/enums";
import { BreadCrumb, Security } from "./FilesSelector.types";
export const PAGE_COUNT = 100;
export const defaultBreadCrumb: BreadCrumb = {
label: "DocSpace",
id: 0,
isRoom: false,
};
export const SHOW_LOADER_TIMER = 500;
export const MIN_LOADER_TIMER = 500;
import {
TFileSecurity,
TFolderSecurity,
} from "@docspace/shared/api/files/types";
import { TRoomSecurity } from "@docspace/shared/api/rooms/types";
export const getHeaderLabel = (
t: any,
t: TTranslation,
isCopy?: boolean,
isRestoreAll?: boolean,
isMove?: boolean,
isSelect?: boolean,
filterParam?: string,
isRestore?: boolean
isRestore?: boolean,
) => {
if (isRestore) return t("Common:RestoreTo");
if (isMove) return t("Common:MoveTo");
@ -31,19 +25,19 @@ export const getHeaderLabel = (
if (filterParam === FilesSelectorFilterTypes.DOCX)
return t("Translations:CreateMasterFormFromFile");
if (!!filterParam) return t("Common:SelectFile");
if (filterParam) return t("Common:SelectFile");
return t("Common:SaveButton");
};
export const getAcceptButtonLabel = (
t: any,
t: TTranslation,
isCopy?: boolean,
isRestoreAll?: boolean,
isMove?: boolean,
isSelect?: boolean,
filterParam?: string,
isRestore?: boolean
isRestore?: boolean,
) => {
if (isRestore) return t("Common:RestoreHere");
if (isMove) return t("Translations:MoveHere");
@ -53,7 +47,7 @@ export const getAcceptButtonLabel = (
if (filterParam === FilesSelectorFilterTypes.DOCX) return t("Common:Create");
// if (filterParam === FilesSelectorFilterTypes.DOCXF) return t("Common:SubmitToGallery");
if (!!filterParam) return t("Common:SaveButton");
if (filterParam) return t("Common:SaveButton");
return t("Common:SaveHereButton");
};
@ -68,22 +62,25 @@ export const getIsDisabled = (
isMove?: boolean,
isRestoreAll?: boolean,
isRequestRunning?: boolean,
security?: Security,
security?: TFileSecurity | TFolderSecurity | TRoomSecurity,
filterParam?: string,
isFileSelected?: boolean,
includeFolder?: boolean,
isRestore?: boolean
isRestore?: boolean,
) => {
if (isFirstLoad) return true;
if (isRequestRunning) return true;
if (!!filterParam) return !isFileSelected;
if (filterParam) return !isFileSelected;
if (sameId && !isCopy) return true;
if (sameId && isCopy && includeFolder) return true;
if (isRooms) return true;
if (isRoot) return true;
if (isSelectedParentFolder) return true;
if (isCopy) return !security?.CopyTo;
if (isMove || isRestoreAll || isRestore) return !security?.MoveTo;
if (!security) return false;
if (isCopy) return "CopyTo" in security ? !security?.CopyTo : !security.Copy;
if (isMove || isRestoreAll || isRestore)
return "MoveTo" in security ? !security?.MoveTo : !security.Move;
return false;
};

View File

@ -19,7 +19,7 @@ const ChangeUserTypeEvent = ({
onClose,
setSelected,
getPeopleListItem,
setSelection,
setInfoPanelSelection,
needResetUserSelection,
isRoomAdmin,
}) => {
@ -70,7 +70,7 @@ const ChangeUserTypeEvent = ({
if (!needResetUserSelection) {
const user = getPeopleListItem(users[0]);
setSelection(user);
setInfoPanelSelection(user);
}
successCallback && successCallback(users);
@ -138,36 +138,38 @@ const ChangeUserTypeEvent = ({
);
};
export default inject(({ auth, dialogsStore, peopleStore }) => {
const {
changeUserTypeDialogVisible: visible,
setChangeUserTypeDialogVisible: setVisible,
} = dialogsStore;
const { isRoomAdmin, infoPanelStore } = auth;
const { setSelection } = infoPanelStore;
const { dialogStore, filterStore, usersStore } = peopleStore;
export default inject(
({ authStore, dialogsStore, peopleStore, infoPanelStore }) => {
const {
changeUserTypeDialogVisible: visible,
setChangeUserTypeDialogVisible: setVisible,
} = dialogsStore;
const { isRoomAdmin } = authStore;
const { setInfoPanelSelection } = infoPanelStore;
const { dialogStore, filterStore, usersStore } = peopleStore;
const { data: peopleDialogData } = dialogStore;
const { filter: peopleFilter } = filterStore;
const {
updateUserType,
getUsersList,
getPeopleListItem,
needResetUserSelection,
} = usersStore;
const { setSelected } = peopleStore.selectionStore;
return {
isRoomAdmin,
needResetUserSelection,
getPeopleListItem,
setSelection,
setSelected,
const { data: peopleDialogData } = dialogStore;
const { filter: peopleFilter } = filterStore;
const {
updateUserType,
getUsersList,
getPeopleListItem,
needResetUserSelection,
} = usersStore;
const { setSelected } = peopleStore.selectionStore;
return {
isRoomAdmin,
needResetUserSelection,
getPeopleListItem,
setInfoPanelSelection,
setSelected,
visible,
setVisible,
peopleDialogData,
peopleFilter,
updateUserType,
getUsersList,
};
})(observer(ChangeUserTypeEvent));
visible,
setVisible,
peopleDialogData,
peopleFilter,
updateUserType,
getUsersList,
};
}
)(observer(ChangeUserTypeEvent));

View File

@ -1,11 +1,11 @@
import React from "react";
import { inject, observer } from "mobx-react";
import { useTranslation } from "react-i18next";
import api from "@docspace/shared/api";
import { toastr } from "@docspace/shared/components/toast";
import { combineUrl } from "@docspace/shared/utils/combineUrl";
import { setEncryptionAccess } from "SRC_DIR/helpers/desktop";
import config from "PACKAGE_FILE";
import { getTitleWithoutExtension } from "SRC_DIR/helpers/filesUtils";
@ -43,9 +43,6 @@ const CreateEvent = ({
setConvertPasswordDialogVisible,
setFormCreationInfo,
replaceFileStream,
setEncryptionAccess,
setEventDialogVisible,
eventDialogVisible,
keepNewFileName,
@ -248,14 +245,11 @@ const CreateEvent = ({
if (!encryptedFile) return Promise.resolve();
toastr.info(t("Translations:EncryptedFileSaving"));
return replaceFileStream(
file.id,
encryptedFile,
true,
false
).then(
() => open && openDocEditor(file.id, file.providerKey, tab)
);
return api.files
.updateFileStream(file.id, encryptedFile, true, false)
.then(
() => open && openDocEditor(file.id, file.providerKey, tab)
);
});
}
@ -296,7 +290,7 @@ const CreateEvent = ({
export default inject(
({
auth,
settingsStore,
filesStore,
filesActionsStore,
selectedFolderStore,
@ -304,8 +298,9 @@ export default inject(
uploadDataStore,
dialogsStore,
oformsStore,
settingsStore,
filesSettingsStore,
clientLoadingStore,
currentTariffStatusStore,
}) => {
const { setIsSectionBodyLoading } = clientLoadingStore;
@ -332,10 +327,7 @@ export default inject(
const { id: parentId } = selectedFolderStore;
const { replaceFileStream, setEncryptionAccess, currentTariffStatusStore } =
auth;
const { isDesktopClient } = auth.settingsStore;
const { isDesktopClient } = settingsStore;
const { setPortalTariff } = currentTariffStatusStore;
@ -346,7 +338,7 @@ export default inject(
eventDialogVisible,
} = dialogsStore;
const { keepNewFileName } = settingsStore;
const { keepNewFileName } = filesSettingsStore;
return {
setPortalTariff,
@ -375,9 +367,6 @@ export default inject(
setConvertPasswordDialogVisible,
setFormCreationInfo,
replaceFileStream,
setEncryptionAccess,
keepNewFileName,
};
}

View File

@ -84,13 +84,13 @@ export default inject(
tagsStore,
dialogsStore,
settingsStore,
filesSettingsStore,
}) => {
const { fetchTags } = tagsStore;
const { deleteThirdParty, fetchThirdPartyProviders } =
settingsStore.thirdPartyStore;
const { enableThirdParty } = settingsStore;
filesSettingsStore.thirdPartyStore;
const { enableThirdParty } = filesSettingsStore;
const {
createRoomConfirmDialogVisible,

View File

@ -44,9 +44,8 @@ const EditRoomEvent = ({
updateLogoPathsCacheBreaker,
removeLogoPaths,
reloadInfoPanelSelection,
updateInfoPanelSelection,
changeRoomOwner,
reloadSelectionParentRoom,
}) => {
const { t } = useTranslation(["CreateEditRoomDialog", "Common", "Files"]);
@ -108,6 +107,8 @@ const EditRoomEvent = ({
const uploadLogoData = new FormData();
uploadLogoData.append(0, roomParams.icon.uploadedFile);
let room = null;
try {
setIsLoading(true);
@ -115,7 +116,7 @@ const EditRoomEvent = ({
await changeRoomOwner(t, roomParams?.roomOwner?.id);
}
let room = await editRoom(item.id, editRoomParams);
room = await editRoom(item.id, editRoomParams);
room.isLogoLoading = true;
@ -123,8 +124,8 @@ const EditRoomEvent = ({
await createTag(newTags[i]);
}
room = await addTagsToRoom(room.id, tags);
room = await removeTagsFromRoom(room.id, removedTags);
tags.length && (room = await addTagsToRoom(room.id, tags));
removedTags.length && (room = await removeTagsFromRoom(room.id, removedTags));
if (!!item.logo.original && !roomParams.icon.uploadedFile) {
room = await removeLogoFromRoom(room.id);
@ -154,15 +155,14 @@ const EditRoomEvent = ({
}
!withPaging && updateRoom(item, room);
reloadSelectionParentRoom();
reloadInfoPanelSelection();
// updateInfoPanelSelection();
URL.revokeObjectURL(img.src);
setActiveFolders([]);
};
img.src = url;
} else {
!withPaging && updateRoom(item, room);
reloadInfoPanelSelection();
// updateInfoPanelSelection();
}
} catch (err) {
console.log(err);
@ -173,14 +173,14 @@ const EditRoomEvent = ({
updateEditedSelectedRoom(editRoomParams.title, tags);
if (item.logo.original && !roomParams.icon.uploadedFile) {
removeLogoPaths();
reloadInfoPanelSelection();
// updateInfoPanelSelection();
} else if (!item.logo.original && roomParams.icon.uploadedFile)
addDefaultLogoPaths();
else if (item.logo.original && roomParams.icon.uploadedFile)
updateLogoPathsCacheBreaker();
}
reloadSelectionParentRoom();
updateInfoPanelSelection(room);
setIsLoading(false);
onClose();
}
@ -237,13 +237,14 @@ const EditRoomEvent = ({
export default inject(
({
auth,
settingsStore,
filesStore,
tagsStore,
filesActionsStore,
selectedFolderStore,
dialogsStore,
settingsStore,
filesSettingsStore,
infoPanelStore,
}) => {
const {
editRoom,
@ -269,13 +270,10 @@ export default inject(
updateLogoPathsCacheBreaker,
} = selectedFolderStore;
const { updateCurrentFolder, changeRoomOwner } = filesActionsStore;
const { getThirdPartyIcon } = settingsStore.thirdPartyStore;
const { getThirdPartyIcon } = filesSettingsStore.thirdPartyStore;
const { setCreateRoomDialogVisible } = dialogsStore;
const { withPaging } = auth.settingsStore;
const {
reloadSelection: reloadInfoPanelSelection,
reloadSelectionParentRoom,
} = auth.infoPanelStore;
const { withPaging } = settingsStore;
const { updateInfoPanelSelection } = infoPanelStore;
return {
addActiveItems,
setActiveFolders,
@ -308,9 +306,8 @@ export default inject(
updateLogoPathsCacheBreaker,
removeLogoPaths,
reloadInfoPanelSelection,
updateInfoPanelSelection,
changeRoomOwner,
reloadSelectionParentRoom,
};
}
)(observer(EditRoomEvent));

View File

@ -238,8 +238,8 @@ const GlobalEvents = ({ enablePlugins, eventListenerItemsList }) => {
];
};
export default inject(({ auth, pluginStore }) => {
const { enablePlugins } = auth.settingsStore;
export default inject(({ settingsStore, pluginStore }) => {
const { enablePlugins } = settingsStore;
const { eventListenerItemsList } = pluginStore;

View File

@ -186,9 +186,9 @@ const Dialog = ({
);
};
export default inject(({ auth, settingsStore }) => {
const { folderFormValidation } = auth.settingsStore;
const { keepNewFileName, setKeepNewFileName } = settingsStore;
export default inject(({ settingsStore, filesSettingsStore }) => {
const { folderFormValidation } = settingsStore;
const { keepNewFileName, setKeepNewFileName } = filesSettingsStore;
return { folderFormValidation, keepNewFileName, setKeepNewFileName };
})(observer(Dialog));

View File

@ -227,9 +227,9 @@ Layout.propTypes = {
setIsTabletView: PropTypes.func,
};
export default inject(({ auth, bannerStore }) => {
export default inject(({ settingsStore }) => {
const { isTabletView, setIsTabletView, setWindowWidth, isFrame } =
auth.settingsStore;
settingsStore;
return {
isTabletView,
setIsTabletView,

View File

@ -44,7 +44,7 @@ const Main = (props) => {
window.visualViewport.removeEventListener("resize", onResize);
clearTimeout(updateSizeRef.current);
};
}, [onResize]);
}, [onResize, isFrame]);
React.useEffect(() => {
onResize();
@ -100,10 +100,10 @@ const Main = (props) => {
Main.displayName = "Main";
export default inject(({ auth }) => {
const { isBannerVisible } = auth.bannerStore;
export default inject(({ settingsStore, bannerStore }) => {
const { isBannerVisible } = bannerStore;
const { mainBarVisible, isFrame } = auth.settingsStore;
const { mainBarVisible, isFrame } = settingsStore;
return {
mainBarVisible,
isBannerVisible,

View File

@ -294,50 +294,52 @@ const Bar = (props) => {
) : null;
};
export default inject(({ auth, profileActionsStore }) => {
const { user, withActivationBar, sendActivationLink } = auth.userStore;
export default inject(
({ settingsStore, profileActionsStore, userStore, currentQuotaStore }) => {
const { user, withActivationBar, sendActivationLink } = userStore;
const { onPaymentsClick } = profileActionsStore;
const { onPaymentsClick } = profileActionsStore;
const {
maxCountRoomsByQuota,
usedRoomsCount,
const {
maxCountRoomsByQuota,
usedRoomsCount,
maxTotalSizeByQuota,
usedTotalStorageSizeCount,
maxTotalSizeByQuota,
usedTotalStorageSizeCount,
maxCountManagersByQuota,
addedManagersCount,
maxCountManagersByQuota,
addedManagersCount,
showRoomQuotaBar,
showStorageQuotaBar,
showUserQuotaBar,
} = auth.currentQuotaStore;
showRoomQuotaBar,
showStorageQuotaBar,
showUserQuotaBar,
} = currentQuotaStore;
const { currentColorScheme, setMainBarVisible } = auth.settingsStore;
const { currentColorScheme, setMainBarVisible } = settingsStore;
return {
isAdmin: user?.isAdmin,
userEmail: user?.email,
withActivationBar,
sendActivationLink,
return {
isAdmin: user?.isAdmin,
userEmail: user?.email,
withActivationBar,
sendActivationLink,
onPaymentsClick,
onPaymentsClick,
maxCountRoomsByQuota,
usedRoomsCount,
maxCountRoomsByQuota,
usedRoomsCount,
maxTotalSizeByQuota,
usedTotalStorageSizeCount,
maxTotalSizeByQuota,
usedTotalStorageSizeCount,
maxCountManagersByQuota,
addedManagersCount,
maxCountManagersByQuota,
addedManagersCount,
showRoomQuotaBar,
showStorageQuotaBar,
showUserQuotaBar,
showRoomQuotaBar,
showStorageQuotaBar,
showUserQuotaBar,
currentColorScheme,
setMainBarVisible,
};
})(withTranslation(["Profile", "Common"])(observer(Bar)));
currentColorScheme,
setMainBarVisible,
};
}
)(withTranslation(["Profile", "Common"])(observer(Bar)));

View File

@ -57,20 +57,26 @@ const MainBar = ({
);
};
export default inject(({ auth, clientLoadingStore, filesStore }) => {
const { currentTariffStatusStore, settingsStore } = auth;
const { checkedMaintenance, setMaintenanceExist, snackbarExist, isFrame } =
settingsStore;
const { isNotPaidPeriod } = currentTariffStatusStore;
const { firstLoad } = clientLoadingStore;
const { isInit } = filesStore;
export default inject(
({
settingsStore,
clientLoadingStore,
filesStore,
currentTariffStatusStore,
}) => {
const { checkedMaintenance, setMaintenanceExist, snackbarExist, isFrame } =
settingsStore;
const { isNotPaidPeriod } = currentTariffStatusStore;
const { firstLoad } = clientLoadingStore;
const { isInit } = filesStore;
return {
firstLoad: firstLoad && isInit,
checkedMaintenance,
snackbarExist,
setMaintenanceExist,
isNotPaidPeriod,
isFrame,
};
})(observer(MainBar));
return {
firstLoad: firstLoad && isInit,
checkedMaintenance,
snackbarExist,
setMaintenanceExist,
isNotPaidPeriod,
isFrame,
};
}
)(observer(MainBar));

View File

@ -208,8 +208,8 @@ NavMenu.defaultProps = {
isDesktop: false,
};
const NavMenuWrapper = inject(({ auth }) => {
const { settingsStore, isAuthenticated, isLoaded, language } = auth;
const NavMenuWrapper = inject(({ authStore, settingsStore }) => {
const { isAuthenticated, isLoaded, language } = authStore;
const {
isDesktopClient: isDesktop,
frameConfig,

View File

@ -75,8 +75,8 @@ HeaderNav.propTypes = {
isAuthenticated: PropTypes.bool,
};
export default inject(({ auth, profileActionsStore }) => {
const { userStore, isAuthenticated } = auth;
export default inject(({ authStore, profileActionsStore, userStore }) => {
const { isAuthenticated } = authStore;
const { user, userIsUpdate, setUserIsUpdate } = userStore;
const { getActions } = profileActionsStore;

View File

@ -91,8 +91,8 @@ HeaderUnAuth.propTypes = {
isLoaded: PropTypes.bool,
};
export default inject(({ auth }) => {
const { settingsStore, isAuthenticated, isLoaded } = auth;
export default inject(({ authStore, settingsStore }) => {
const { isAuthenticated, isLoaded } = authStore;
const { enableAdmMess, wizardToken, logoUrl, theme } = settingsStore;
return {

View File

@ -335,17 +335,14 @@ HeaderComponent.propTypes = {
needNavMenu: PropTypes.bool,
};
export default inject(({ auth }) => {
export default inject(({ settingsStore, authStore }) => {
const {
settingsStore,
userStore,
isLoaded,
isAuthenticated,
isAdmin,
version,
} = auth;
} = authStore;
const {
logoUrl,
defaultPage,
@ -355,9 +352,6 @@ export default inject(({ auth }) => {
toggleArticleOpen,
} = settingsStore;
//TODO: restore when chat will complete -> const mainModules = availableModules.filter((m) => !m.isolateMode);
const { user } = userStore;
return {
theme,
isPersonal,

View File

@ -42,6 +42,6 @@ NavLogoItem.propTypes = {
logoUrl: PropTypes.string,
};
export default inject(({ auth }) => ({
logoUrl: auth.settingsStore.logoUrl,
export default inject(({ settingsStore }) => ({
logoUrl: settingsStore.logoUrl,
}))(observer(NavLogoItem));

View File

@ -237,8 +237,8 @@ ProfileMenu.propTypes = {
clickOutsideAction: PropTypes.func,
};
export default inject(({ auth }) => {
const { isBannerVisible } = auth.bannerStore;
export default inject(({ bannerStore }) => {
const { isBannerVisible } = bannerStore;
return { isBannerVisible };
})(observer(withTheme(ProfileMenu)));

View File

@ -3,7 +3,6 @@ import CatalogFolderReactSvgUrl from "PUBLIC_DIR/images/catalog.folder.react.svg
import React from "react";
import { withTranslation } from "react-i18next";
import Filter from "@docspace/shared/api/people/filter";
import Loaders from "@docspace/common/components/Loaders";
import { inject, observer } from "mobx-react";
import { getSelectedGroup } from "../../../helpers/people-helpers";
import { useNavigate } from "react-router-dom";
@ -13,6 +12,7 @@ import config from "PACKAGE_FILE";
import { combineUrl } from "@docspace/shared/utils/combineUrl";
import { ArticleItem } from "@docspace/shared/components/article-item";
import withLoader from "../../../HOCs/withLoader";
import { ArticleFolderLoader } from "@docspace/shared/skeletons/article";
const departmentsIcon = DepartmentsGroupReactSvgUrl;
const groupIcon = CatalogFolderReactSvgUrl;
@ -128,32 +128,34 @@ const ArticleBodyContent = ({
};
const BodyContent = withTranslation(["Article"])(
withLoader(ArticleBodyContent)(<Loaders.ArticleFolder />)
withLoader(ArticleBodyContent)(<ArticleFolderLoader />)
);
export default inject(({ auth, peopleStore }) => {
const { settingsStore, setDocumentTitle, isAdmin } = auth;
const { customNames, showText, toggleArticleOpen } = settingsStore;
const { groupsStore, selectedGroupStore, filterStore } = peopleStore;
const { filter } = filterStore;
const { groups } = groupsStore;
const { groupsCaption } = customNames;
const { selectedGroup, selectGroup } = selectedGroupStore;
const selectedKey = selectedGroup ? selectedGroup : "root";
export default inject(
({ authStore, settingsStore, peopleStore, userStore }) => {
const { setDocumentTitle, isAdmin } = authStore;
const { customNames, showText, toggleArticleOpen } = settingsStore;
const { groupsStore, selectedGroupStore, filterStore } = peopleStore;
const { filter } = filterStore;
const { groups } = groupsStore;
const { groupsCaption } = customNames;
const { selectedGroup, selectGroup } = selectedGroupStore;
const selectedKey = selectedGroup ? selectedGroup : "root";
return {
setDocumentTitle,
return {
setDocumentTitle,
isVisitor: auth.userStore.user.isVisitor,
isAdmin,
groups,
groupsCaption,
selectedKey,
selectGroup,
isVisitor: userStore.user.isVisitor,
isAdmin,
groups,
groupsCaption,
selectedKey,
selectGroup,
filter,
filter,
showText,
toggleArticleOpen,
};
})(observer(BodyContent));
showText,
toggleArticleOpen,
};
}
)(observer(BodyContent));

View File

@ -23,6 +23,7 @@ import {
import MobileView from "./MobileView";
import withLoader from "../../../HOCs/withLoader";
import { ArticleButtonLoader } from "@docspace/shared/skeletons/article";
const ArticleMainButtonContent = (props) => {
const [dialogVisible, setDialogVisible] = React.useState(false);
@ -112,22 +113,21 @@ const ArticleMainButtonContent = (props) => {
);
};
export default inject(({ auth }) => {
const { userCaption, guestCaption, groupCaption } =
auth.settingsStore.customNames;
export default inject(({ authStore, settingsStore }) => {
const { userCaption, guestCaption, groupCaption } = settingsStore.customNames;
return {
isAdmin: auth.isAdmin,
isAdmin: authStore.isAdmin,
homepage: config.homepage,
userCaption,
guestCaption,
groupCaption,
toggleShowText: auth.settingsStore.toggleShowText,
isMobileArticle: auth.settingsStore.isMobileArticle,
showText: auth.settingsStore.showText,
toggleShowText: settingsStore.toggleShowText,
isMobileArticle: settingsStore.isMobileArticle,
showText: settingsStore.showText,
};
})(
withTranslation(["Article", "Common", "PeopleTranslations"])(
withLoader(observer(ArticleMainButtonContent))(<Loaders.ArticleButton />)
withLoader(observer(ArticleMainButtonContent))(<ArticleButtonLoader />)
)
);

View File

@ -1,40 +0,0 @@
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import Backend from "@docspace/shared/utils/i18next-http-backend";
import { LANGUAGE } from "@docspace/shared/constants";
import config from "PACKAGE_FILE";
import { getCookie } from "@docspace/shared/utils";
import { loadLanguagePath } from "SRC_DIR/helpers/utils";
const newInstance = i18n.createInstance();
newInstance
.use(Backend)
.use(initReactI18next)
.init({
lng: getCookie(LANGUAGE) || "en",
fallbackLng: "en",
load: "currentOnly",
//debug: true,
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
format: function (value, format) {
if (format === "lowercase") return value.toLowerCase();
return value;
},
},
backend: {
loadPath: loadLanguagePath(config.homepage),
},
ns: ["PeopleSelector", "Common", "PeopleTranslations"],
defaultNS: "PeopleSelector",
react: {
useSuspense: false,
},
});
export default newInstance;

View File

@ -1,286 +0,0 @@
import i18n from "./i18n";
import PropTypes from "prop-types";
import { inject, observer } from "mobx-react";
import React, { useState, useEffect } from "react";
import { I18nextProvider, withTranslation } from "react-i18next";
import { Selector } from "@docspace/shared/components/selector";
import { getUserRole } from "@docspace/shared/utils/common";
import Filter from "@docspace/shared/api/people/filter";
import { getUserList } from "@docspace/shared/api/people";
import Loaders from "@docspace/common/components/Loaders";
import { EmployeeStatus } from "@docspace/shared/enums";
import { LOADER_TIMEOUT } from "@docspace/shared/constants";
import useLoadingWithTimeout from "SRC_DIR/Hooks/useLoadingWithTimeout";
import DefaultUserPhoto from "PUBLIC_DIR/images/default_user_photo_size_82-82.png";
import EmptyScreenPersonsSvgUrl from "PUBLIC_DIR/images/empty_screen_persons.svg?url";
import CatalogAccountsReactSvgUrl from "PUBLIC_DIR/images/catalog.accounts.react.svg?url";
import EmptyScreenPersonsSvgDarkUrl from "PUBLIC_DIR/images/empty_screen_persons_dark.svg?url";
const PeopleSelector = ({
acceptButtonLabel,
accessRights,
cancelButtonLabel,
className,
emptyScreenDescription,
emptyScreenHeader,
headerLabel,
id,
isMultiSelect,
items,
onAccept,
onAccessRightsChange,
onBackClick,
onCancel,
onSelect,
onSelectAll,
searchEmptyScreenDescription,
searchEmptyScreenHeader,
searchPlaceholder,
selectAllIcon,
selectAllLabel,
selectedAccessRight,
selectedItems,
style,
t,
withAccessRights,
withCancelButton,
withSelectAll,
filter,
excludeItems,
currentUserId,
theme,
withOutCurrentAuthorizedUser,
withAbilityCreateRoomUsers,
withFooterCheckbox,
footerCheckboxLabel,
isChecked,
setIsChecked,
filterUserId,
}) => {
const [itemsList, setItemsList] = useState(items);
const [searchValue, setSearchValue] = useState("");
const [total, setTotal] = useState(0);
const [hasNextPage, setHasNextPage] = useState(true);
const [isNextPageLoading, setIsNextPageLoading] = useState(false);
const [isLoading, setIsLoading] = useLoadingWithTimeout(
LOADER_TIMEOUT,
false
);
useEffect(() => {
loadNextPage(0);
}, []);
const toListItem = (item) => {
const {
id,
email,
avatar,
icon,
displayName,
hasAvatar,
isOwner,
isAdmin,
isVisitor,
isCollaborator,
} = item;
const role = getUserRole(item);
const userAvatar = hasAvatar ? avatar : DefaultUserPhoto;
return {
id,
email,
avatar: userAvatar,
icon,
label: displayName || email,
role,
isOwner,
isAdmin,
isVisitor,
isCollaborator,
hasAvatar,
};
};
const moveCurrentUserToTopOfList = (listUser) => {
const currentUserIndex = listUser.findIndex(
(user) => user.id === currentUserId
);
// return if the current user is already at the top of the list or not found
if (currentUserIndex < 1) return listUser;
const [currentUser] = listUser.splice(currentUserIndex, 1);
listUser.splice(0, 0, currentUser);
return listUser;
};
const removeCurrentUserFromList = (listUser) => {
if (filterUserId) {
return listUser.filter((user) => user.id !== filterUserId);
}
return listUser.filter((user) => user.id !== currentUserId);
};
const loadNextPage = (startIndex, search = searchValue) => {
const pageCount = 100;
setIsNextPageLoading(true);
if (startIndex === 0) {
setIsLoading(true);
}
const currentFilter =
typeof filter === "function" ? filter() : filter ?? Filter.getDefault();
currentFilter.page = startIndex / pageCount;
currentFilter.pageCount = pageCount;
if (!!search.length) {
currentFilter.search = search;
}
getUserList(currentFilter)
.then((response) => {
let newItems = startIndex ? itemsList : [];
let totalDifferent = startIndex ? response.total - total : 0;
const items = response.items
.filter((item) => {
const excludeUser =
withAbilityCreateRoomUsers &&
((!item.isAdmin && !item.isOwner && !item.isRoomAdmin) ||
item.status === EmployeeStatus.Disabled);
if (excludeItems.includes(item.id) || excludeUser) {
totalDifferent++;
return false;
} else {
return true;
}
})
.map((item) => toListItem(item));
const tempItems = [...newItems, ...items];
newItems = withOutCurrentAuthorizedUser
? removeCurrentUserFromList(tempItems)
: moveCurrentUserToTopOfList(tempItems);
const newTotal = withOutCurrentAuthorizedUser
? response.total - totalDifferent - 1
: response.total - totalDifferent;
setHasNextPage(newItems.length < newTotal);
setItemsList(newItems);
setTotal(newTotal);
setIsNextPageLoading(false);
setIsLoading(false);
})
.catch((error) => console.log(error));
};
const onSearch = (value) => {
setSearchValue(value);
loadNextPage(0, value);
};
const onClearSearch = () => {
setSearchValue("");
loadNextPage(0, "");
};
const emptyScreenImage = theme.isBase
? EmptyScreenPersonsSvgUrl
: EmptyScreenPersonsSvgDarkUrl;
return (
<Selector
id={id}
className={className}
style={style}
headerLabel={headerLabel || t("ListAccounts")}
onBackClick={onBackClick}
searchPlaceholder={searchPlaceholder || t("Common:Search")}
searchValue={searchValue}
onSearch={onSearch}
onClearSearch={onClearSearch}
items={itemsList}
isMultiSelect={isMultiSelect}
selectedItems={selectedItems}
acceptButtonLabel={acceptButtonLabel || t("Common:SelectAction")}
onAccept={onAccept}
withSelectAll={withSelectAll}
selectAllLabel={selectAllLabel || t("AllAccounts")}
selectAllIcon={selectAllIcon}
withAccessRights={withAccessRights}
accessRights={accessRights}
selectedAccessRight={selectedAccessRight}
withCancelButton={withCancelButton}
cancelButtonLabel={cancelButtonLabel || t("Common:CancelButton")}
onCancel={onCancel}
emptyScreenImage={emptyScreenImage}
emptyScreenHeader={emptyScreenHeader || t("EmptyHeader")}
emptyScreenDescription={emptyScreenDescription || t("EmptyDescription")}
searchEmptyScreenImage={emptyScreenImage}
searchEmptyScreenHeader={
searchEmptyScreenHeader || t("People:NotFoundUsers")
}
searchEmptyScreenDescription={
searchEmptyScreenDescription || t("People:NotFoundUsersDescription")
}
hasNextPage={hasNextPage}
isNextPageLoading={isNextPageLoading}
loadNextPage={loadNextPage}
totalItems={total}
isLoading={isLoading}
withFooterCheckbox={withFooterCheckbox}
footerCheckboxLabel={footerCheckboxLabel}
isChecked={isChecked}
setIsChecked={setIsChecked}
searchLoader={<Loaders.SelectorSearchLoader />}
isSearchLoading={isLoading}
rowLoader={<Loaders.SelectorRowLoader isUser isContainer={isLoading} />}
/>
);
};
PeopleSelector.propTypes = { excludeItems: PropTypes.array };
PeopleSelector.defaultProps = {
excludeItems: [],
selectAllIcon: CatalogAccountsReactSvgUrl,
};
const ExtendedPeopleSelector = inject(({ auth }) => {
return {
theme: auth.settingsStore.theme,
currentUserId: auth.userStore.user.id,
};
})(
observer(
withTranslation([
"PeopleSelector",
"PeopleTranslations",
"People",
"Common",
])(PeopleSelector)
)
);
export default (props) => (
<I18nextProvider i18n={i18n}>
<ExtendedPeopleSelector {...props} />
</I18nextProvider>
);

View File

@ -1,62 +0,0 @@
import React from "react";
import PropTypes from "prop-types";
import { Avatar } from "@docspace/shared/components/avatar";
import { Text } from "@docspace/shared/components/text";
import StyledUserTooltip from "./StyledUserTooltip";
const UserTooltip = ({ avatarUrl, label, email, position, theme }) => (
<StyledUserTooltip theme={theme}>
<div className="block-avatar">
<Avatar
theme={theme}
className="user-avatar"
size="min"
role="user"
source={avatarUrl}
userName=""
editing={false}
/>
</div>
<div className="block-info">
<Text
theme={theme}
isBold={true}
fontSize="13px"
fontWeight={600}
truncate={true}
title={label}
>
{label}
</Text>
<Text
theme={theme}
color={theme.peopleSelector.textColor}
fontSize="13px"
className="email-text"
truncate={true}
title={email}
>
{email}
</Text>
<Text
theme={theme}
fontSize="13px"
fontWeight={600}
truncate={true}
title={position}
>
{position}
</Text>
</div>
</StyledUserTooltip>
);
UserTooltip.propTypes = {
avatarUrl: PropTypes.string,
label: PropTypes.string,
email: PropTypes.string,
position: PropTypes.string,
};
export default UserTooltip;

View File

@ -4,10 +4,11 @@ import LinkReactSvgUrl from "PUBLIC_DIR/images/link.react.svg?url";
import LockedReactSvgUrl from "PUBLIC_DIR/images/locked.react.svg?url";
import FileActionsFavoriteReactSvgUrl from "PUBLIC_DIR/images/file.actions.favorite.react.svg?url";
import FavoriteReactSvgUrl from "PUBLIC_DIR/images/favorite.react.svg?url";
import React from "react";
import styled from "styled-components";
import { isTablet, commonIconsStyles } from "@docspace/shared/utils";
import { isTablet, isMobile, commonIconsStyles } from "@docspace/shared/utils";
import {
FileStatus,
RoomsType,
@ -30,10 +31,12 @@ const QuickButtons = (props) => {
viewAs,
folderCategory,
isPublicRoom,
onClickShare,
isPersonalRoom,
isArchiveFolder,
} = props;
const { id, locked, fileStatus, title, fileExst } = item;
const { id, locked, shared, fileStatus, title, fileExst } = item;
const isFavorite =
(fileStatus & FileStatus.IsFavorite) === FileStatus.IsFavorite;
@ -54,6 +57,10 @@ const QuickButtons = (props) => {
? theme.filesQuickButtons.sharedColor
: theme.filesQuickButtons.color;
const colorShare = shared
? theme.filesQuickButtons.sharedColor
: theme.filesQuickButtons.color;
const tabletViewQuickButton = isTablet();
const sizeQuickButton = isTile || tabletViewQuickButton ? "medium" : "small";
@ -67,6 +74,8 @@ const QuickButtons = (props) => {
const isAvailableDownloadFile =
isPublicRoom && item.security.Download && viewAs === "tile";
const isAvailableShareFile = isPersonalRoom && item.canShare;
const isPublicRoomType =
item.roomType === RoomsType.PublicRoom ||
item.roomType === RoomsType.CustomRoom;
@ -82,6 +91,11 @@ const QuickButtons = (props) => {
!isArchiveFolder &&
!isTile;
const onShare = () => {
if (isMobile()) return;
onClickShare();
};
return (
<div className="badges additional-badges badges__quickButtons">
{isAvailableLockFile && (
@ -125,6 +139,19 @@ const QuickButtons = (props) => {
title={t("Files:CopyGeneralLink")}
/>
)}
{isAvailableShareFile && (
<ColorTheme
themeId={ThemeId.IconButton}
iconName={LinkReactSvgUrl}
className="badge copy-link icons-group"
size={sizeQuickButton}
onClick={onShare}
color={colorShare}
isDisabled={isDisabled}
hoverColor={theme.filesQuickButtons.sharedColor}
title={t("Files:CopyGeneralLink")}
/>
)}
{/* {fileExst && !isTrashFolder && displayBadges && (
<ColorTheme
themeId={ThemeId.IconButton}

View File

@ -0,0 +1,61 @@
import { inject, observer } from "mobx-react";
import Section, { SectionProps } from "@docspace/shared/components/section";
const SectionWrapper = ({
children,
...rest
}: SectionProps) => {
return <Section {...rest}>{children}</Section>;
};
export default inject(
({
settingsStore,
dialogsStore,
infoPanelStore,
}: {
settingsStore: any;
dialogsStore: any;
infoPanelStore: any;
}) => {
const {
isDesktopClient: isDesktop,
currentDeviceType,
isHeaderVisible,
isTabletView,
maintenanceExist,
snackbarExist,
showText,
} = settingsStore;
const { isVisible, isMobileHidden, setIsVisible, getCanDisplay } =
infoPanelStore;
const { createRoomDialogVisible, invitePanelOptions } = dialogsStore;
const canDisplay = getCanDisplay();
const anotherDialogOpen =
createRoomDialogVisible || invitePanelOptions.visible;
const { isScrollLocked: isInfoPanelScrollLocked } = infoPanelStore;
return {
isDesktop,
currentDeviceType,
isInfoPanelVisible: isVisible,
isMobileHidden,
setIsInfoPanelVisible: setIsVisible,
canDisplay,
anotherDialogOpen,
isHeaderVisible,
isTabletView,
maintenanceExist,
snackbarExist,
showText,
isInfoPanelScrollLocked,
};
}
)(observer(SectionWrapper));

View File

@ -52,9 +52,9 @@ const SharedButton = ({
);
};
export default inject(({ auth, filesActionsStore, dialogsStore }) => {
export default inject(({ settingsStore, filesActionsStore, dialogsStore }) => {
return {
theme: auth.settingsStore.theme,
theme: settingsStore.theme,
onSelectItem: filesActionsStore.onSelectItem,
setSharingPanelVisible: dialogsStore.setSharingPanelVisible,
};

View File

@ -83,9 +83,9 @@ const ReactSmartBanner = (props) => {
);
};
export default inject(({ auth }) => {
export default inject(({ bannerStore }) => {
return {
isBannerVisible: auth.bannerStore.isBannerVisible,
setIsBannerVisible: auth.bannerStore.setIsBannerVisible,
isBannerVisible: bannerStore.isBannerVisible,
setIsBannerVisible: bannerStore.setIsBannerVisible,
};
})(observer(ReactSmartBanner));

View File

@ -82,20 +82,17 @@ const BenefitsContainer = ({ isTrial, isEnterprise }) => {
);
};
export default inject(({ auth }) => {
const {
paymentQuotasStore,
export default inject(
({ authStore, currentQuotaStore, paymentQuotasStore }) => {
const { isEnterprise } = authStore;
currentQuotaStore,
isEnterprise,
} = auth;
const { portalPaymentQuotasFeatures } = paymentQuotasStore;
const { portalPaymentQuotasFeatures } = paymentQuotasStore;
const { isTrial } = currentQuotaStore;
return {
features: portalPaymentQuotasFeatures,
isTrial,
isEnterprise,
};
})(observer(BenefitsContainer));
const { isTrial } = currentQuotaStore;
return {
features: portalPaymentQuotasFeatures,
isTrial,
isEnterprise,
};
}
)(observer(BenefitsContainer));

View File

@ -123,9 +123,9 @@ const ContactContainer = (props) => {
);
};
export default inject(({ auth, payments }) => {
const { settingsStore, isCommunity } = auth;
const { helpUrl, salesEmail } = payments;
export default inject(({ authStore, settingsStore, paymentStore }) => {
const { isCommunity } = authStore;
const { helpUrl, salesEmail } = paymentStore;
const { theme } = settingsStore;
return { helpUrl, salesEmail, theme, isCommunity };
})(observer(ContactContainer));

View File

@ -6,6 +6,7 @@ import { Button } from "@docspace/shared/components/button";
import { Text } from "@docspace/shared/components/text";
import { Link } from "@docspace/shared/components/link";
import { toastr } from "@docspace/shared/components/toast";
import { getTfaNewBackupCodes } from "@docspace/shared/api/settings";
import { withTranslation } from "react-i18next";
import ModalDialogContainer from "../ModalDialogContainer";
@ -35,9 +36,9 @@ class BackupCodesDialogComponent extends React.Component {
}
getNewBackupCodes = async () => {
const { getNewBackupCodes, setBackupCodes } = this.props;
const { setBackupCodes } = this.props;
try {
const newCodes = await getNewBackupCodes();
const newCodes = await getTfaNewBackupCodes();
setBackupCodes(newCodes);
} catch (e) {
toastr.error(e);
@ -146,7 +147,6 @@ const BackupCodesDialog = withTranslation(
BackupCodesDialog.propTypes = {
visible: PropTypes.bool.isRequired,
onClose: PropTypes.func.isRequired,
getNewBackupCodes: PropTypes.func.isRequired,
backupCodes: PropTypes.array.isRequired,
backupCodesCount: PropTypes.number.isRequired,
setBackupCodes: PropTypes.func.isRequired,

View File

@ -220,15 +220,15 @@ ChangeEmailDialog.propTypes = {
user: PropTypes.object.isRequired,
};
export default inject(({ auth, peopleStore }) => {
export default inject(({ settingsStore, peopleStore, userStore }) => {
const { updateProfile } = peopleStore.targetUserStore;
const { updateProfileInUsers } = peopleStore.usersStore;
const { user: profile } = auth.userStore;
const { user: profile } = userStore;
return {
updateProfile,
updateProfileInUsers,
isTabletView: auth.settingsStore.isTabletView,
isTabletView: settingsStore.isTabletView,
profile,
};
})(observer(ChangeEmailDialog));

View File

@ -173,12 +173,12 @@ const ChangeNameDialog = (props) => {
);
};
export default inject(({ peopleStore, auth }) => {
export default inject(({ peopleStore, settingsStore }) => {
const { updateProfile } = peopleStore.targetUserStore;
const { updateProfileInUsers } = peopleStore.usersStore;
const { userNameRegex } = auth.settingsStore;
const { userNameRegex } = settingsStore;
return { updateProfile, updateProfileInUsers, userNameRegex };
})(observer(ChangeNameDialog));

View File

@ -83,7 +83,7 @@ class ChangePasswordDialogComponent extends React.Component {
type="page"
href={`mailto:${email}`}
noHover
color={currentColorScheme.main.accent}
color={currentColorScheme.main?.accent}
title={email}
>
{{ email }}
@ -118,8 +118,8 @@ class ChangePasswordDialogComponent extends React.Component {
}
}
const ChangePasswordDialog = inject(({ auth }) => ({
currentColorScheme: auth.settingsStore.currentColorScheme,
const ChangePasswordDialog = inject(({ settingsStore }) => ({
currentColorScheme: settingsStore.currentColorScheme,
}))(
observer(
withTranslation(["ChangePasswordDialog", "Common"])(

View File

@ -160,12 +160,12 @@ const StyledSelectedOwner = styled.div`
box-sizing: border-box;
background: ${({ currentColorScheme }) => currentColorScheme.main.accent};
background: ${({ currentColorScheme }) => currentColorScheme.main?.accent};
border-radius: 16px;
.text {
color: ${({ currentColorScheme }) => currentColorScheme.text.accent};
color: ${({ currentColorScheme }) => currentColorScheme.text?.accent};
font-weight: 600;
font-size: ${(props) => props.theme.getCorrectFontSize("13px")};
@ -180,7 +180,7 @@ const StyledSelectedOwner = styled.div`
cursor: pointer;
path {
fill: ${({ currentColorScheme }) => currentColorScheme.text.accent};
fill: ${({ currentColorScheme }) => currentColorScheme.text?.accent};
}
}
}

View File

@ -4,7 +4,7 @@ import { inject, observer } from "mobx-react";
import { ReactSVG } from "react-svg";
import { withTranslation } from "react-i18next";
import PeopleSelector from "SRC_DIR/components/PeopleSelector";
import PeopleSelector from "@docspace/shared/selectors/People";
import Filter from "@docspace/shared/api/people/filter";
@ -118,6 +118,7 @@ const ChangePortalOwnerDialog = ({
onAccept={onAccept}
onCancel={onBackClick}
onBackClick={onBackClick}
currentUserId={id}
/>
</ModalDialog.Container>
)}
@ -228,9 +229,9 @@ const ChangePortalOwnerDialog = ({
);
};
export default inject(({ auth, setup }) => {
const { displayName, avatar, id } = auth.userStore.user;
const { currentColorScheme } = auth.settingsStore;
export default inject(({ setup, userStore, settingsStore }) => {
const { displayName, avatar, id } = userStore.user;
const { currentColorScheme } = settingsStore;
const { sendOwnerChange } = setup;
return { displayName, avatar, id, sendOwnerChange, currentColorScheme };

View File

@ -106,9 +106,9 @@ ChangePricingPlanDialog.propTypes = {
onClose: PropTypes.func.isRequired,
};
export default inject(({ auth, payments }) => {
const { managersCount, allowedStorageSizeByQuota } = payments;
const { currentQuotaStore } = auth;
export default inject(({ paymentStore, currentQuotaStore }) => {
const { managersCount, allowedStorageSizeByQuota } = paymentStore;
const { addedManagersCount, usedTotalStorageSizeCount } = currentQuotaStore;
return {
managersCount,

View File

@ -40,7 +40,7 @@ class ChangeUserStatusDialogComponent extends React.Component {
onClose,
userIDs,
getPeopleListItem,
setSelection,
setInfoPanelSelection,
infoPanelVisible,
needResetUserSelection,
} = this.props;
@ -51,7 +51,7 @@ class ChangeUserStatusDialogComponent extends React.Component {
if (users.length === 1 && infoPanelVisible) {
const user = getPeopleListItem(users[0]);
setSelection(user);
setInfoPanelSelection(user);
}
toastr.success(t("PeopleTranslations:SuccessChangeUserStatus"));
@ -170,13 +170,13 @@ ChangeUserStatusDialog.propTypes = {
userIDs: PropTypes.arrayOf(PropTypes.string).isRequired,
};
export default inject(({ peopleStore, auth }) => {
export default inject(({ peopleStore, infoPanelStore }) => {
const setSelected = peopleStore.selectionStore.setSelected;
const { getPeopleListItem, updateUserStatus, needResetUserSelection } =
peopleStore.usersStore;
const { setSelection, isVisible: infoPanelVisible } = auth.infoPanelStore;
const { setInfoPanelSelection, isVisible: infoPanelVisible } = infoPanelStore;
return {
needResetUserSelection,
@ -186,7 +186,7 @@ export default inject(({ peopleStore, auth }) => {
getPeopleListItem,
setSelection,
setInfoPanelSelection,
infoPanelVisible,
};
})(observer(ChangeUserStatusDialog));

View File

@ -0,0 +1,62 @@
import { TFile, TFolder } from "@docspace/shared/api/files/types";
import { ConflictResolveType } from "@docspace/shared/enums";
import { TTranslation } from "@docspace/shared/types";
export type TConflictResolveDialogData = {
destFolderId: number;
folderIds: number[];
fileIds: number[];
deleteAfter: boolean;
folderTitle: string;
isCopy: boolean;
translations: { [key: string]: string };
isUploadConflict: boolean;
newUploadData: {
files: { file: { name: string; size: string } }[];
filesSize: number;
};
};
export type TActiveItem = TFile | TFolder;
export interface ConflictResolveDialogProps {
visible: boolean;
setConflictResolveDialogVisible: (value: boolean) => void;
conflictResolveDialogData: TConflictResolveDialogData;
items: (TFile | TFolder)[];
itemOperationToFolder: (data: {
destFolderId: number;
folderIds: number[];
fileIds: number[];
conflictResolveType: ConflictResolveType;
deleteAfter: boolean;
isCopy: boolean;
translations: {
[key: string]: string;
};
}) => Promise<void>;
activeFiles: TActiveItem[];
activeFolders: TActiveItem[];
setActiveFiles: (items: TActiveItem[]) => void;
setActiveFolders: (items: TActiveItem[]) => void;
updateActiveFiles: (items: TActiveItem[]) => void;
setSelected: (value: string) => void;
setMoveToPanelVisible: (value: boolean) => void;
setRestorePanelVisible: (value: boolean) => void;
setCopyPanelVisible: (value: boolean) => void;
setRestoreAllPanelVisible: (value: boolean) => void;
setMoveToPublicRoomVisible: (value: boolean) => void;
handleFilesUpload: (
data: {
files: {
file: {
name: string;
size: string;
};
}[];
filesSize: number;
},
t: TTranslation,
create: boolean,
) => void;
}

View File

@ -1,368 +0,0 @@
import React, { useState } from "react";
import { ModalDialog } from "@docspace/shared/components/modal-dialog";
import { RadioButtonGroup } from "@docspace/shared/components/radio-button-group";
import { Button } from "@docspace/shared/components/button";
import { Text } from "@docspace/shared/components/text";
import { toastr } from "@docspace/shared/components/toast";
import { withTranslation, Trans } from "react-i18next";
import { inject, observer } from "mobx-react";
import { ConflictResolveType } from "@docspace/shared/enums";
import styled from "styled-components";
const StyledModalDialog = styled(ModalDialog)`
.radio {
padding-bottom: 8px;
}
.message {
margin-bottom: 16px;
.bold {
font-weight: 600;
}
}
.select-action {
margin-bottom: 12px;
}
.conflict-resolve-radio-button {
label {
display: flex;
align-items: flex-start;
&:not(:last-child) {
margin-bottom: 12px;
}
}
svg {
overflow: visible;
${({ theme }) =>
theme.interfaceDirection === "rtl"
? `margin-left: 8px;`
: `margin-right: 8px;`}
margin-top: 3px;
}
.radio-option-title {
font-weight: 600;
font-size: ${(props) => props.theme.getCorrectFontSize("14px")};
line-height: 16px;
}
.radio-option-description {
font-size: ${(props) => props.theme.getCorrectFontSize("12px")};
line-height: 16px;
color: #a3a9ae;
}
}
`;
const ConflictResolveDialog = (props) => {
const {
t,
tReady,
visible,
setConflictResolveDialogVisible,
conflictResolveDialogData,
items,
itemOperationToFolder,
activeFiles,
activeFolders,
setActiveFiles,
setActiveFolders,
updateActiveFiles,
setSelected,
setMoveToPanelVisible,
setRestorePanelVisible,
setCopyPanelVisible,
setRestoreAllPanelVisible,
setMoveToPublicRoomVisible,
handleFilesUpload,
} = props;
const {
destFolderId,
folderIds,
fileIds,
deleteAfter,
folderTitle,
isCopy,
translations,
isUploadConflict,
} = conflictResolveDialogData;
const [resolveType, setResolveType] = useState("overwrite");
const onSelectResolveType = (e) => setResolveType(e.target.value);
const onClose = () => {
setMoveToPublicRoomVisible(false);
setConflictResolveDialogVisible(false);
};
const onClosePanels = () => {
setConflictResolveDialogVisible(false);
setMoveToPanelVisible(false);
setRestorePanelVisible(false);
setCopyPanelVisible(false);
setRestoreAllPanelVisible(false);
setMoveToPublicRoomVisible(false);
};
const differenceArray = (activeItems, ids) => {
return activeItems.filter((item) => !ids.includes(item.id ?? item));
};
const onCloseDialog = () => {
const newActiveFiles = differenceArray(activeFiles, fileIds);
const newActiveFolder = differenceArray(activeFolders, folderIds);
setActiveFiles(newActiveFiles);
setActiveFolders(newActiveFolder);
onClose();
};
const getResolveType = () => {
switch (resolveType) {
case "skip":
return ConflictResolveType.Skip;
case "overwrite":
return ConflictResolveType.Overwrite;
case "create":
return ConflictResolveType.Duplicate;
default:
return ConflictResolveType.Overwrite;
}
};
const onAcceptType = async () => {
const conflictResolveType = getResolveType();
let newFileIds = fileIds;
let newActiveFiles = activeFiles;
if (conflictResolveType === ConflictResolveType.Skip) {
for (let item of items) {
newFileIds = newFileIds.filter((x) => x !== item.id);
newActiveFiles = newActiveFiles.filter((f) => f.id !== item.id);
}
}
updateActiveFiles(newActiveFiles);
if (!folderIds.length && !newFileIds.length) {
setSelected("none");
onClosePanels();
return;
}
const data = {
destFolderId,
folderIds,
fileIds: newFileIds,
conflictResolveType,
deleteAfter,
isCopy,
translations,
};
setSelected("none");
onClosePanels();
try {
sessionStorage.setItem("filesSelectorPath", `${destFolderId}`);
await itemOperationToFolder(data);
} catch (error) {
toastr.error(error.message ? error.message : error);
}
};
const onAcceptUploadType = async () => {
const conflictResolveType = getResolveType();
let data = conflictResolveDialogData.newUploadData;
if (conflictResolveType === ConflictResolveType.Skip) {
let filesSize = 0;
const newFiles = [];
for (let i = 0; i < data.files.length; i++) {
if (!items.includes(data.files[i].file.name)) {
filesSize += data.files[i].file.size;
newFiles.push(data.files[i]);
}
}
data = { ...data, files: newFiles, filesSize };
}
if (data.files.length === 0) {
setSelected("none");
onClosePanels();
return;
}
setSelected("none");
onClosePanels();
try {
handleFilesUpload(
data,
t,
conflictResolveType === ConflictResolveType.Duplicate
);
} catch (error) {
toastr.error(error.message ? error.message : error);
}
};
const radioOptions = [
{
label: (
<div>
<Text className="radio-option-title">{t("OverwriteTitle")}</Text>
<Text className="radio-option-description">
{t("OverwriteDescription")}
</Text>
</div>
),
value: "overwrite",
},
{
label: (
<div>
<Text className="radio-option-title">
{t("Common:CreateFileCopy")}
</Text>
<Text className="radio-option-description">
{t("CreateDescription")}
</Text>
</div>
),
value: "create",
},
{
label: (
<div>
<Text className="radio-option-title">{t("SkipTitle")}</Text>
<Text className="radio-option-description">
{t("SkipDescription")}
</Text>
</div>
),
value: "skip",
},
];
return (
<StyledModalDialog
isLoading={!tReady}
visible={visible}
onClose={onCloseDialog}
isLarge
zIndex={312}
>
<ModalDialog.Header>{t("ConflictResolveTitle")}</ModalDialog.Header>
<ModalDialog.Body>
<Text className="message">
{items.length === 1 ? (
<Trans
t={t}
ns="ConflictResolveDialog"
i18nKey="ConflictResolveDescription"
values={{ file: items[0].title, folder: folderTitle }}
components={{ 1: <span className="bold" /> }}
/>
) : (
<Trans
t={t}
ns="ConflictResolveDialog"
i18nKey="ConflictResolveDescriptionFiles"
values={{ filesCount: items.length, folder: folderTitle }}
components={{ 1: <span className="bold" /> }}
/>
)}
</Text>
<Text className="select-action">
{t("ConflictResolveSelectAction")}
</Text>
<RadioButtonGroup
className="conflict-resolve-radio-button"
orientation="vertical"
fontSize="13px"
fontWeight="400"
name="group"
onClick={onSelectResolveType}
options={radioOptions}
selected="overwrite"
/>
</ModalDialog.Body>
<ModalDialog.Footer>
<Button
key="OkButton"
label={t("Common:OKButton")}
size="normal"
primary
onClick={isUploadConflict ? onAcceptUploadType : onAcceptType}
/>
<Button
key="CancelButton"
label={t("Common:CancelButton")}
size="normal"
onClick={onCloseDialog}
/>
</ModalDialog.Footer>
</StyledModalDialog>
);
};
export default inject(({ auth, dialogsStore, uploadDataStore, filesStore }) => {
const {
conflictResolveDialogVisible: visible,
setConflictResolveDialogVisible,
conflictResolveDialogData,
conflictResolveDialogItems: items,
setMoveToPanelVisible,
setRestorePanelVisible,
setRestoreAllPanelVisible,
setCopyPanelVisible,
setMoveToPublicRoomVisible,
} = dialogsStore;
const { itemOperationToFolder, handleFilesUpload } = uploadDataStore;
const {
activeFiles,
activeFolders,
setActiveFiles,
setActiveFolders,
updateActiveFiles,
setSelected,
} = filesStore;
const { settingsStore } = auth;
const { theme } = settingsStore;
return {
theme,
items,
visible,
conflictResolveDialogData,
setConflictResolveDialogVisible,
itemOperationToFolder,
activeFiles,
activeFolders,
setActiveFiles,
setActiveFolders,
updateActiveFiles,
setSelected,
setMoveToPanelVisible,
setRestorePanelVisible,
setRestoreAllPanelVisible,
setCopyPanelVisible,
setMoveToPublicRoomVisible,
handleFilesUpload,
};
})(
withTranslation(["ConflictResolveDialog", "Common"])(
observer(ConflictResolveDialog)
)
);

View File

@ -0,0 +1,263 @@
import React from "react";
import { useTranslation, Trans } from "react-i18next";
import { inject, observer } from "mobx-react";
import ConflictResolve from "@docspace/shared/dialogs/conflict-resolve";
import { toastr } from "@docspace/shared/components/toast";
import { TData } from "@docspace/shared/components/toast/Toast.type";
import { ConflictResolveType } from "@docspace/shared/enums";
import DialogsStore from "SRC_DIR/store/DialogsStore";
import UploadDataStore from "SRC_DIR/store/UploadDataStore";
import FilesStore from "SRC_DIR/store/FilesStore";
import {
ConflictResolveDialogProps,
TActiveItem,
} from "./ConflictResolveDialog.types";
const ConflictResolveDialog = (props: ConflictResolveDialogProps) => {
const {
visible,
setConflictResolveDialogVisible,
conflictResolveDialogData,
items,
itemOperationToFolder,
activeFiles,
activeFolders,
setActiveFiles,
setActiveFolders,
updateActiveFiles,
setSelected,
setMoveToPanelVisible,
setRestorePanelVisible,
setCopyPanelVisible,
setRestoreAllPanelVisible,
setMoveToPublicRoomVisible,
handleFilesUpload,
} = props;
const { t, ready } = useTranslation(["ConflictResolveDialog", "Common"]);
const {
destFolderId,
folderIds,
fileIds,
deleteAfter,
folderTitle,
isCopy,
translations,
isUploadConflict,
} = conflictResolveDialogData;
const onClose = () => {
setMoveToPublicRoomVisible(false);
setConflictResolveDialogVisible(false);
};
const onClosePanels = () => {
setConflictResolveDialogVisible(false);
setMoveToPanelVisible(false);
setRestorePanelVisible(false);
setCopyPanelVisible(false);
setRestoreAllPanelVisible(false);
setMoveToPublicRoomVisible(false);
};
const differenceArray = (
activeItems: TActiveItem[],
ids: (number | string)[],
) => {
return activeItems.filter((item) => {
const itemId =
typeof item !== "number" && typeof item !== "string" && "id" in item
? item.id
: item;
return !ids.includes(itemId);
});
};
const onCloseDialog = () => {
const newActiveFiles = differenceArray(activeFiles, fileIds);
const newActiveFolder = differenceArray(activeFolders, folderIds);
setActiveFiles(newActiveFiles);
setActiveFolders(newActiveFolder);
onClose();
};
const onAcceptType = async (conflictResolveType: ConflictResolveType) => {
let newFileIds = fileIds;
let newActiveFiles = activeFiles;
if (conflictResolveType === ConflictResolveType.Skip) {
items.forEach((item) => {
newFileIds = newFileIds.filter((x) => x !== item.id);
newActiveFiles = newActiveFiles.filter((f) => f.id !== item.id);
});
}
updateActiveFiles(newActiveFiles);
if (!folderIds.length && !newFileIds.length) {
setSelected("none");
onClosePanels();
return;
}
const data = {
destFolderId,
folderIds,
fileIds: newFileIds,
conflictResolveType,
deleteAfter,
isCopy,
translations,
};
setSelected("none");
onClosePanels();
try {
sessionStorage.setItem("filesSelectorPath", `${destFolderId}`);
await itemOperationToFolder(data);
} catch (error: unknown) {
const message = (error as { message: string }).message
? ((error as { message: string }).message as TData)
: (error as string);
toastr.error(message);
}
};
const onAcceptUploadType = async (
conflictResolveType: ConflictResolveType,
) => {
let data = conflictResolveDialogData.newUploadData;
if (conflictResolveType === ConflictResolveType.Skip) {
let filesSize = 0;
const newFiles = [];
for (let i = 0; i < data.files.length; i += 1) {
// @ts-expect-error need rewrite stores to typescript for fix this
if (!items.includes(data.files[i].file.name)) {
filesSize += +data.files[i].file.size;
newFiles.push(data.files[i]);
}
}
data = { ...data, files: newFiles, filesSize };
}
if (data.files.length === 0) {
setSelected("none");
onClosePanels();
return;
}
setSelected("none");
onClosePanels();
try {
handleFilesUpload(
data,
t,
conflictResolveType === ConflictResolveType.Duplicate,
);
} catch (error) {
const message = (error as { message: string }).message
? ((error as { message: string }).message as TData)
: (error as string);
toastr.error(message);
}
};
const messageText =
items.length === 1 ? (
<Trans
t={t}
ns="ConflictResolveDialog"
i18nKey="ConflictResolveDescription"
values={{ file: items[0].title, folder: folderTitle }}
components={{ 1: <span className="bold" /> }}
/>
) : (
<Trans
t={t}
ns="ConflictResolveDialog"
i18nKey="ConflictResolveDescriptionFiles"
values={{ filesCount: items.length, folder: folderTitle }}
components={{ 1: <span className="bold" /> }}
/>
);
return (
<ConflictResolve
visible={visible}
headerLabel={t("ConflictResolveTitle")}
isLoading={!ready}
onSubmit={isUploadConflict ? onAcceptUploadType : onAcceptType}
onClose={onCloseDialog}
cancelButtonLabel={t("Common:CancelButton")}
submitButtonLabel={t("Common:OKButton")}
messageText={messageText}
selectActionText={t("ConflictResolveSelectAction")}
overwriteTitle={t("OverwriteTitle")}
overwriteDescription={t("OverwriteDescription")}
duplicateTitle={t("Common:CreateFileCopy")}
duplicateDescription={t("CreateDescription")}
skipTitle={t("SkipTitle")}
skipDescription={t("SkipDescription")}
/>
);
};
export default inject(
({
dialogsStore,
uploadDataStore,
filesStore,
}: {
dialogsStore: DialogsStore;
uploadDataStore: UploadDataStore;
filesStore: FilesStore;
}) => {
const {
conflictResolveDialogVisible: visible,
setConflictResolveDialogVisible,
conflictResolveDialogData,
conflictResolveDialogItems: items,
setMoveToPanelVisible,
setRestorePanelVisible,
setRestoreAllPanelVisible,
setCopyPanelVisible,
setMoveToPublicRoomVisible,
} = dialogsStore;
const { itemOperationToFolder, handleFilesUpload } = uploadDataStore;
const {
activeFiles,
activeFolders,
setActiveFiles,
setActiveFolders,
updateActiveFiles,
setSelected,
} = filesStore;
return {
items,
visible,
conflictResolveDialogData,
setConflictResolveDialogVisible,
itemOperationToFolder,
activeFiles,
activeFolders,
setActiveFiles,
setActiveFolders,
updateActiveFiles,
setSelected,
setMoveToPanelVisible,
setRestorePanelVisible,
setRestoreAllPanelVisible,
setCopyPanelVisible,
setMoveToPublicRoomVisible,
handleFilesUpload,
};
},
)(observer(ConflictResolveDialog));

View File

@ -287,6 +287,7 @@ const PureConnectDialogContainer = (props) => {
)}
<FieldContainer
labelVisible
labelText={t("Login")}
isRequired
isVertical
@ -305,6 +306,7 @@ const PureConnectDialogContainer = (props) => {
/>
</FieldContainer>
<FieldContainer
labelVisible
labelText={t("Common:Password")}
isRequired
isVertical
@ -378,14 +380,20 @@ const ConnectDialog = withTranslation([
])(PureConnectDialogContainer);
export default inject(
({ auth, settingsStore, selectedFolderStore, dialogsStore, backup }) => {
({
settingsStore,
filesSettingsStore,
selectedFolderStore,
dialogsStore,
backup,
}) => {
const {
providers,
saveThirdParty,
openConnectWindow,
fetchThirdPartyProviders,
} = settingsStore.thirdPartyStore;
const { personal, folderFormValidation } = auth.settingsStore;
} = filesSettingsStore.thirdPartyStore;
const { personal, folderFormValidation } = settingsStore;
const { id, folders } = selectedFolderStore;
const {

View File

@ -149,7 +149,7 @@ export default inject(
uploadDataStore,
treeFoldersStore,
dialogsStore,
settingsStore,
filesSettingsStore,
selectedFolderStore,
}) => {
const {
@ -161,7 +161,7 @@ export default inject(
const { convertUploadedFiles, convertFile, setIsConvertSingleFile } =
uploadDataStore;
const { storeOriginalFiles, setStoreOriginal, hideConfirmConvert } =
settingsStore;
filesSettingsStore;
const { id: folderId } = selectedFolderStore;
const {
convertDialogVisible: visible,

View File

@ -258,7 +258,13 @@ const ConvertPasswordDialog = withTranslation([
])(ConvertPasswordDialogComponent);
export default inject(
({ filesStore, filesActionsStore, auth, dialogsStore, uploadDataStore }) => {
({
filesStore,
filesActionsStore,
settingsStore,
dialogsStore,
uploadDataStore,
}) => {
const {
convertPasswordDialogVisible: visible,
setConvertPasswordDialogVisible,
@ -268,7 +274,7 @@ export default inject(
const { copyAsAction, fileCopyAs } = uploadDataStore;
const { setPasswordEntryProcess } = filesStore;
const { completeAction } = filesActionsStore;
const { settingsStore } = auth;
const { isTabletView, isDesktopClient } = settingsStore;
return {

Some files were not shown because too many files have changed in this diff Show More