Merge branch 'develop' into feature/socket-newtag
This commit is contained in:
commit
fbfd9daa46
6
.github/workflows/4testing-multi-build.yml
vendored
6
.github/workflows/4testing-multi-build.yml
vendored
@ -2,7 +2,7 @@ name: 4testing multiarch-build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "develop" ]
|
||||
branches: [ "release/rc-v1.2.0" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@ -33,10 +33,10 @@ jobs:
|
||||
cd ./build/install/docker
|
||||
REPO="onlyoffice" \
|
||||
DOCKER_IMAGE_PREFIX="4testing-docspace" \
|
||||
DOCKER_TAG="develop" \
|
||||
DOCKER_TAG="rc-v1.2.0" \
|
||||
DOCKERFILE="Dockerfile.app" \
|
||||
docker buildx bake -f build.yml \
|
||||
--set *.args.GIT_BRANCH="develop" \
|
||||
--set *.args.GIT_BRANCH="release/rc-v1.2.0" \
|
||||
--set *.platform=linux/amd64 \
|
||||
--push
|
||||
shell: bash
|
||||
|
7
build/build.document.server.docker.bat
Normal file
7
build/build.document.server.docker.bat
Normal file
@ -0,0 +1,7 @@
|
||||
@echo off
|
||||
|
||||
pwsh %~dp0/build.document.server.docker.ps1 %1
|
||||
|
||||
echo.
|
||||
|
||||
pause
|
15
build/build.document.server.docker.ps1
Normal file
15
build/build.document.server.docker.ps1
Normal file
@ -0,0 +1,15 @@
|
||||
$PSversionMajor = $PSVersionTable.PSVersion | sort-object major | ForEach-Object { $_.major }
|
||||
$PSversionMinor = $PSVersionTable.PSVersion | sort-object minor | ForEach-Object { $_.minor }
|
||||
|
||||
if ($PSversionMajor -lt 7 -or $PSversionMinor -lt 2) {
|
||||
Write-Error "Powershell version must be greater than or equal to 7.2."
|
||||
exit
|
||||
}
|
||||
|
||||
$RootDir = Split-Path -Parent $PSScriptRoot
|
||||
|
||||
Write-Host "Run Document server" -ForegroundColor Green
|
||||
$DOCUMENT_SERVER_IMAGE_NAME = "onlyoffice/documentserver-de:latest"
|
||||
|
||||
|
||||
docker run -i -t -d -p 8085:80 -e JWT_ENABLED=false -e JWT_IN_BODY=false --restart=always -v $RootDir/Data:/var/www/onlyoffice/Data $DOCUMENT_SERVER_IMAGE_NAME
|
@ -161,8 +161,9 @@ public class SecurityContext
|
||||
return false;
|
||||
}
|
||||
|
||||
var settingLoginEvents = await _dbLoginEventsManager.GetLoginEventIds(tenant, userid);
|
||||
if (loginEventId != 0 && !settingLoginEvents.Contains(loginEventId))
|
||||
var loginEventById = await _dbLoginEventsManager.GetById(loginEventId);
|
||||
|
||||
if (loginEventById == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
32
common/ASC.Core.Common/Core/Payments.cs
Normal file
32
common/ASC.Core.Common/Core/Payments.cs
Normal file
@ -0,0 +1,32 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.Core;
|
||||
public enum Payments
|
||||
{
|
||||
Paid = 0,
|
||||
Free = 1
|
||||
}
|
@ -24,6 +24,8 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace ASC.Core.Data;
|
||||
|
||||
[Scope]
|
||||
@ -62,25 +64,21 @@ public class DbLoginEventsManager
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public async Task<List<int>> GetLoginEventIds(int tenantId, Guid userId)
|
||||
public async Task<LoginEvent> GetById(int id)
|
||||
{
|
||||
var date = DateTime.UtcNow.AddYears(-1);
|
||||
if (id < 0) return null;
|
||||
|
||||
using var loginEventContext = _dbContextFactory.CreateDbContext();
|
||||
using var loginEventContext = await _dbContextFactory.CreateDbContextAsync();
|
||||
|
||||
var resultList = await loginEventContext.LoginEvents
|
||||
.Where(r => r.TenantId == tenantId && r.UserId == userId && _loginActions.Contains(r.Action ?? 0) && r.Date >= date && r.Active)
|
||||
.Select(r => r.Id)
|
||||
.ToListAsync();
|
||||
|
||||
return resultList;
|
||||
return await loginEventContext.LoginEvents.FindAsync(id);
|
||||
}
|
||||
|
||||
public async Task<List<BaseEvent>> GetLoginEvents(int tenantId, Guid userId)
|
||||
{
|
||||
var date = DateTime.UtcNow.AddYears(-1);
|
||||
|
||||
using var loginEventContext = _dbContextFactory.CreateDbContext();
|
||||
using var loginEventContext = await _dbContextFactory.CreateDbContextAsync();
|
||||
|
||||
var loginInfo = await loginEventContext.LoginEvents
|
||||
.Where(r => r.TenantId == tenantId && r.UserId == userId && _loginActions.Contains(r.Action ?? 0) && r.Date >= date && r.Active)
|
||||
.OrderByDescending(r => r.Id)
|
||||
@ -91,7 +89,8 @@ public class DbLoginEventsManager
|
||||
|
||||
public async Task LogOutEvent(int loginEventId)
|
||||
{
|
||||
using var loginEventContext = _dbContextFactory.CreateDbContext();
|
||||
using var loginEventContext = await _dbContextFactory.CreateDbContextAsync();
|
||||
|
||||
var events = await loginEventContext.LoginEvents
|
||||
.Where(r => r.Id == loginEventId)
|
||||
.ToListAsync();
|
||||
@ -108,7 +107,8 @@ public class DbLoginEventsManager
|
||||
|
||||
public async Task LogOutAllActiveConnections(int tenantId, Guid userId)
|
||||
{
|
||||
using var loginEventContext = _dbContextFactory.CreateDbContext();
|
||||
using var loginEventContext = await _dbContextFactory.CreateDbContextAsync();
|
||||
|
||||
var events = await loginEventContext.LoginEvents
|
||||
.Where(r => r.TenantId == tenantId && r.UserId == userId && r.Active)
|
||||
.ToListAsync();
|
||||
@ -125,7 +125,8 @@ public class DbLoginEventsManager
|
||||
|
||||
public async Task LogOutAllActiveConnectionsForTenant(int tenantId)
|
||||
{
|
||||
using var loginEventContext = _dbContextFactory.CreateDbContext();
|
||||
using var loginEventContext = await _dbContextFactory.CreateDbContextAsync();
|
||||
|
||||
var events = await loginEventContext.LoginEvents
|
||||
.Where(r => r.TenantId == tenantId && r.Active)
|
||||
.ToListAsync();
|
||||
@ -140,7 +141,8 @@ public class DbLoginEventsManager
|
||||
|
||||
public async Task LogOutAllActiveConnectionsExceptThis(int loginEventId, int tenantId, Guid userId)
|
||||
{
|
||||
using var loginEventContext = _dbContextFactory.CreateDbContext();
|
||||
using var loginEventContext = await _dbContextFactory.CreateDbContextAsync();
|
||||
|
||||
var events = await loginEventContext.LoginEvents
|
||||
.Where(r => r.TenantId == tenantId && r.UserId == userId && r.Id != loginEventId && r.Active)
|
||||
.ToListAsync();
|
||||
|
@ -220,9 +220,20 @@ public class EFUserService : IUserService
|
||||
q = GetUserQueryForFilter(userDbContext, q, isDocSpaceAdmin, employeeStatus, includeGroups, excludeGroups, activationStatus, text);
|
||||
|
||||
if (!string.IsNullOrEmpty(sortBy))
|
||||
{
|
||||
if (sortBy == "type")
|
||||
{
|
||||
var q1 = from user in q join userGroup in userDbContext.UserGroups.Where(g => !g.Removed && (g.UserGroupId == Users.Constants.GroupAdmin.ID || g.UserGroupId == Users.Constants.GroupUser.ID))
|
||||
on user.Id equals userGroup.Userid into joinedGroup from @group in joinedGroup.DefaultIfEmpty() select new { user, @group };
|
||||
|
||||
q = sortOrderAsc ? q1.OrderBy(r => r.group != null && r.group.UserGroupId == Users.Constants.GroupAdmin.ID ? 1 : r.group == null ? 2 : 3).Select(r => r.user)
|
||||
: q1.OrderByDescending(u => u.group != null && u.group.UserGroupId == Users.Constants.GroupAdmin.ID ? 1 : u.group == null ? 2 : 3).Select(r => r.user);
|
||||
}
|
||||
else
|
||||
{
|
||||
q = q.OrderBy(sortBy, sortOrderAsc);
|
||||
}
|
||||
}
|
||||
|
||||
if (offset != 0)
|
||||
{
|
||||
|
@ -19,7 +19,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="MySql.Data" Version="8.0.30" />
|
||||
<PackageReference Include="MySql.Data" Version="8.0.31" />
|
||||
<PackageReference Include="protobuf-net" Version="3.1.17" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -125,7 +125,7 @@
|
||||
"ConnectionStrings": {
|
||||
"default": {
|
||||
"name": "default",
|
||||
"connectionString": "Server=localhost;Database=onlyoffice;User ID=dev;Password=dev;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;AllowPublicKeyRetrieval=True;ConnectionReset=false",
|
||||
"connectionString": "Server=localhost;Database=onlyoffice;User ID=dev;Password=dev;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;AllowPublicKeyRetrieval=True;Connection Timeout=30;Maximum Pool Size=300;ConnectionReset=false",
|
||||
"providerName": "MySql.Data.MySqlClient"
|
||||
},
|
||||
"postgre": {
|
||||
@ -135,7 +135,7 @@
|
||||
},
|
||||
"mysql": {
|
||||
"name": "mysql",
|
||||
"connectionString": "Server=localhost;Database=onlyoffice;User ID=dev;Password=dev;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;AllowPublicKeyRetrieval=True;ConnectionReset=false",
|
||||
"connectionString": "Server=localhost;Database=onlyoffice;User ID=dev;Password=dev;Pooling=true;Character Set=utf8;AutoEnlist=false;SSL Mode=none;AllowPublicKeyRetrieval=True;Connection Timeout=30;Maximum Pool Size=300;ConnectionReset=false",
|
||||
"providerName": "MySql.Data.MySqlClient"
|
||||
}
|
||||
},
|
||||
|
@ -89,6 +89,14 @@ const ArchiveDialogComponent = (props) => {
|
||||
const acceptButton =
|
||||
action === "archive" ? t("Common:OKButton") : t("Common:Restore");
|
||||
|
||||
const isArchive = action === "archive";
|
||||
const idButtonSubmit = isArchive
|
||||
? "shared_move-to-archived-modal_submit"
|
||||
: "restore-all_submit";
|
||||
const idButtonCancel = isArchive
|
||||
? "shared_move-to-archived-modal_cancel"
|
||||
: "restore-all_cancel";
|
||||
|
||||
return (
|
||||
<StyledModal
|
||||
isLoading={!tReady}
|
||||
@ -102,6 +110,7 @@ const ArchiveDialogComponent = (props) => {
|
||||
</ModalDialog.Body>
|
||||
<ModalDialog.Footer>
|
||||
<Button
|
||||
id={idButtonSubmit}
|
||||
key="OkButton"
|
||||
label={acceptButton}
|
||||
size="normal"
|
||||
@ -111,6 +120,7 @@ const ArchiveDialogComponent = (props) => {
|
||||
scale
|
||||
/>
|
||||
<Button
|
||||
id={idButtonCancel}
|
||||
key="CancelButton"
|
||||
label={t("Common:CancelButton")}
|
||||
size="normal"
|
||||
|
@ -98,6 +98,7 @@ class ChangeUserStatusDialogComponent extends React.Component {
|
||||
</ModalDialog.Body>
|
||||
<ModalDialog.Footer>
|
||||
<Button
|
||||
id="change-user-status-modal_submit"
|
||||
label={t("ChangeUsersStatusButton")}
|
||||
size="normal"
|
||||
primary
|
||||
@ -107,6 +108,7 @@ class ChangeUserStatusDialogComponent extends React.Component {
|
||||
isDisabled={userIDs.length === 0}
|
||||
/>
|
||||
<Button
|
||||
id="change-user-status-modal_cancel"
|
||||
label={t("Common:CancelButton")}
|
||||
size="normal"
|
||||
scale
|
||||
|
@ -109,6 +109,7 @@ class ChangeUserTypeDialogComponent extends React.Component {
|
||||
</ModalDialog.Body>
|
||||
<ModalDialog.Footer>
|
||||
<Button
|
||||
id="change-user-type-modal_submit"
|
||||
label={t("ChangeUserTypeButton")}
|
||||
size="normal"
|
||||
scale
|
||||
@ -118,6 +119,7 @@ class ChangeUserTypeDialogComponent extends React.Component {
|
||||
isDisabled={!userIDs.length}
|
||||
/>
|
||||
<Button
|
||||
id="change-user-type-modal_cancel"
|
||||
label={t("Common:CancelButton")}
|
||||
size="normal"
|
||||
scale
|
||||
|
@ -149,6 +149,7 @@ const CreateRoomDialog = ({
|
||||
{!!roomParams.type && (
|
||||
<ModalDialog.Footer>
|
||||
<Button
|
||||
id="shared_create-room-modal_submit"
|
||||
tabIndex={5}
|
||||
label={t("Common:Create")}
|
||||
size="normal"
|
||||
@ -158,6 +159,7 @@ const CreateRoomDialog = ({
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
<Button
|
||||
id="shared_create-room-modal_cancel"
|
||||
tabIndex={5}
|
||||
label={t("Common:CancelButton")}
|
||||
size="normal"
|
||||
|
@ -2,6 +2,7 @@ import { RoomsType } from "@docspace/common/constants";
|
||||
|
||||
export const roomTypes = [
|
||||
{
|
||||
id: "shared_filling-forms-room",
|
||||
type: RoomsType.FillingFormsRoom,
|
||||
title: "FillingFormsRoomTitle",
|
||||
description: "FillingFormsRoomDescription",
|
||||
@ -10,6 +11,7 @@ export const roomTypes = [
|
||||
secondaryInfo: "FillingFormsRoomSecondaryInfo",
|
||||
},
|
||||
{
|
||||
id: "shared_collaboration-room",
|
||||
type: RoomsType.EditingRoom,
|
||||
title: "CollaborationRoomTitle",
|
||||
description: "CollaborationRoomDescription",
|
||||
@ -18,6 +20,7 @@ export const roomTypes = [
|
||||
secondaryInfo: "CollaborationRoomSecondaryInfo",
|
||||
},
|
||||
{
|
||||
id: "shared_review-room",
|
||||
type: RoomsType.ReviewRoom,
|
||||
title: "ReviewRoomTitle",
|
||||
description: "ReviewRoomDescription",
|
||||
@ -26,6 +29,7 @@ export const roomTypes = [
|
||||
secondaryInfo: "ReviewRoomSecondaryInfo",
|
||||
},
|
||||
{
|
||||
id: "shared_read-only-room",
|
||||
type: RoomsType.ReadOnlyRoom,
|
||||
title: "ViewOnlyRoomTitle",
|
||||
description: "ViewOnlyRoomDescription",
|
||||
@ -34,6 +38,7 @@ export const roomTypes = [
|
||||
secondaryInfo: "ViewOnlyRoomSecondaryInfo",
|
||||
},
|
||||
{
|
||||
id: "shared_custom-room",
|
||||
type: RoomsType.CustomRoom,
|
||||
title: "CustomRoomTitle",
|
||||
description: "CustomRoomDescription",
|
||||
|
@ -21,7 +21,13 @@ const StyledToggleParam = styled(StyledParam)`
|
||||
}
|
||||
`;
|
||||
|
||||
const ToggleParam = ({ title, description, isChecked, onCheckedChange }) => {
|
||||
const ToggleParam = ({
|
||||
id,
|
||||
title,
|
||||
description,
|
||||
isChecked,
|
||||
onCheckedChange,
|
||||
}) => {
|
||||
return (
|
||||
<StyledToggleParam isPrivate>
|
||||
<div className="set_room_params-info">
|
||||
@ -31,6 +37,7 @@ const ToggleParam = ({ title, description, isChecked, onCheckedChange }) => {
|
||||
<div className="set_room_params-info-description">{description}</div>
|
||||
</div>
|
||||
<ToggleButton
|
||||
id={id}
|
||||
className="set_room_params-toggle"
|
||||
isChecked={isChecked}
|
||||
onChange={onCheckedChange}
|
||||
|
@ -131,7 +131,15 @@ const StyledDisplayItem = styled(StyledRoomType)`
|
||||
}
|
||||
`;
|
||||
|
||||
const RoomType = ({ t, room, onClick, type = "listItem", isOpen }) => {
|
||||
const RoomType = ({
|
||||
t,
|
||||
room,
|
||||
onClick,
|
||||
type = "listItem",
|
||||
isOpen,
|
||||
id,
|
||||
selectedId,
|
||||
}) => {
|
||||
const arrowClassName =
|
||||
type === "dropdownButton"
|
||||
? "choose_room-forward_btn dropdown-button"
|
||||
@ -170,23 +178,37 @@ const RoomType = ({ t, room, onClick, type = "listItem", isOpen }) => {
|
||||
);
|
||||
|
||||
return type === "listItem" ? (
|
||||
<StyledListItem title={t(room.title)} onClick={onClick}>
|
||||
<StyledListItem id={id} title={t(room.title)} onClick={onClick}>
|
||||
{content}
|
||||
</StyledListItem>
|
||||
) : type === "dropdownButton" ? (
|
||||
<StyledDropdownButton
|
||||
id={id}
|
||||
title={t(room.title)}
|
||||
onClick={onClick}
|
||||
isOpen={isOpen}
|
||||
data-selected-id={selectedId}
|
||||
>
|
||||
{content}
|
||||
</StyledDropdownButton>
|
||||
) : type === "dropdownItem" ? (
|
||||
<StyledDropdownItem title={t(room.title)} onClick={onClick} isOpen={isOpen}>
|
||||
<StyledDropdownItem
|
||||
id={id}
|
||||
title={t(room.title)}
|
||||
onClick={onClick}
|
||||
isOpen={isOpen}
|
||||
data-selected-id={selectedId}
|
||||
>
|
||||
{content}
|
||||
</StyledDropdownItem>
|
||||
) : (
|
||||
<StyledDisplayItem title={t(room.title)}>{content}</StyledDisplayItem>
|
||||
<StyledDisplayItem
|
||||
id={id}
|
||||
title={t(room.title)}
|
||||
data-selected-id={selectedId}
|
||||
>
|
||||
{content}
|
||||
</StyledDisplayItem>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -41,6 +41,7 @@ const DropdownDesktop = ({ t, open, roomTypes, chooseRoomType }) => {
|
||||
<div className="dropdown-content">
|
||||
{roomTypes.map((room) => (
|
||||
<RoomType
|
||||
id={room.id}
|
||||
t={t}
|
||||
key={room.type}
|
||||
room={room}
|
||||
|
@ -72,6 +72,7 @@ const DropdownMobile = ({ t, open, onClose, roomTypes, chooseRoomType }) => {
|
||||
<div className="dropdown-mobile-content">
|
||||
{roomTypes.map((room) => (
|
||||
<RoomType
|
||||
id={room.id}
|
||||
t={t}
|
||||
key={room.type}
|
||||
room={room}
|
||||
|
@ -37,11 +37,12 @@ const RoomTypeDropdown = ({
|
||||
setRoomType(roomType);
|
||||
toggleDropdown();
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledRoomTypeDropdown isOpen={isOpen}>
|
||||
<RoomType
|
||||
t={t}
|
||||
id="shared_select-room"
|
||||
selectedId={currentRoom.id}
|
||||
room={currentRoom}
|
||||
type="dropdownButton"
|
||||
isOpen={isOpen}
|
||||
|
@ -21,6 +21,7 @@ const RoomTypeList = ({ t, setRoomType }) => {
|
||||
<StyledRoomTypeList>
|
||||
{roomTypes.map((room) => (
|
||||
<RoomType
|
||||
id={room.id}
|
||||
t={t}
|
||||
key={room.type}
|
||||
room={room}
|
||||
|
@ -74,7 +74,7 @@ const SetRoomParams = ({
|
||||
)}
|
||||
|
||||
<InputParam
|
||||
id={"room-name"}
|
||||
id="shared_room-name"
|
||||
title={`${t("Common:Name")}:`}
|
||||
placeholder={t("NamePlaceholder")}
|
||||
value={roomParams.title}
|
||||
|
@ -19,7 +19,9 @@ const TagDropdown = ({
|
||||
const [dropdownMaxHeight, setDropdownMaxHeight] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
document.getElementById("tags-input").addEventListener("keyup", onKeyPress);
|
||||
document
|
||||
.getElementById("shared_tags-input")
|
||||
.addEventListener("keyup", onKeyPress);
|
||||
|
||||
return () => document.removeEventListener("keyup", onKeyPress);
|
||||
});
|
||||
@ -39,7 +41,7 @@ const TagDropdown = ({
|
||||
};
|
||||
|
||||
const onClickOutside = () => {
|
||||
document.getElementById("tags-input").blur();
|
||||
document.getElementById("shared_tags-input").blur();
|
||||
};
|
||||
|
||||
const addNewTag = () => {
|
||||
|
@ -50,7 +50,7 @@ const TagInput = ({
|
||||
return (
|
||||
<StyledTagInput className="set_room_params-input set_room_params-tag_input">
|
||||
<InputParam
|
||||
id={"tags-input"}
|
||||
id="shared_tags-input"
|
||||
title={`${t("Common:Tags")}:`}
|
||||
placeholder={t("TagsPlaceholder")}
|
||||
value={tagInput}
|
||||
|
@ -221,6 +221,7 @@ const ThirdPartyComboBox = ({
|
||||
<StyledStorageLocation isOpen={isOpen}>
|
||||
<div className="set_room_params-thirdparty">
|
||||
<div
|
||||
id="shared_third-party-storage_combobox"
|
||||
className="set_room_params-thirdparty-combobox"
|
||||
onClick={toggleIsOpen}
|
||||
>
|
||||
@ -235,6 +236,7 @@ const ThirdPartyComboBox = ({
|
||||
</div>
|
||||
|
||||
<Button
|
||||
id="shared_third-party-storage_connect"
|
||||
isDisabled={
|
||||
!storageLocation?.provider ||
|
||||
!!storageLocation?.thirdpartyAccount ||
|
||||
@ -262,7 +264,8 @@ const ThirdPartyComboBox = ({
|
||||
>
|
||||
{thirdparties.map((thirdparty) => (
|
||||
<DropDownItem
|
||||
className="dropdown-item"
|
||||
id={thirdparty.id}
|
||||
className={`dropdown-item ${thirdparty.className ?? ""}`}
|
||||
label={thirdparty.title}
|
||||
key={thirdparty.id}
|
||||
height={32}
|
||||
|
@ -90,6 +90,7 @@ const ThirdPartyStorage = ({
|
||||
return (
|
||||
<StyledThirdPartyStorage>
|
||||
<ToggleParam
|
||||
id="shared_third-party-storage-toggle"
|
||||
title={t("ThirdPartyStorageTitle")}
|
||||
description={t("ThirdPartyStorageDescription")}
|
||||
isChecked={storageLocation.isThirdparty}
|
||||
@ -188,6 +189,7 @@ export default inject(
|
||||
(item) =>
|
||||
item && {
|
||||
id: item[0],
|
||||
className: `storage_${item[0].toLowerCase()}`,
|
||||
providerKey: item[0],
|
||||
isOauth: item.length > 1 && item[0] !== "WebDav",
|
||||
oauthHref: item.length > 1 && item[0] !== "WebDav" ? item[1] : "",
|
||||
|
@ -159,6 +159,7 @@ const DeleteDialogComponent = (props) => {
|
||||
</ModalDialog.Body>
|
||||
<ModalDialog.Footer>
|
||||
<Button
|
||||
id="delete-file-modal_submit"
|
||||
key="OkButton"
|
||||
label={accessButtonLabel}
|
||||
size="normal"
|
||||
@ -171,6 +172,7 @@ const DeleteDialogComponent = (props) => {
|
||||
isDisabled={!selection.length}
|
||||
/>
|
||||
<Button
|
||||
id="delete-file-modal_cancel"
|
||||
key="CancelButton"
|
||||
label={t("Common:CancelButton")}
|
||||
size="normal"
|
||||
|
@ -77,6 +77,7 @@ const EmptyTrashDialogComponent = (props) => {
|
||||
</ModalDialog.Body>
|
||||
<ModalDialog.Footer>
|
||||
<Button
|
||||
id="empty-archive_delete-submit"
|
||||
key="OkButton"
|
||||
label={t("DeleteForeverButton")}
|
||||
size="normal"
|
||||
@ -86,6 +87,7 @@ const EmptyTrashDialogComponent = (props) => {
|
||||
scale
|
||||
/>
|
||||
<Button
|
||||
id="empty-archive_delete-cancel"
|
||||
key="CancelButton"
|
||||
label={t("Common:CancelButton")}
|
||||
size="normal"
|
||||
|
@ -129,6 +129,7 @@ class SendInviteDialogComponent extends React.Component {
|
||||
</ModalDialog.Body>
|
||||
<ModalDialog.Footer>
|
||||
<Button
|
||||
id="send-inite-again-modal_submit"
|
||||
label={t("Common:SendButton")}
|
||||
size="normal"
|
||||
scale
|
||||
@ -138,6 +139,7 @@ class SendInviteDialogComponent extends React.Component {
|
||||
isDisabled={!userIds.length}
|
||||
/>
|
||||
<Button
|
||||
id="send-inite-again-modal_cancel"
|
||||
label={t("Common:CancelButton")}
|
||||
size="normal"
|
||||
scale
|
||||
|
@ -134,6 +134,7 @@ const SelectionPanelBody = ({
|
||||
|
||||
<div>
|
||||
<Button
|
||||
id="select-file-modal-submit"
|
||||
theme={theme}
|
||||
className="select-file-modal-dialog-buttons-save"
|
||||
primary
|
||||
@ -153,6 +154,7 @@ const SelectionPanelBody = ({
|
||||
isLoading={isDisableTree}
|
||||
/>
|
||||
<Button
|
||||
id="select-file-modal-cancel"
|
||||
theme={theme}
|
||||
className="modal-dialog-button"
|
||||
size="normal"
|
||||
|
@ -159,7 +159,7 @@ const SectionHeaderContent = (props) => {
|
||||
getHeaderMenu,
|
||||
cbMenuItems,
|
||||
getCheckboxItemLabel,
|
||||
|
||||
getMenuItemId,
|
||||
setInfoPanelIsVisible,
|
||||
isInfoPanelVisible,
|
||||
isOwner,
|
||||
@ -186,8 +186,10 @@ const SectionHeaderContent = (props) => {
|
||||
<>
|
||||
{cbMenuItems.map((key) => {
|
||||
const label = getCheckboxItemLabel(t, key);
|
||||
const id = getMenuItemId(key);
|
||||
return (
|
||||
<DropDownItem
|
||||
id={id}
|
||||
key={key}
|
||||
label={label}
|
||||
data-key={key}
|
||||
@ -226,7 +228,7 @@ const SectionHeaderContent = (props) => {
|
||||
const getContextOptions = () => {
|
||||
return [
|
||||
isOwner && {
|
||||
id: "main-button_administrator",
|
||||
id: "accounts-add_administrator",
|
||||
className: "main-button_drop-down",
|
||||
icon: "/static/images/person.admin.react.svg",
|
||||
label: t("Common:DocSpaceAdmin"),
|
||||
@ -235,7 +237,7 @@ const SectionHeaderContent = (props) => {
|
||||
key: "administrator",
|
||||
},
|
||||
{
|
||||
id: "main-button_manager",
|
||||
id: "accounts-add_manager",
|
||||
className: "main-button_drop-down",
|
||||
icon: "/static/images/person.manager.react.svg",
|
||||
label: t("Common:RoomAdmin"),
|
||||
@ -244,7 +246,7 @@ const SectionHeaderContent = (props) => {
|
||||
key: "manager",
|
||||
},
|
||||
{
|
||||
id: "main-button_user",
|
||||
id: "accounts-add_user",
|
||||
className: "main-button_drop-down",
|
||||
icon: "/static/images/person.user.react.svg",
|
||||
label: t("Common:User"),
|
||||
@ -257,7 +259,7 @@ const SectionHeaderContent = (props) => {
|
||||
isSeparator: true,
|
||||
},
|
||||
{
|
||||
id: "main-button_invite-again",
|
||||
id: "accounts-add_invite-again",
|
||||
className: "main-button_drop-down",
|
||||
icon: "/static/images/invite.again.react.svg",
|
||||
label: t("LblInviteAgain"),
|
||||
@ -296,6 +298,7 @@ const SectionHeaderContent = (props) => {
|
||||
{t("Accounts")}
|
||||
</Headline>
|
||||
<ContextMenuButton
|
||||
id="header_add-button"
|
||||
className="action-button"
|
||||
directionX="left"
|
||||
title={t("Common:Actions")}
|
||||
@ -314,6 +317,7 @@ const SectionHeaderContent = (props) => {
|
||||
) && (
|
||||
<div className="info-panel-toggle-bg">
|
||||
<IconButton
|
||||
id="info-panel-toggle--open"
|
||||
className="info-panel-toggle"
|
||||
iconName="images/panel.react.svg"
|
||||
size="16"
|
||||
@ -349,6 +353,7 @@ export default withRouter(
|
||||
isHeaderIndeterminate,
|
||||
isHeaderChecked,
|
||||
cbMenuItems,
|
||||
getMenuItemId,
|
||||
getCheckboxItemLabel,
|
||||
} = headerMenuStore;
|
||||
|
||||
@ -361,6 +366,7 @@ export default withRouter(
|
||||
isHeaderChecked,
|
||||
getHeaderMenu,
|
||||
cbMenuItems,
|
||||
getMenuItemId,
|
||||
getCheckboxItemLabel,
|
||||
setInfoPanelIsVisible,
|
||||
isInfoPanelVisible,
|
||||
|
@ -73,11 +73,43 @@ class DetailsHelper {
|
||||
getPropertyList = () => {
|
||||
return this.getNeededProperties().map((propertyId) => ({
|
||||
id: propertyId,
|
||||
className: this.getPropertyClassName(propertyId),
|
||||
title: this.getPropertyTitle(propertyId),
|
||||
content: this.getPropertyContent(propertyId),
|
||||
}));
|
||||
};
|
||||
|
||||
getPropertyClassName = (propertyId) => {
|
||||
switch (propertyId) {
|
||||
case "Owner":
|
||||
return "info_details_owner";
|
||||
case "Location":
|
||||
return "info_details_location";
|
||||
case "Type":
|
||||
return "info_details_type";
|
||||
case "Storage Type":
|
||||
return "info_details_storage-type";
|
||||
case "File extension":
|
||||
return "info_details_file-extension";
|
||||
case "Content":
|
||||
return "info_details_content";
|
||||
case "Size":
|
||||
return "info_details_size";
|
||||
case "Date modified":
|
||||
return "info_details_date_modified";
|
||||
case "Last modified by":
|
||||
return "info_details_last-modified-by";
|
||||
case "Creation date":
|
||||
return "info_details_creation-date";
|
||||
case "Versions":
|
||||
return "info_details_versions";
|
||||
case "Comments":
|
||||
return "info_details_comments";
|
||||
case "Tags":
|
||||
return "info_details_tags";
|
||||
}
|
||||
};
|
||||
|
||||
getNeededProperties = () => {
|
||||
return (this.item.isRoom
|
||||
? [
|
||||
|
@ -0,0 +1,37 @@
|
||||
import moment from "moment";
|
||||
|
||||
import { LANGUAGE } from "@docspace/common/constants";
|
||||
import { getCookie } from "@docspace/common/utils";
|
||||
|
||||
export const getRelativeDateDay = (t, date) => {
|
||||
moment.locale(getCookie(LANGUAGE));
|
||||
|
||||
const given = moment(date);
|
||||
|
||||
const now = moment();
|
||||
const weekAgo = moment().subtract(1, "week");
|
||||
const halfYearAgo = moment().subtract(6, "month");
|
||||
|
||||
if (given.isAfter(weekAgo)) {
|
||||
if (now.weekday() === given.weekday()) return t("Common:Today");
|
||||
if (now.weekday() - 1 === given.weekday()) return t("Common:Yesterday");
|
||||
|
||||
const weekday = moment.weekdays(given.weekday());
|
||||
return weekday.charAt(0).toUpperCase() + weekday.slice(1);
|
||||
}
|
||||
|
||||
if (given.isBetween(halfYearAgo, weekAgo)) {
|
||||
const shortDate = given.format("MMMM D");
|
||||
return shortDate.charAt(0).toUpperCase() + shortDate.slice(1);
|
||||
}
|
||||
|
||||
const longDate = given.format("MMMM D, YYYY");
|
||||
return longDate.charAt(0).toUpperCase() + longDate.slice(1);
|
||||
};
|
||||
|
||||
export const getDateTime = (date) => {
|
||||
moment.locale(getCookie(LANGUAGE));
|
||||
|
||||
const given = moment(date);
|
||||
return given.format("LT");
|
||||
};
|
@ -69,16 +69,13 @@ const InfoPanelBodyContent = ({
|
||||
if (isAccounts) return viewHelper.AccountsView();
|
||||
|
||||
switch (isRooms ? roomsView : fileView) {
|
||||
case "members": {
|
||||
case "info_members":
|
||||
return viewHelper.MembersView();
|
||||
}
|
||||
case "history": {
|
||||
case "info_history":
|
||||
return viewHelper.HistoryView();
|
||||
}
|
||||
case "details": {
|
||||
case "info_details":
|
||||
return viewHelper.DetailsView();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
|
@ -4,9 +4,9 @@ import { Base } from "@docspace/components/themes";
|
||||
import { mobile } from "@docspace/components/utils/device";
|
||||
|
||||
const StyledInfoPanelBody = styled.div`
|
||||
padding: 0 3px 0 20px;
|
||||
padding: 80px 3px 0 20px;
|
||||
@media ${mobile} {
|
||||
padding: 0 8px 0 16px;
|
||||
padding: 80px 8px 0 16px;
|
||||
}
|
||||
height: auto;
|
||||
background-color: ${(props) => props.theme.infoPanel.backgroundColor};
|
||||
@ -26,13 +26,24 @@ const StyledInfoPanelBody = styled.div`
|
||||
`;
|
||||
|
||||
const StyledTitle = styled.div`
|
||||
position: fixed;
|
||||
margin-top: -80px;
|
||||
margin-left: -20px;
|
||||
width: calc(100% - 40px);
|
||||
padding: 24px 0 24px 20px;
|
||||
background: ${(props) => props.theme.infoPanel.backgroundColor};
|
||||
z-index: 100;
|
||||
|
||||
@media ${mobile} {
|
||||
width: calc(100% - 32px);
|
||||
padding: 24px 0 24px 16px;
|
||||
}
|
||||
|
||||
display: flex;
|
||||
flex-wrap: no-wrap;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
padding: 24px 0;
|
||||
|
||||
${(props) =>
|
||||
props.withBottomBorder &&
|
||||
|
@ -9,6 +9,11 @@ const StyledHistoryList = styled.div`
|
||||
`;
|
||||
|
||||
const StyledHistorySubtitle = styled.div`
|
||||
position: sticky;
|
||||
background: ${(props) => props.theme.infoPanel.backgroundColor};
|
||||
top: 80px;
|
||||
z-index: 100;
|
||||
|
||||
padding: 8px 0 12px;
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
@ -46,7 +51,11 @@ const StyledHistoryBlock = styled.div`
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 16px 0;
|
||||
border-bottom: ${(props) => `solid 1px ${props.theme.infoPanel.borderColor}`};
|
||||
|
||||
${({ withBottomDivider, theme }) =>
|
||||
withBottomDivider
|
||||
? ` border-bottom: solid 1px ${theme.infoPanel.borderColor}; `
|
||||
: ` margin-bottom: 12px; `}
|
||||
|
||||
.avatar {
|
||||
min-width: 32px;
|
||||
|
@ -71,7 +71,11 @@ const AccountsItemTitle = ({
|
||||
)}
|
||||
</div>
|
||||
{!!contextOptions.length && (
|
||||
<ContextMenuButton className="context-button" getData={getData} />
|
||||
<ContextMenuButton
|
||||
id="info-accounts-options"
|
||||
className="context-button"
|
||||
getData={getData}
|
||||
/>
|
||||
)}
|
||||
</StyledAccountsItemTitle>
|
||||
);
|
||||
|
@ -71,6 +71,7 @@ const ItemContextOptions = ({
|
||||
/>
|
||||
{options?.length > 0 && (
|
||||
<ContextMenuButton
|
||||
id="info-options"
|
||||
className="expandButton"
|
||||
title={"Show item actions"}
|
||||
onClick={onContextMenu}
|
||||
|
@ -35,7 +35,7 @@ const ItemTitle = ({
|
||||
const filesItemSelection =
|
||||
isRooms &&
|
||||
!isSeveralItems &&
|
||||
roomsView === "members" &&
|
||||
roomsView === "info_members" &&
|
||||
!selection.isRoom &&
|
||||
!!selectionParentRoom
|
||||
? selectionParentRoom
|
||||
|
@ -58,18 +58,21 @@ const Accounts = ({
|
||||
const options = [];
|
||||
|
||||
const adminOption = {
|
||||
id: "info-account-type_docspace-admin",
|
||||
key: "admin",
|
||||
title: t("Common:DocSpaceAdmin"),
|
||||
label: t("Common:DocSpaceAdmin"),
|
||||
action: "admin",
|
||||
};
|
||||
const managerOption = {
|
||||
id: "info-account-type_room-admin",
|
||||
key: "manager",
|
||||
title: t("Common:RoomAdmin"),
|
||||
label: t("Common:RoomAdmin"),
|
||||
action: "manager",
|
||||
};
|
||||
const userOption = {
|
||||
id: "info-account-type_user",
|
||||
key: "user",
|
||||
title: t("Common:User"),
|
||||
label: t("Common:User"),
|
||||
@ -99,6 +102,7 @@ const Accounts = ({
|
||||
|
||||
const combobox = (
|
||||
<ComboBox
|
||||
id="info-account-type-select"
|
||||
className="type-combobox"
|
||||
selectedOption={
|
||||
typesOptions.find((option) => option.key === role) || {}
|
||||
|
@ -85,7 +85,11 @@ const Details = ({
|
||||
<StyledProperties>
|
||||
{itemProperties.map((property) => {
|
||||
return (
|
||||
<div key={property.title} className="property">
|
||||
<div
|
||||
id={property.id}
|
||||
key={property.title}
|
||||
className={`property ${property.className}`}
|
||||
>
|
||||
<Text className="property-title">{property.title}</Text>
|
||||
{property.content}
|
||||
</div>
|
||||
|
@ -0,0 +1,93 @@
|
||||
import React from "react";
|
||||
|
||||
import Avatar from "@docspace/components/avatar";
|
||||
import Text from "@docspace/components/text";
|
||||
import HistoryBlockMessage from "./HistoryBlockMessage";
|
||||
import HistoryBlockItemList from "./HistoryBlockItemList";
|
||||
import HistoryBlockUser from "./HistoryBlockUser";
|
||||
import { FeedItemTypes } from "@docspace/common/constants";
|
||||
|
||||
import { StyledHistoryBlock } from "../../styles/history";
|
||||
import { getDateTime } from "../../helpers/HistoryHelper";
|
||||
|
||||
const HistoryBlock = ({
|
||||
t,
|
||||
selection,
|
||||
feed,
|
||||
selectedFolder,
|
||||
selectionParentRoom,
|
||||
getInfoPanelItemIcon,
|
||||
checkAndOpenLocationAction,
|
||||
openUser,
|
||||
isVisitor,
|
||||
isLastEntity,
|
||||
}) => {
|
||||
const { target, initiator, json, groupedFeeds } = feed;
|
||||
|
||||
const isUserAction = json.Item === FeedItemTypes.User && target;
|
||||
const isItemAction =
|
||||
json.Item === FeedItemTypes.File || json.Item === FeedItemTypes.Folder;
|
||||
|
||||
return (
|
||||
<StyledHistoryBlock
|
||||
withBottomDivider={!isLastEntity}
|
||||
isUserAction={isUserAction}
|
||||
>
|
||||
<Avatar
|
||||
role="user"
|
||||
className="avatar"
|
||||
size="min"
|
||||
source={
|
||||
initiator.avatarSmall ||
|
||||
(initiator.displayName
|
||||
? ""
|
||||
: initiator.email && "/static/images/@.react.svg")
|
||||
}
|
||||
userName={initiator.displayName}
|
||||
/>
|
||||
<div className="info">
|
||||
<div className="title">
|
||||
<Text className="name">{initiator.displayName}</Text>
|
||||
{initiator.isOwner && (
|
||||
<Text className="secondary-info">
|
||||
{t("Common:Owner").toLowerCase()}
|
||||
</Text>
|
||||
)}
|
||||
<Text className="date">{getDateTime(json.ModifiedDate)}</Text>
|
||||
</div>
|
||||
|
||||
<HistoryBlockMessage
|
||||
t={t}
|
||||
className="message"
|
||||
action={json}
|
||||
groupedActions={groupedFeeds}
|
||||
selection={selection}
|
||||
selectedFolder={selectedFolder}
|
||||
selectionParentRoom={selectionParentRoom}
|
||||
/>
|
||||
|
||||
{isItemAction && (
|
||||
<HistoryBlockItemList
|
||||
t={t}
|
||||
items={[json, ...groupedFeeds]}
|
||||
getInfoPanelItemIcon={getInfoPanelItemIcon}
|
||||
checkAndOpenLocationAction={checkAndOpenLocationAction}
|
||||
/>
|
||||
)}
|
||||
|
||||
{isUserAction &&
|
||||
[target, ...groupedFeeds].map((user, i) => (
|
||||
<HistoryBlockUser
|
||||
isVisitor={isVisitor}
|
||||
key={user.id}
|
||||
user={user}
|
||||
withComma={i !== groupedFeeds.length}
|
||||
openUser={openUser}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</StyledHistoryBlock>
|
||||
);
|
||||
};
|
||||
|
||||
export default HistoryBlock;
|
@ -2,25 +2,14 @@ import React, { useState, useEffect, useRef } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
|
||||
import {
|
||||
StyledHistoryBlock,
|
||||
StyledHistoryList,
|
||||
StyledHistorySubtitle,
|
||||
} from "../../styles/history";
|
||||
import { StyledHistoryList, StyledHistorySubtitle } from "../../styles/history";
|
||||
|
||||
import Avatar from "@docspace/components/avatar";
|
||||
import Text from "@docspace/components/text";
|
||||
import { parseAndFormatDate } from "../../helpers/DetailsHelper";
|
||||
import HistoryBlockMessage from "./HistoryBlockMessage";
|
||||
import HistoryBlockItemList from "./HistoryBlockItemList";
|
||||
import Loaders from "@docspace/common/components/Loaders";
|
||||
import HistoryBlockUser from "./HistoryBlockUser";
|
||||
import { FeedItemTypes } from "@docspace/common/constants";
|
||||
import { getRelativeDateDay } from "./../../helpers/HistoryHelper";
|
||||
import HistoryBlock from "./HistoryBlock";
|
||||
|
||||
const History = ({
|
||||
t,
|
||||
personal,
|
||||
culture,
|
||||
selection,
|
||||
selectedFolder,
|
||||
selectionParentRoom,
|
||||
@ -59,9 +48,11 @@ const History = ({
|
||||
|
||||
const parseHistoryJSON = (fetchedHistory) => {
|
||||
let feeds = fetchedHistory.feeds;
|
||||
let newFeeds = [];
|
||||
let parsedFeeds = [];
|
||||
|
||||
for (let i = 0; i < feeds.length; i++) {
|
||||
const feedsJSON = JSON.parse(feeds[i].json);
|
||||
const feedDay = getRelativeDateDay(t, feeds[i].modifiedDate);
|
||||
|
||||
let newGroupedFeeds = [];
|
||||
if (feeds[i].groupedFeeds) {
|
||||
@ -74,14 +65,26 @@ const History = ({
|
||||
);
|
||||
}
|
||||
|
||||
newFeeds.push({
|
||||
if (parsedFeeds.length && parsedFeeds.at(-1).day === feedDay)
|
||||
parsedFeeds.at(-1).feeds.push({
|
||||
...feeds[i],
|
||||
json: feedsJSON,
|
||||
groupedFeeds: newGroupedFeeds,
|
||||
});
|
||||
else
|
||||
parsedFeeds.push({
|
||||
day: feedDay,
|
||||
feeds: [
|
||||
{
|
||||
...feeds[i],
|
||||
json: feedsJSON,
|
||||
groupedFeeds: newGroupedFeeds,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
return { ...fetchedHistory, feeds: newFeeds };
|
||||
return { ...fetchedHistory, feedsByDays: parsedFeeds };
|
||||
};
|
||||
|
||||
useEffect(async () => {
|
||||
@ -101,76 +104,24 @@ const History = ({
|
||||
return (
|
||||
<>
|
||||
<StyledHistoryList>
|
||||
<StyledHistorySubtitle>{t("RecentActivities")}</StyledHistorySubtitle>
|
||||
|
||||
{history.feeds.map((feed) => (
|
||||
<StyledHistoryBlock
|
||||
{history.feedsByDays.map(({ day, feeds }) => [
|
||||
<StyledHistorySubtitle key={day}>{day}</StyledHistorySubtitle>,
|
||||
...feeds.map((feed, i) => (
|
||||
<HistoryBlock
|
||||
key={feed.json.Id}
|
||||
isUserAction={feed.json.Item === FeedItemTypes.User && feed.target}
|
||||
>
|
||||
<Avatar
|
||||
role="user"
|
||||
className="avatar"
|
||||
size="min"
|
||||
source={
|
||||
feed.initiator.avatarSmall ||
|
||||
(feed.initiator.displayName
|
||||
? ""
|
||||
: feed.initiator.email && "/static/images/@.react.svg")
|
||||
}
|
||||
userName={feed.initiator.displayName}
|
||||
/>
|
||||
<div className="info">
|
||||
<div className="title">
|
||||
<Text className="name">{feed.initiator.displayName}</Text>
|
||||
{feed.initiator.isOwner && (
|
||||
<Text className="secondary-info">
|
||||
{t("Common:Owner").toLowerCase()}
|
||||
</Text>
|
||||
)}
|
||||
<Text className="date">
|
||||
{parseAndFormatDate(
|
||||
feed.json.ModifiedDate,
|
||||
personal,
|
||||
culture
|
||||
)}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<HistoryBlockMessage
|
||||
t={t}
|
||||
className="message"
|
||||
action={feed.json}
|
||||
groupedActions={feed.groupedFeeds}
|
||||
feed={feed}
|
||||
selection={selection}
|
||||
selectedFolder={selectedFolder}
|
||||
selectionParentRoom={selectionParentRoom}
|
||||
/>
|
||||
|
||||
{(feed.json.Item === FeedItemTypes.File ||
|
||||
feed.json.Item === FeedItemTypes.Folder) && (
|
||||
<HistoryBlockItemList
|
||||
t={t}
|
||||
items={[feed.json, ...feed.groupedFeeds]}
|
||||
getInfoPanelItemIcon={getInfoPanelItemIcon}
|
||||
checkAndOpenLocationAction={checkAndOpenLocationAction}
|
||||
/>
|
||||
)}
|
||||
|
||||
{feed.json.Item === FeedItemTypes.User &&
|
||||
feed.target &&
|
||||
[feed.target, ...feed.groupedFeeds].map((user, i) => (
|
||||
<HistoryBlockUser
|
||||
isVisitor={isVisitor}
|
||||
key={user.id}
|
||||
user={user}
|
||||
withComma={i !== feed.groupedFeeds.length}
|
||||
openUser={openUser}
|
||||
isVisitor={isVisitor}
|
||||
isLastEntity={i === feeds.length - 1}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</StyledHistoryBlock>
|
||||
))}
|
||||
)),
|
||||
])}
|
||||
</StyledHistoryList>
|
||||
</>
|
||||
);
|
||||
|
@ -130,6 +130,7 @@ const Members = ({
|
||||
</Text>
|
||||
{canInviteUserInRoomAbility && (
|
||||
<IconButton
|
||||
id="info_add-user"
|
||||
className={"icon"}
|
||||
title={t("Common:AddUsers")}
|
||||
iconName="/static/images/person+.react.svg"
|
||||
|
@ -47,27 +47,27 @@ const InfoPanelHeaderContent = (props) => {
|
||||
|
||||
const closeInfoPanel = () => setIsVisible(false);
|
||||
|
||||
const setMembers = () => setView("members");
|
||||
const setHistory = () => setView("history");
|
||||
const setDetails = () => setView("details");
|
||||
const setMembers = () => setView("info_members");
|
||||
const setHistory = () => setView("info_history");
|
||||
const setDetails = () => setView("info_details");
|
||||
|
||||
const isArchiveRoot = rootFolderType === FolderType.Archive;
|
||||
|
||||
const submenuData = [
|
||||
{
|
||||
id: "members",
|
||||
id: "info_members",
|
||||
name: t("InfoPanel:SubmenuMembers"),
|
||||
onClick: setMembers,
|
||||
content: null,
|
||||
},
|
||||
{
|
||||
id: "history",
|
||||
id: "info_history",
|
||||
name: t("InfoPanel:SubmenuHistory"),
|
||||
onClick: setHistory,
|
||||
content: null,
|
||||
},
|
||||
{
|
||||
id: "details",
|
||||
id: "info_details",
|
||||
name: t("InfoPanel:SubmenuDetails"),
|
||||
onClick: setDetails,
|
||||
content: null,
|
||||
@ -100,6 +100,7 @@ const InfoPanelHeaderContent = (props) => {
|
||||
{!isTablet && (
|
||||
<div className="info-panel-toggle-bg">
|
||||
<IconButton
|
||||
id="info-panel-toggle--close"
|
||||
className="info-panel-toggle"
|
||||
iconName="images/panel.react.svg"
|
||||
size="16"
|
||||
|
@ -136,35 +136,41 @@ class SectionHeaderContent extends React.Component {
|
||||
]
|
||||
: [
|
||||
{
|
||||
id: "personal_new-documnet",
|
||||
key: "new-document",
|
||||
label: t("NewDocument"),
|
||||
onClick: this.createDocument,
|
||||
icon: "images/actions.documents.react.svg",
|
||||
},
|
||||
{
|
||||
id: "personal_new-spreadsheet",
|
||||
key: "new-spreadsheet",
|
||||
label: t("NewSpreadsheet"),
|
||||
onClick: this.createSpreadsheet,
|
||||
icon: "images/spreadsheet.react.svg",
|
||||
},
|
||||
{
|
||||
id: "personal_new-presentation",
|
||||
key: "new-presentation",
|
||||
label: t("NewPresentation"),
|
||||
onClick: this.createPresentation,
|
||||
icon: "images/actions.presentation.react.svg",
|
||||
},
|
||||
{
|
||||
id: "personal_form-template",
|
||||
icon: "images/form.react.svg",
|
||||
label: t("Translations:NewForm"),
|
||||
key: "new-form-base",
|
||||
items: [
|
||||
{
|
||||
id: "personal_template_black",
|
||||
key: "new-form",
|
||||
label: t("Translations:SubNewForm"),
|
||||
icon: "images/form.blank.react.svg",
|
||||
onClick: this.createForm,
|
||||
},
|
||||
{
|
||||
id: "personal_template_new-form-file",
|
||||
key: "new-form-file",
|
||||
label: t("Translations:SubNewFormFile"),
|
||||
icon: "images/form.file.react.svg",
|
||||
@ -172,6 +178,7 @@ class SectionHeaderContent extends React.Component {
|
||||
disabled: isPrivacyFolder,
|
||||
},
|
||||
{
|
||||
id: "personal_template_oforms-gallery",
|
||||
key: "oforms-gallery",
|
||||
label: t("Common:OFORMsGallery"),
|
||||
icon: "images/form.gallery.react.svg",
|
||||
@ -181,6 +188,7 @@ class SectionHeaderContent extends React.Component {
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "personal_new-folder",
|
||||
key: "new-folder",
|
||||
label: t("NewFolder"),
|
||||
onClick: this.createFolder,
|
||||
@ -355,6 +363,7 @@ class SectionHeaderContent extends React.Component {
|
||||
if (isArchiveFolder) {
|
||||
return [
|
||||
{
|
||||
id: "header_option_empty-archive",
|
||||
key: "empty-archive",
|
||||
label: t("ArchiveAction"),
|
||||
onClick: this.onEmptyTrashAction,
|
||||
@ -362,6 +371,7 @@ class SectionHeaderContent extends React.Component {
|
||||
icon: "images/clear.trash.react.svg",
|
||||
},
|
||||
{
|
||||
id: "header_option_restore-all",
|
||||
key: "restore-all",
|
||||
label: t("RestoreAll"),
|
||||
onClick: this.onRestoreAllArchiveAction,
|
||||
@ -373,6 +383,7 @@ class SectionHeaderContent extends React.Component {
|
||||
|
||||
return [
|
||||
{
|
||||
id: "header_option_sharing-settings",
|
||||
key: "sharing-settings",
|
||||
label: t("SharingPanel:SharingSettingsTitle"),
|
||||
onClick: this.onOpenSharingPanel,
|
||||
@ -380,6 +391,7 @@ class SectionHeaderContent extends React.Component {
|
||||
icon: "/static/images/share.react.svg",
|
||||
},
|
||||
{
|
||||
id: "header_option_link-portal-users",
|
||||
key: "link-portal-users",
|
||||
label: t("LinkForPortalUsers"),
|
||||
onClick: this.createLinkForPortalUsers,
|
||||
@ -387,6 +399,7 @@ class SectionHeaderContent extends React.Component {
|
||||
icon: "/static/images/invitation.link.react.svg",
|
||||
},
|
||||
{
|
||||
id: "header_option_empty-trash",
|
||||
key: "empty-trash",
|
||||
label: t("RecycleBinAction"),
|
||||
onClick: this.onEmptyTrashAction,
|
||||
@ -394,6 +407,7 @@ class SectionHeaderContent extends React.Component {
|
||||
icon: "images/clear.trash.react.svg",
|
||||
},
|
||||
{
|
||||
id: "header_option_restore-all",
|
||||
key: "restore-all",
|
||||
label: t("RestoreAll"),
|
||||
onClick: this.onRestoreAllAction,
|
||||
@ -401,6 +415,7 @@ class SectionHeaderContent extends React.Component {
|
||||
icon: "images/subtract.react.svg",
|
||||
},
|
||||
{
|
||||
id: "header_option_show-info",
|
||||
key: "show-info",
|
||||
label: t("InfoPanel:ViewDetails"),
|
||||
onClick: this.onShowInfo,
|
||||
@ -408,6 +423,7 @@ class SectionHeaderContent extends React.Component {
|
||||
icon: "/static/images/info.outline.react.svg",
|
||||
},
|
||||
{
|
||||
id: "header_option_reconnect-storage",
|
||||
key: "reconnect-storage",
|
||||
label: t("Common:ReconnectStorage"),
|
||||
icon: "images/reconnect.svg",
|
||||
@ -415,6 +431,7 @@ class SectionHeaderContent extends React.Component {
|
||||
disabled: !selectedFolder.providerKey || !isRoom,
|
||||
},
|
||||
{
|
||||
id: "header_option_edit-room",
|
||||
key: "edit-room",
|
||||
label: t("EditRoom"),
|
||||
icon: "images/settings.react.svg",
|
||||
@ -422,6 +439,7 @@ class SectionHeaderContent extends React.Component {
|
||||
disabled: !isRoom,
|
||||
},
|
||||
{
|
||||
id: "header_option_invite-users-to-room",
|
||||
key: "invite-users-to-room",
|
||||
label: t("InviteUsers"),
|
||||
icon: "/static/images/person.react.svg",
|
||||
@ -429,14 +447,21 @@ class SectionHeaderContent extends React.Component {
|
||||
disabled: !isRoom,
|
||||
},
|
||||
{
|
||||
id: "header_option_room-info",
|
||||
key: "room-info",
|
||||
label: t("Common:Info"),
|
||||
icon: "/static/images/info.outline.react.svg",
|
||||
onClick: this.onToggleInfoPanel,
|
||||
disabled: !isRoom,
|
||||
},
|
||||
{ key: "separator-2", isSeparator: true, disabled: isRecycleBinFolder },
|
||||
{
|
||||
id: "header_option_separator-2",
|
||||
key: "separator-2",
|
||||
isSeparator: true,
|
||||
disabled: isRecycleBinFolder,
|
||||
},
|
||||
{
|
||||
id: "header_option_archive-room",
|
||||
key: "archive-room",
|
||||
label: t("Archived"),
|
||||
icon: "/static/images/room.archive.svg",
|
||||
@ -446,6 +471,7 @@ class SectionHeaderContent extends React.Component {
|
||||
action: "archive",
|
||||
},
|
||||
{
|
||||
id: "header_option_download",
|
||||
key: "download",
|
||||
label: t("Common:Download"),
|
||||
onClick: this.downloadAction,
|
||||
@ -453,6 +479,7 @@ class SectionHeaderContent extends React.Component {
|
||||
icon: "images/download.react.svg",
|
||||
},
|
||||
{
|
||||
id: "header_option_move-to",
|
||||
key: "move-to",
|
||||
label: t("MoveTo"),
|
||||
onClick: this.onMoveAction,
|
||||
@ -460,6 +487,7 @@ class SectionHeaderContent extends React.Component {
|
||||
icon: "images/move.react.svg",
|
||||
},
|
||||
{
|
||||
id: "header_option_copy",
|
||||
key: "copy",
|
||||
label: t("Translations:Copy"),
|
||||
onClick: this.onCopyAction,
|
||||
@ -467,6 +495,7 @@ class SectionHeaderContent extends React.Component {
|
||||
icon: "/static/images/copy.react.svg",
|
||||
},
|
||||
{
|
||||
id: "header_option_rename",
|
||||
key: "rename",
|
||||
label: t("Rename"),
|
||||
onClick: this.renameAction,
|
||||
@ -474,11 +503,13 @@ class SectionHeaderContent extends React.Component {
|
||||
icon: "images/rename.react.svg",
|
||||
},
|
||||
{
|
||||
id: "header_option_separator-3",
|
||||
key: "separator-3",
|
||||
isSeparator: true,
|
||||
disabled: isDisabled,
|
||||
},
|
||||
{
|
||||
id: "header_option_delete",
|
||||
key: "delete",
|
||||
label: t("Common:Delete"),
|
||||
onClick: this.onDeleteAction,
|
||||
@ -506,14 +537,20 @@ class SectionHeaderContent extends React.Component {
|
||||
};
|
||||
|
||||
getMenuItems = () => {
|
||||
const { t, cbMenuItems, getCheckboxItemLabel } = this.props;
|
||||
|
||||
const {
|
||||
t,
|
||||
cbMenuItems,
|
||||
getCheckboxItemLabel,
|
||||
getCheckboxItemId,
|
||||
} = this.props;
|
||||
const checkboxOptions = (
|
||||
<>
|
||||
{cbMenuItems.map((key) => {
|
||||
const label = getCheckboxItemLabel(t, key);
|
||||
const id = getCheckboxItemId(key);
|
||||
return (
|
||||
<DropDownItem
|
||||
id={id}
|
||||
key={key}
|
||||
label={label}
|
||||
data-key={key}
|
||||
@ -700,6 +737,7 @@ export default inject(
|
||||
isThirdPartySelection,
|
||||
cbMenuItems,
|
||||
getCheckboxItemLabel,
|
||||
getCheckboxItemId,
|
||||
isEmptyFilesList,
|
||||
getFolderInfo,
|
||||
setBufferSelection,
|
||||
@ -817,6 +855,7 @@ export default inject(
|
||||
getHeaderMenu,
|
||||
backToParentFolder,
|
||||
getCheckboxItemLabel,
|
||||
getCheckboxItemId,
|
||||
setSelectFileDialogVisible,
|
||||
|
||||
isRecycleBinFolder,
|
||||
|
@ -159,6 +159,7 @@ const StyledAutoBackup = styled.div`
|
||||
}
|
||||
|
||||
.auto-backup_badge {
|
||||
height: 16px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
${(props) => !props.isEnableAuto && UnavailableStyles}
|
||||
|
@ -22,8 +22,6 @@ const Backup = ({
|
||||
return (
|
||||
<>
|
||||
<HelpButton
|
||||
displayType="auto"
|
||||
place="bottom"
|
||||
iconName={"/static/images/help.react.svg"}
|
||||
tooltipContent={
|
||||
<>
|
||||
|
@ -39,6 +39,7 @@ class AccountsContextOptionsStore {
|
||||
|
||||
case "profile":
|
||||
return {
|
||||
id: "option_profile",
|
||||
key: option,
|
||||
icon: "/static/images/profile.react.svg",
|
||||
label: t("Common:Profile"),
|
||||
@ -47,6 +48,7 @@ class AccountsContextOptionsStore {
|
||||
|
||||
case "change-name":
|
||||
return {
|
||||
id: "option_change-name",
|
||||
key: option,
|
||||
icon: "images/pencil.react.svg",
|
||||
label: t("PeopleTranslations:NameChangeButton"),
|
||||
@ -54,6 +56,7 @@ class AccountsContextOptionsStore {
|
||||
};
|
||||
case "change-email":
|
||||
return {
|
||||
id: "option_change-email",
|
||||
key: option,
|
||||
icon: "images/change.mail.react.svg",
|
||||
label: t("PeopleTranslations:EmailChangeButton"),
|
||||
@ -61,6 +64,7 @@ class AccountsContextOptionsStore {
|
||||
};
|
||||
case "change-password":
|
||||
return {
|
||||
id: "option_change-password",
|
||||
key: option,
|
||||
icon: "images/change.security.react.svg",
|
||||
label: t("PeopleTranslations:PasswordChangeButton"),
|
||||
@ -68,6 +72,7 @@ class AccountsContextOptionsStore {
|
||||
};
|
||||
case "change-owner":
|
||||
return {
|
||||
id: "option_change-owner",
|
||||
key: option,
|
||||
icon: "/static/images/refresh.react.svg",
|
||||
label: t("Translations:OwnerChange"),
|
||||
@ -76,6 +81,7 @@ class AccountsContextOptionsStore {
|
||||
|
||||
case "enable":
|
||||
return {
|
||||
id: "option_enable",
|
||||
key: option,
|
||||
icon: "images/enable.react.svg",
|
||||
label: t("PeopleTranslations:EnableUserButton"),
|
||||
@ -83,6 +89,7 @@ class AccountsContextOptionsStore {
|
||||
};
|
||||
case "disable":
|
||||
return {
|
||||
id: "option_disable",
|
||||
key: option,
|
||||
icon: "images/remove.react.svg",
|
||||
label: t("PeopleTranslations:DisableUserButton"),
|
||||
@ -91,6 +98,7 @@ class AccountsContextOptionsStore {
|
||||
|
||||
case "reassign-data":
|
||||
return {
|
||||
id: "option_reassign-data",
|
||||
key: option,
|
||||
icon: "images/ressing_data.react.svg",
|
||||
label: t("PeopleTranslations:ReassignData"),
|
||||
@ -98,6 +106,7 @@ class AccountsContextOptionsStore {
|
||||
};
|
||||
case "delete-personal-data":
|
||||
return {
|
||||
id: "option_delete-personal-data",
|
||||
key: option,
|
||||
icon: "images/del_data.react.svg",
|
||||
label: t("PeopleTranslations:RemoveData"),
|
||||
@ -105,6 +114,7 @@ class AccountsContextOptionsStore {
|
||||
};
|
||||
case "delete-user":
|
||||
return {
|
||||
id: "option_delete-user",
|
||||
key: option,
|
||||
icon: "images/trash.react.svg",
|
||||
label: t("DeleteProfileEverDialog:DeleteUser"),
|
||||
@ -113,6 +123,7 @@ class AccountsContextOptionsStore {
|
||||
|
||||
case "details":
|
||||
return {
|
||||
id: "option_details",
|
||||
key: option,
|
||||
icon: "images/info.react.svg",
|
||||
label: t("Common:Info"),
|
||||
@ -121,6 +132,7 @@ class AccountsContextOptionsStore {
|
||||
|
||||
case "invite-again":
|
||||
return {
|
||||
id: "option_invite-again",
|
||||
key: option,
|
||||
icon: "/static/images/invite.again.react.svg",
|
||||
label: t("LblInviteAgain"),
|
||||
@ -128,6 +140,7 @@ class AccountsContextOptionsStore {
|
||||
};
|
||||
case "reset-auth":
|
||||
return {
|
||||
id: "option_reset-auth",
|
||||
key: option,
|
||||
icon: "images/restore.auth.react.svg",
|
||||
label: t("PeopleTranslations:ResetAuth"),
|
||||
|
@ -469,6 +469,7 @@ class ContextOptionsStore {
|
||||
|
||||
const blockAction = isCanWebEdit
|
||||
? {
|
||||
id: "option_block-unblock-version",
|
||||
key: "block-unblock-version",
|
||||
label: t("UnblockVersion"),
|
||||
icon: "/static/images/locked.react.svg",
|
||||
@ -486,6 +487,7 @@ class ContextOptionsStore {
|
||||
? onlyShowVersionHistory
|
||||
? [
|
||||
{
|
||||
id: "option_show-version-history",
|
||||
key: "show-version-history",
|
||||
label: t("ShowVersionHistory"),
|
||||
icon: "images/history.react.svg",
|
||||
@ -495,11 +497,13 @@ class ContextOptionsStore {
|
||||
]
|
||||
: [
|
||||
{
|
||||
id: "option_version",
|
||||
key: "version",
|
||||
label: t("VersionHistory"),
|
||||
icon: "images/history-finalized.react.svg",
|
||||
items: [
|
||||
{
|
||||
id: "option_finalize-version",
|
||||
key: "finalize-version",
|
||||
label: t("FinalizeVersion"),
|
||||
icon: "images/history-finalized.react.svg",
|
||||
@ -507,6 +511,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_version-history",
|
||||
key: "show-version-history",
|
||||
label: t("ShowVersionHistory"),
|
||||
icon: "images/history.react.svg",
|
||||
@ -519,6 +524,7 @@ class ContextOptionsStore {
|
||||
]
|
||||
: [
|
||||
{
|
||||
id: "option_finalize-version",
|
||||
key: "finalize-version",
|
||||
label: t("FinalizeVersion"),
|
||||
icon: "images/history-finalized.react.svg",
|
||||
@ -526,6 +532,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_version-history",
|
||||
key: "show-version-history",
|
||||
label: t("ShowVersionHistory"),
|
||||
icon: "images/history.react.svg",
|
||||
@ -539,11 +546,13 @@ class ContextOptionsStore {
|
||||
!isMobile && !isMobileUtils() && !isTabletUtils()
|
||||
? [
|
||||
{
|
||||
id: "option_move-or-copy",
|
||||
key: "move",
|
||||
label: t("MoveOrCopy"),
|
||||
icon: "/static/images/copy.react.svg",
|
||||
items: [
|
||||
{
|
||||
id: "option_move-to",
|
||||
key: "move-to",
|
||||
label: t("MoveTo"),
|
||||
icon: "images/move.react.svg",
|
||||
@ -551,6 +560,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_copy-to",
|
||||
key: "copy-to",
|
||||
label: t("Translations:Copy"),
|
||||
icon: "/static/images/copy.react.svg",
|
||||
@ -558,6 +568,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_create-copy",
|
||||
key: "copy",
|
||||
label: t("Common:Duplicate"),
|
||||
icon: "/static/images/duplicate.react.svg",
|
||||
@ -569,6 +580,7 @@ class ContextOptionsStore {
|
||||
]
|
||||
: [
|
||||
{
|
||||
id: "option_move-to",
|
||||
key: "move-to",
|
||||
label: t("MoveTo"),
|
||||
icon: "images/move.react.svg",
|
||||
@ -576,6 +588,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_copy-to",
|
||||
key: "copy-to",
|
||||
label: t("Translations:Copy"),
|
||||
icon: "/static/images/copy.react.svg",
|
||||
@ -583,6 +596,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_create-copy",
|
||||
key: "copy",
|
||||
label: t("Common:Duplicate"),
|
||||
icon: "/static/images/duplicate.react.svg",
|
||||
@ -593,6 +607,7 @@ class ContextOptionsStore {
|
||||
|
||||
const optionsModel = [
|
||||
{
|
||||
id: "option_select",
|
||||
key: "select",
|
||||
label: "Select",
|
||||
icon: "images/check-box.react.svg",
|
||||
@ -600,6 +615,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_open",
|
||||
key: "open",
|
||||
label: t("Open"),
|
||||
icon: "images/folder.react.svg",
|
||||
@ -607,6 +623,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_fill-form",
|
||||
key: "fill-form",
|
||||
label: t("Common:FillFormButton"),
|
||||
icon: "/static/images/form.fill.rect.svg",
|
||||
@ -614,6 +631,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_edit",
|
||||
key: "edit",
|
||||
label: t("Common:EditButton"),
|
||||
icon: "/static/images/access.edit.react.svg",
|
||||
@ -621,6 +639,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_preview",
|
||||
key: "preview",
|
||||
label: t("Preview"),
|
||||
icon: "/static/images/eye.react.svg",
|
||||
@ -628,6 +647,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_view",
|
||||
key: "view",
|
||||
label: t("Common:View"),
|
||||
icon: "/static/images/eye.react.svg",
|
||||
@ -635,6 +655,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_make-form",
|
||||
key: "make-form",
|
||||
label: t("Common:MakeForm"),
|
||||
icon: "/static/images/form.plus.react.svg",
|
||||
@ -646,6 +667,7 @@ class ContextOptionsStore {
|
||||
isSeparator: true,
|
||||
},
|
||||
{
|
||||
id: "option_reconnect-storage",
|
||||
key: "reconnect-storage",
|
||||
label: t("Common:ReconnectStorage"),
|
||||
icon: "images/reconnect.svg",
|
||||
@ -653,6 +675,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_edit-room",
|
||||
key: "edit-room",
|
||||
label: t("EditRoom"),
|
||||
icon: "images/settings.react.svg",
|
||||
@ -660,6 +683,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_invite-users-to-room",
|
||||
key: "invite-users-to-room",
|
||||
label: t("InviteUsers"),
|
||||
icon: "/static/images/person.react.svg",
|
||||
@ -668,6 +692,7 @@ class ContextOptionsStore {
|
||||
action: item.id,
|
||||
},
|
||||
{
|
||||
id: "option_room-info",
|
||||
key: "room-info",
|
||||
label: t("Common:Info"),
|
||||
icon: "/static/images/info.outline.react.svg",
|
||||
@ -675,6 +700,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_pin-room",
|
||||
key: "pin-room",
|
||||
label: t("Pin"),
|
||||
icon: "/static/images/pin.react.svg",
|
||||
@ -684,6 +710,7 @@ class ContextOptionsStore {
|
||||
action: "pin",
|
||||
},
|
||||
{
|
||||
id: "option_unpin-room",
|
||||
key: "unpin-room",
|
||||
label: t("Unpin"),
|
||||
icon: "/static/images/unpin.react.svg",
|
||||
@ -693,6 +720,7 @@ class ContextOptionsStore {
|
||||
action: "unpin",
|
||||
},
|
||||
{
|
||||
id: "option_sharing-settings",
|
||||
key: "sharing-settings",
|
||||
label: t("SharingPanel:SharingSettingsTitle"),
|
||||
icon: "/static/images/share.react.svg",
|
||||
@ -700,6 +728,7 @@ class ContextOptionsStore {
|
||||
disabled: !isShareable,
|
||||
},
|
||||
{
|
||||
id: "option_owner-change",
|
||||
key: "owner-change",
|
||||
label: t("Translations:OwnerChange"),
|
||||
icon: "images/file.actions.owner.react.svg",
|
||||
@ -707,6 +736,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_link-for-portal-users",
|
||||
key: "link-for-portal-users",
|
||||
label: t("LinkForPortalUsers"),
|
||||
icon: "/static/images/invitation.link.react.svg",
|
||||
@ -714,6 +744,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_send-by-email",
|
||||
key: "send-by-email",
|
||||
label: t("SendByEmail"),
|
||||
icon: "/static/images/mail.react.svg",
|
||||
@ -721,6 +752,7 @@ class ContextOptionsStore {
|
||||
},
|
||||
...versionActions,
|
||||
{
|
||||
id: "option_show-info",
|
||||
key: "show-info",
|
||||
label: t("Common:Info"),
|
||||
icon: "/static/images/info.outline.react.svg",
|
||||
@ -733,6 +765,7 @@ class ContextOptionsStore {
|
||||
isSeparator: true,
|
||||
},
|
||||
{
|
||||
id: "option_open-location",
|
||||
key: "open-location",
|
||||
label: t("OpenLocation"),
|
||||
icon: "images/folder.location.react.svg",
|
||||
@ -740,6 +773,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_mark-read",
|
||||
key: "mark-read",
|
||||
label: t("MarkRead"),
|
||||
icon: "images/tick.rounded.svg",
|
||||
@ -747,6 +781,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_mark-as-favorite",
|
||||
key: "mark-as-favorite",
|
||||
label: t("MarkAsFavorite"),
|
||||
icon: "images/favorites.react.svg",
|
||||
@ -756,6 +791,7 @@ class ContextOptionsStore {
|
||||
action: "mark",
|
||||
},
|
||||
{
|
||||
id: "option_remove-from-favorites",
|
||||
key: "remove-from-favorites",
|
||||
label: t("RemoveFromFavorites"),
|
||||
icon: "images/favorites.react.svg",
|
||||
@ -765,6 +801,7 @@ class ContextOptionsStore {
|
||||
action: "remove",
|
||||
},
|
||||
{
|
||||
id: "option_download",
|
||||
key: "download",
|
||||
label: t("Common:Download"),
|
||||
icon: "images/download.react.svg",
|
||||
@ -772,6 +809,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_download-as",
|
||||
key: "download-as",
|
||||
label: t("Translations:DownloadAs"),
|
||||
icon: "images/download-as.react.svg",
|
||||
@ -780,6 +818,7 @@ class ContextOptionsStore {
|
||||
},
|
||||
...moveActions,
|
||||
{
|
||||
id: "option_restore",
|
||||
key: "restore",
|
||||
label: t("Common:Restore"),
|
||||
icon: "images/move.react.svg",
|
||||
@ -787,6 +826,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_rename",
|
||||
key: "rename",
|
||||
label: t("Rename"),
|
||||
icon: "images/rename.react.svg",
|
||||
@ -798,6 +838,7 @@ class ContextOptionsStore {
|
||||
isSeparator: true,
|
||||
},
|
||||
{
|
||||
id: "option_unsubscribe",
|
||||
key: "unsubscribe",
|
||||
label: t("RemoveFromList"),
|
||||
icon: "images/remove.svg",
|
||||
@ -805,6 +846,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_change-thirdparty-info",
|
||||
key: "change-thirdparty-info",
|
||||
label: t("Translations:ThirdPartyInfo"),
|
||||
icon: "/static/images/access.edit.react.svg",
|
||||
@ -812,6 +854,7 @@ class ContextOptionsStore {
|
||||
disabled: false,
|
||||
},
|
||||
{
|
||||
id: "option_archive-room",
|
||||
key: "archive-room",
|
||||
label: t("Archived"),
|
||||
icon: "/static/images/room.archive.svg",
|
||||
@ -821,6 +864,7 @@ class ContextOptionsStore {
|
||||
action: "archive",
|
||||
},
|
||||
{
|
||||
id: "option_unarchive-room",
|
||||
key: "unarchive-room",
|
||||
label: t("Common:Restore"),
|
||||
icon: "images/subtract.react.svg",
|
||||
@ -830,6 +874,7 @@ class ContextOptionsStore {
|
||||
action: "unarchive",
|
||||
},
|
||||
{
|
||||
id: "option_delete",
|
||||
key: "delete",
|
||||
label: isRootThirdPartyFolder
|
||||
? t("Common:Disconnect")
|
||||
|
@ -1072,7 +1072,6 @@ class FilesActionStore {
|
||||
openLocationAction = async (locationId) => {
|
||||
this.filesStore.setBufferSelection(null);
|
||||
const files = await this.filesStore.fetchFiles(locationId, null);
|
||||
console.log(files);
|
||||
return files;
|
||||
};
|
||||
|
||||
@ -1439,6 +1438,7 @@ class FilesActionStore {
|
||||
if (!isTablet() && !isMobile) return null;
|
||||
else
|
||||
return {
|
||||
id: "menu-show-info",
|
||||
key: "show-info",
|
||||
label: t("Common:Info"),
|
||||
iconUrl: "/static/images/info.outline.react.svg",
|
||||
@ -1448,6 +1448,7 @@ class FilesActionStore {
|
||||
if (!this.isAvailableOption("copy")) return null;
|
||||
else
|
||||
return {
|
||||
id: "menu-copy",
|
||||
label: t("Translations:Copy"),
|
||||
onClick: () => setCopyPanelVisible(true),
|
||||
iconUrl: "/static/images/copyTo.react.svg",
|
||||
@ -1457,6 +1458,7 @@ class FilesActionStore {
|
||||
if (!this.isAvailableOption("download")) return null;
|
||||
else
|
||||
return {
|
||||
id: "menu-download",
|
||||
label: t("Common:Download"),
|
||||
onClick: () =>
|
||||
this.downloadAction(
|
||||
@ -1469,6 +1471,7 @@ class FilesActionStore {
|
||||
if (!this.isAvailableOption("downloadAs")) return null;
|
||||
else
|
||||
return {
|
||||
id: "menu-download-as",
|
||||
label: t("Translations:DownloadAs"),
|
||||
onClick: () => setDownloadDialogVisible(true),
|
||||
iconUrl: "/static/images/downloadAs.react.svg",
|
||||
@ -1478,12 +1481,14 @@ class FilesActionStore {
|
||||
if (!this.isAvailableOption("moveTo")) return null;
|
||||
else
|
||||
return {
|
||||
id: "menu-move-to",
|
||||
label: t("MoveTo"),
|
||||
onClick: () => setMoveToPanelVisible(true),
|
||||
iconUrl: "/static/images/move.react.svg",
|
||||
};
|
||||
case "pin":
|
||||
return {
|
||||
id: "menu-pin",
|
||||
key: "pin",
|
||||
label: t("Pin"),
|
||||
iconUrl: "/static/images/pin.react.svg",
|
||||
@ -1492,6 +1497,7 @@ class FilesActionStore {
|
||||
};
|
||||
case "unpin":
|
||||
return {
|
||||
id: "menu-unpin",
|
||||
key: "unpin",
|
||||
label: t("Unpin"),
|
||||
iconUrl: "/static/images/unpin.react.svg",
|
||||
@ -1502,6 +1508,7 @@ class FilesActionStore {
|
||||
if (!this.isAvailableOption("archive")) return null;
|
||||
else
|
||||
return {
|
||||
id: "menu-archive",
|
||||
key: "archive",
|
||||
label: t("Archived"),
|
||||
iconUrl: "/static/images/room.archive.svg",
|
||||
@ -1512,6 +1519,7 @@ class FilesActionStore {
|
||||
if (!this.isAvailableOption("unarchive")) return null;
|
||||
else
|
||||
return {
|
||||
id: "menu-unarchive",
|
||||
key: "unarchive",
|
||||
label: t("Common:Restore"),
|
||||
iconUrl: "images/subtract.react.svg",
|
||||
@ -1522,6 +1530,7 @@ class FilesActionStore {
|
||||
if (!this.isAvailableOption("delete-room")) return null;
|
||||
else
|
||||
return {
|
||||
id: "menu-delete-room",
|
||||
label: t("Common:Delete"),
|
||||
onClick: () => this.deleteRooms(t),
|
||||
iconUrl: "/static/images/delete.react.svg",
|
||||
@ -1531,6 +1540,7 @@ class FilesActionStore {
|
||||
if (!this.isAvailableOption("delete")) return null;
|
||||
else
|
||||
return {
|
||||
id: "menu-delete",
|
||||
label: t("Common:Delete"),
|
||||
onClick: () => {
|
||||
if (this.settingsStore.confirmDelete) {
|
||||
@ -1700,6 +1710,7 @@ class FilesActionStore {
|
||||
.set("download", download)
|
||||
.set("downloadAs", downloadAs)
|
||||
.set("restore", {
|
||||
id: "menu-restore",
|
||||
label: t("Common:Restore"),
|
||||
onClick: () => setMoveToPanelVisible(true),
|
||||
iconUrl: "/static/images/move.react.svg",
|
||||
|
@ -2216,6 +2216,42 @@ class FilesStore {
|
||||
}
|
||||
};
|
||||
|
||||
getCheckboxItemId = (key) => {
|
||||
switch (key) {
|
||||
case "all":
|
||||
return "selected-all";
|
||||
case FilterType.FoldersOnly:
|
||||
return "selected-only-folders";
|
||||
case FilterType.DocumentsOnly:
|
||||
return "selected-only-documents";
|
||||
case FilterType.PresentationsOnly:
|
||||
return "selected-only-presentations";
|
||||
case FilterType.SpreadsheetsOnly:
|
||||
return "selected-only-spreadsheets";
|
||||
case FilterType.ImagesOnly:
|
||||
return "selected-only-images";
|
||||
case FilterType.MediaOnly:
|
||||
return "selected-only-media";
|
||||
case FilterType.ArchiveOnly:
|
||||
return "selected-only-archives";
|
||||
case FilterType.FilesOnly:
|
||||
return "selected-only-files";
|
||||
case `room-${RoomsType.FillingFormsRoom}`:
|
||||
return "selected-only-filling-form-rooms";
|
||||
case `room-${RoomsType.CustomRoom}`:
|
||||
return "selected-only-custom-room";
|
||||
case `room-${RoomsType.EditingRoom}`:
|
||||
return "selected-only-collaboration-rooms";
|
||||
case `room-${RoomsType.ReviewRoom}`:
|
||||
return "selected-only-review-rooms";
|
||||
case `room-${RoomsType.ReadOnlyRoom}`:
|
||||
return "selected-only-view-rooms";
|
||||
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
get sortedFiles() {
|
||||
const {
|
||||
extsConvertible,
|
||||
|
@ -35,7 +35,18 @@ class HeaderMenuStore {
|
||||
|
||||
return cbMenu;
|
||||
}
|
||||
|
||||
getMenuItemId = (item) => {
|
||||
switch (item) {
|
||||
case "active":
|
||||
return "selected_active";
|
||||
case "pending":
|
||||
return "selected_pending";
|
||||
case "disabled":
|
||||
return "selected_disabled";
|
||||
case "all":
|
||||
return "selected_all";
|
||||
}
|
||||
};
|
||||
getCheckboxItemLabel = (t, item) => {
|
||||
switch (item) {
|
||||
case "active":
|
||||
|
@ -193,7 +193,7 @@ class PeopleStore {
|
||||
const options = [];
|
||||
|
||||
const adminOption = {
|
||||
id: "group-menu_administrator",
|
||||
id: "menu_change-user_administrator",
|
||||
className: "group-menu_drop-down",
|
||||
label: t("Common:DocSpaceAdmin"),
|
||||
title: t("Common:DocSpaceAdmin"),
|
||||
@ -202,7 +202,7 @@ class PeopleStore {
|
||||
key: "administrator",
|
||||
};
|
||||
const managerOption = {
|
||||
id: "group-menu_manager",
|
||||
id: "menu_change-user_manager",
|
||||
className: "group-menu_drop-down",
|
||||
label: t("Common:RoomAdmin"),
|
||||
title: t("Common:RoomAdmin"),
|
||||
@ -211,7 +211,7 @@ class PeopleStore {
|
||||
key: "manager",
|
||||
};
|
||||
const userOption = {
|
||||
id: "group-menu_user",
|
||||
id: "menu_change-user_user",
|
||||
className: "group-menu_drop-down",
|
||||
label: t("Common:User"),
|
||||
title: t("Common:User"),
|
||||
@ -228,6 +228,7 @@ class PeopleStore {
|
||||
|
||||
const headerMenu = [
|
||||
{
|
||||
id: "menu-change-type",
|
||||
key: "change-user",
|
||||
label: t("ChangeUserTypeDialog:ChangeUserTypeButton"),
|
||||
disabled: !hasUsersToMakeEmployees,
|
||||
@ -236,6 +237,7 @@ class PeopleStore {
|
||||
options: options,
|
||||
},
|
||||
{
|
||||
id: "menu-info",
|
||||
key: "info",
|
||||
label: t("Common:Info"),
|
||||
disabled:
|
||||
@ -245,6 +247,7 @@ class PeopleStore {
|
||||
iconUrl: "images/info.react.svg",
|
||||
},
|
||||
{
|
||||
id: "menu-invite",
|
||||
key: "invite",
|
||||
label: t("Common:Invite"),
|
||||
disabled: !hasUsersToInvite,
|
||||
@ -252,6 +255,7 @@ class PeopleStore {
|
||||
iconUrl: "/static/images/invite.again.react.svg",
|
||||
},
|
||||
{
|
||||
id: "menu-enable",
|
||||
key: "enable",
|
||||
label: t("Common:Enable"),
|
||||
disabled: !hasUsersToActivate,
|
||||
@ -259,6 +263,7 @@ class PeopleStore {
|
||||
iconUrl: "images/enable.react.svg",
|
||||
},
|
||||
{
|
||||
id: "menu-disable",
|
||||
key: "disable",
|
||||
label: t("PeopleTranslations:DisableUserButton"),
|
||||
disabled: !hasUsersToDisable,
|
||||
@ -266,6 +271,7 @@ class PeopleStore {
|
||||
iconUrl: "images/disable.react.svg",
|
||||
},
|
||||
{
|
||||
id: "menu-delete",
|
||||
key: "delete",
|
||||
label: t("Common:Delete"),
|
||||
disabled: !hasUsersToRemove,
|
||||
|
@ -195,6 +195,7 @@ const Navigation = ({
|
||||
</StyledContainer>
|
||||
{infoPanelIsVisible && (
|
||||
<ToggleInfoPanelButton
|
||||
id="info-panel-toggle--open"
|
||||
isRootFolder={isRootFolder}
|
||||
toggleInfoPanel={toggleInfoPanel}
|
||||
isInfoPanelVisible={isInfoPanelVisible}
|
||||
|
@ -47,6 +47,9 @@ const StyledContainer = styled.div`
|
||||
width: 100%;
|
||||
grid-template-columns: ${(props) =>
|
||||
props.isRootFolder ? "auto 1fr" : "29px 1fr auto"};
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
`}
|
||||
`;
|
||||
|
||||
|
@ -125,6 +125,7 @@ const ControlButtons = ({
|
||||
)}
|
||||
{!personal && (
|
||||
<ContextMenuButton
|
||||
id="header_optional-button"
|
||||
zIndex={402}
|
||||
className="option-button"
|
||||
directionX="right"
|
||||
@ -147,6 +148,7 @@ const ControlButtons = ({
|
||||
<>
|
||||
{!isMobile && (
|
||||
<PlusButton
|
||||
id="header_add-button"
|
||||
className="add-button"
|
||||
getData={getContextOptionsPlus}
|
||||
withMenu={withMenu}
|
||||
|
@ -31,6 +31,7 @@ const PlusButton = (props) => {
|
||||
<IconButton
|
||||
onClick={onClick}
|
||||
iconName="images/plus.svg"
|
||||
id={props.id}
|
||||
size={15}
|
||||
isFill
|
||||
/>
|
||||
@ -50,6 +51,7 @@ PlusButton.propTypes = {
|
||||
className: PropTypes.string,
|
||||
getData: PropTypes.func.isRequired,
|
||||
onPlusClick: PropTypes.func,
|
||||
id: PropTypes.string,
|
||||
};
|
||||
|
||||
PlusButton.defaultProps = {
|
||||
|
@ -54,6 +54,7 @@ const ToggleInfoPanelButton = ({
|
||||
isRootFolder,
|
||||
isInfoPanelVisible,
|
||||
toggleInfoPanel,
|
||||
id,
|
||||
}) => {
|
||||
return (
|
||||
<StyledInfoPanelToggleWrapper
|
||||
@ -62,6 +63,7 @@ const ToggleInfoPanelButton = ({
|
||||
>
|
||||
<div className="info-panel-toggle-bg">
|
||||
<IconButton
|
||||
id={id}
|
||||
className="info-panel-toggle"
|
||||
iconName="images/panel.react.svg"
|
||||
size="16"
|
||||
|
@ -23,8 +23,8 @@ class InfoPanelStore {
|
||||
selection = null;
|
||||
selectionParentRoom = null;
|
||||
|
||||
roomsView = "details";
|
||||
fileView = "history";
|
||||
roomsView = "info_details";
|
||||
fileView = "info_history";
|
||||
|
||||
authStore = null;
|
||||
settingsStore = null;
|
||||
@ -54,7 +54,7 @@ class InfoPanelStore {
|
||||
|
||||
setView = (view) => {
|
||||
this.roomsView = view;
|
||||
this.fileView = view === "members" ? "history" : view;
|
||||
this.fileView = view === "info_members" ? "info_history" : view;
|
||||
};
|
||||
|
||||
// Selection helpers //
|
||||
|
@ -222,7 +222,7 @@ class ContextMenuButton extends React.Component {
|
||||
(item.label || item.icon || item.key) && (
|
||||
<DropDownItem
|
||||
{...item}
|
||||
id={item.key}
|
||||
id={item.id}
|
||||
key={item.key || index}
|
||||
onClick={this.onDropDownItemClick.bind(this, item)}
|
||||
/>
|
||||
|
@ -113,6 +113,7 @@ class LinkWithDropdown extends React.Component {
|
||||
const dropDownItem = data.map((item) => (
|
||||
<DropDownItem
|
||||
className="drop-down-item"
|
||||
id={item.key}
|
||||
key={item.key}
|
||||
{...item}
|
||||
onClick={this.onClickDropDownItem}
|
||||
|
@ -140,6 +140,7 @@ const GroupMenuItem = ({ item }) => {
|
||||
title,
|
||||
withDropDown,
|
||||
options,
|
||||
id,
|
||||
} = item;
|
||||
return (
|
||||
<>
|
||||
@ -148,6 +149,7 @@ const GroupMenuItem = ({ item }) => {
|
||||
) : (
|
||||
<>
|
||||
<StyledButton
|
||||
id={id}
|
||||
label={label}
|
||||
title={title || label}
|
||||
isDisabled={disabled}
|
||||
|
@ -36,6 +36,7 @@ const TableGroupMenu = (props) => {
|
||||
{...rest}
|
||||
>
|
||||
<Checkbox
|
||||
id="menu-checkbox_selected-all-file"
|
||||
className="table-container_group-menu-checkbox"
|
||||
onChange={onCheckboxChange}
|
||||
isChecked={isChecked}
|
||||
@ -43,6 +44,7 @@ const TableGroupMenu = (props) => {
|
||||
title={t("Common:MainHeaderSelectAll")}
|
||||
/>
|
||||
<ComboBox
|
||||
id="menu-combobox"
|
||||
comboIcon="/static/images/triangle.navigation.down.react.svg"
|
||||
noBorder
|
||||
advancedOptions={checkboxOptions}
|
||||
@ -63,6 +65,7 @@ const TableGroupMenu = (props) => {
|
||||
<StyledInfoPanelToggleWrapper isInfoPanelVisible={isInfoPanelVisible}>
|
||||
<div className="info-panel-toggle-bg">
|
||||
<IconButton
|
||||
id="info-panel-toggle--open"
|
||||
className="info-panel-toggle"
|
||||
iconName="images/panel.react.svg"
|
||||
size="16"
|
||||
|
@ -389,13 +389,13 @@
|
||||
<EmbeddedResource Update="Resources\FilesUCResource.zh-CN.resx">
|
||||
<DependentUpon>FilesUCResource.resx</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\FilesCommonResource.az-Latn-AZ.resx">
|
||||
<EmbeddedResource Update="Resources\FilesCommonResource.az.resx">
|
||||
<DependentUpon>FilesCommonResource.resx</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\FilesJSResource.az-Latn-AZ.resx">
|
||||
<EmbeddedResource Update="Resources\FilesJSResource.az.resx">
|
||||
<DependentUpon>FilesJSResource.resx</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Update="Resources\FilesUCResource.az-Latn-AZ.resx">
|
||||
<EmbeddedResource Update="Resources\FilesUCResource.az.resx">
|
||||
<DependentUpon>FilesUCResource.resx</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
@ -58,10 +58,10 @@ public interface IFolderDao<T>
|
||||
Task<Folder<T>> GetRootFolderByFileAsync(T fileId);
|
||||
|
||||
IAsyncEnumerable<Folder<T>> GetRoomsAsync(T parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders,
|
||||
bool withoutTags, bool excludeSubject, ProviderFilter provider);
|
||||
bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds);
|
||||
|
||||
IAsyncEnumerable<Folder<T>> GetRoomsAsync(IEnumerable<T> parentsIds, IEnumerable<T> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders,
|
||||
bool withoutTags, bool excludeSubject, ProviderFilter provider);
|
||||
bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds);
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of folders in current folder.
|
||||
|
@ -164,7 +164,8 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
|
||||
return GetFoldersAsync(parentId, default, FilterType.None, false, default, string.Empty);
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<Folder<int>> GetRoomsAsync(int parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider)
|
||||
public async IAsyncEnumerable<Folder<int>> GetRoomsAsync(int parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter,
|
||||
IEnumerable<string> subjectEntriesIds)
|
||||
{
|
||||
if (CheckInvalidFilter(filterType) || provider != ProviderFilter.None)
|
||||
{
|
||||
@ -179,8 +180,8 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
|
||||
var filesDbContext = _dbContextFactory.CreateDbContext();
|
||||
var q = GetFolderQuery(filesDbContext, r => r.ParentId == parentId).AsNoTracking();
|
||||
|
||||
q = !withSubfolders ? BuildRoomsQuery(filesDbContext, q, filter, tags, subjectId, searchByTags, withoutTags, searchByTypes, false, excludeSubject)
|
||||
: BuildRoomsWithSubfoldersQuery(filesDbContext, parentId, filter, tags, searchByTags, searchByTypes, withoutTags, excludeSubject, subjectId);
|
||||
q = !withSubfolders ? BuildRoomsQuery(filesDbContext, q, filter, tags, subjectId, searchByTags, withoutTags, searchByTypes, false, excludeSubject, subjectFilter, subjectEntriesIds)
|
||||
: BuildRoomsWithSubfoldersQuery(filesDbContext, parentId, filter, tags, searchByTags, searchByTypes, withoutTags, excludeSubject, subjectId, subjectFilter, subjectEntriesIds);
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
@ -194,7 +195,7 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
|
||||
}
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<Folder<int>> GetRoomsAsync(IEnumerable<int> parentsIds, IEnumerable<int> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider)
|
||||
public async IAsyncEnumerable<Folder<int>> GetRoomsAsync(IEnumerable<int> parentsIds, IEnumerable<int> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
|
||||
{
|
||||
if (CheckInvalidFilter(filterType) || provider != ProviderFilter.None)
|
||||
{
|
||||
@ -209,8 +210,8 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
|
||||
var filesDbContext = _dbContextFactory.CreateDbContext();
|
||||
var q = GetFolderQuery(filesDbContext, f => roomsIds.Contains(f.Id) || (f.CreateBy == _authContext.CurrentAccount.ID && parentsIds.Contains(f.ParentId))).AsNoTracking();
|
||||
|
||||
q = !withSubfolders ? BuildRoomsQuery(filesDbContext, q, filter, tags, subjectId, searchByTags, withoutTags, searchByTypes, false, excludeSubject)
|
||||
: BuildRoomsWithSubfoldersQuery(filesDbContext, roomsIds, filter, tags, searchByTags, searchByTypes, withoutTags, excludeSubject, subjectId);
|
||||
q = !withSubfolders ? BuildRoomsQuery(filesDbContext, q, filter, tags, subjectId, searchByTags, withoutTags, searchByTypes, false, excludeSubject, subjectFilter, subjectEntriesIds)
|
||||
: BuildRoomsWithSubfoldersQuery(filesDbContext, roomsIds, filter, tags, searchByTags, searchByTypes, withoutTags, excludeSubject, subjectId, subjectFilter, subjectEntriesIds);
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
@ -1458,8 +1459,21 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
|
||||
}
|
||||
|
||||
private IQueryable<DbFolder> BuildRoomsQuery(FilesDbContext filesDbContext, IQueryable<DbFolder> query, FolderType filterByType, IEnumerable<string> tags, Guid subjectId, bool searchByTags, bool withoutTags,
|
||||
bool searchByFilter, bool withSubfolders, bool excludeSubject)
|
||||
bool searchByFilter, bool withSubfolders, bool excludeSubject, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
|
||||
{
|
||||
if (subjectId != Guid.Empty)
|
||||
{
|
||||
if (subjectFilter == SubjectFilter.Owner)
|
||||
{
|
||||
query = excludeSubject ? query.Where(f => f.CreateBy != subjectId) : query.Where(f => f.CreateBy == subjectId);
|
||||
}
|
||||
else if (subjectFilter == SubjectFilter.Member)
|
||||
{
|
||||
query = excludeSubject ? query.Where(f => f.CreateBy != subjectId && !subjectEntriesIds.Contains(f.Id.ToString()))
|
||||
: query.Where(f => f.CreateBy == subjectId || subjectEntriesIds.Contains(f.Id.ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
if (searchByFilter)
|
||||
{
|
||||
query = query.Where(f => f.FolderType == filterByType);
|
||||
@ -1471,11 +1485,6 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
|
||||
.Where(r => r.tag.Type == TagType.Custom).Any(t => t.EntryId == f.Id.ToString()));
|
||||
}
|
||||
|
||||
if (subjectId != Guid.Empty)
|
||||
{
|
||||
query = excludeSubject ? query.Where(f => f.CreateBy != subjectId) : query.Where(f => f.CreateBy == subjectId);
|
||||
}
|
||||
|
||||
if (searchByTags && !withSubfolders)
|
||||
{
|
||||
query = query.Join(filesDbContext.TagLink, f => f.Id.ToString(), t => t.EntryId, (folder, tag) => new { folder, tag.TagId })
|
||||
@ -1488,11 +1497,11 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
|
||||
}
|
||||
|
||||
private IQueryable<DbFolder> BuildRoomsWithSubfoldersQuery(FilesDbContext filesDbContext, int parentId, FolderType filterByType, IEnumerable<string> tags, bool searchByTags, bool searchByFilter, bool withoutTags,
|
||||
bool excludeSubject, Guid subjectId)
|
||||
bool excludeSubject, Guid subjectId, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
|
||||
{
|
||||
var q1 = GetFolderQuery(filesDbContext, r => r.ParentId == parentId).AsNoTracking();
|
||||
|
||||
q1 = BuildRoomsQuery(filesDbContext, q1, filterByType, tags, subjectId, searchByTags, withoutTags, searchByFilter, true, excludeSubject);
|
||||
q1 = BuildRoomsQuery(filesDbContext, q1, filterByType, tags, subjectId, searchByTags, withoutTags, searchByFilter, true, excludeSubject, subjectFilter, subjectEntriesIds);
|
||||
|
||||
if (searchByTags)
|
||||
{
|
||||
@ -1520,11 +1529,11 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
|
||||
}
|
||||
|
||||
private IQueryable<DbFolder> BuildRoomsWithSubfoldersQuery(FilesDbContext filesDbContext, IEnumerable<int> roomsIds, FolderType filterByType, IEnumerable<string> tags, bool searchByTags, bool searchByFilter, bool withoutTags,
|
||||
bool withoutMe, Guid ownerId)
|
||||
bool withoutMe, Guid ownerId, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
|
||||
{
|
||||
var q1 = GetFolderQuery(filesDbContext, f => roomsIds.Contains(f.Id)).AsNoTracking();
|
||||
|
||||
q1 = BuildRoomsQuery(filesDbContext, q1, filterByType, tags, ownerId, searchByTags, withoutTags, searchByFilter, true, withoutMe);
|
||||
q1 = BuildRoomsQuery(filesDbContext, q1, filterByType, tags, ownerId, searchByTags, withoutTags, searchByFilter, true, withoutMe, subjectFilter, subjectEntriesIds);
|
||||
|
||||
if (searchByTags)
|
||||
{
|
||||
|
@ -272,7 +272,8 @@ public class FileStorageService<T> //: IFileStorageService
|
||||
bool withoutTags = false,
|
||||
IEnumerable<string> tagNames = null,
|
||||
bool excludeSubject = false,
|
||||
ProviderFilter provider = ProviderFilter.None)
|
||||
ProviderFilter provider = ProviderFilter.None,
|
||||
SubjectFilter subjectFilter = SubjectFilter.Owner)
|
||||
{
|
||||
var subjectId = string.IsNullOrEmpty(subject) ? Guid.Empty : new Guid(subject);
|
||||
|
||||
@ -322,7 +323,7 @@ public class FileStorageService<T> //: IFileStorageService
|
||||
try
|
||||
{
|
||||
(entries, total) = await _entryManager.GetEntriesAsync(parent, from, count, filterType, subjectGroup, subjectId, searchText, searchInContent, withSubfolders, orderBy, searchArea,
|
||||
withoutTags, tagNames, excludeSubject, provider);
|
||||
withoutTags, tagNames, excludeSubject, provider, subjectFilter);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -62,6 +62,7 @@ public class FileSecurity : IFileSecurity
|
||||
private readonly AuthManager _authManager;
|
||||
private readonly GlobalFolder _globalFolder;
|
||||
private readonly FileSecurityCommon _fileSecurityCommon;
|
||||
private readonly CoreBaseSettings _coreBaseSettings;
|
||||
|
||||
public FileSecurity(
|
||||
IDaoFactory daoFactory,
|
||||
@ -70,7 +71,8 @@ public class FileSecurity : IFileSecurity
|
||||
AuthContext authContext,
|
||||
AuthManager authManager,
|
||||
GlobalFolder globalFolder,
|
||||
FileSecurityCommon fileSecurityCommon)
|
||||
FileSecurityCommon fileSecurityCommon,
|
||||
CoreBaseSettings coreBaseSettings)
|
||||
{
|
||||
_daoFactory = daoFactory;
|
||||
_userManager = userManager;
|
||||
@ -79,6 +81,7 @@ public class FileSecurity : IFileSecurity
|
||||
_authManager = authManager;
|
||||
_globalFolder = globalFolder;
|
||||
_fileSecurityCommon = fileSecurityCommon;
|
||||
_coreBaseSettings = coreBaseSettings;
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<Tuple<FileEntry<T>, bool>> CanReadAsync<T>(IAsyncEnumerable<FileEntry<T>> entries, Guid userId)
|
||||
@ -527,6 +530,21 @@ public class FileSecurity : IFileSecurity
|
||||
|
||||
private async Task<bool> FilterEntry<T>(FileEntry<T> e, FilesSecurityActions action, Guid userId, IEnumerable<FileShareRecord> shares, bool isOutsider, bool isUser, bool isAuthenticated, bool isDocSpaceAdmin)
|
||||
{
|
||||
if (!_coreBaseSettings.DisableDocSpace)
|
||||
{
|
||||
if (
|
||||
e.RootFolderType == FolderType.COMMON ||
|
||||
e.RootFolderType == FolderType.SHARE ||
|
||||
e.RootFolderType == FolderType.Recent ||
|
||||
e.RootFolderType == FolderType.Favorites ||
|
||||
e.RootFolderType == FolderType.Templates ||
|
||||
e.RootFolderType == FolderType.Privacy ||
|
||||
e.RootFolderType == FolderType.Projects)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (e.RootFolderType == FolderType.COMMON ||
|
||||
e.RootFolderType == FolderType.USER ||
|
||||
e.RootFolderType == FolderType.SHARE ||
|
||||
@ -995,23 +1013,28 @@ public class FileSecurity : IFileSecurity
|
||||
}
|
||||
|
||||
public async Task<List<FileEntry>> GetVirtualRoomsAsync(FilterType filterType, Guid subjectId, string searchText, bool searchInContent, bool withSubfolders,
|
||||
SearchArea searchArea, bool withoutTags, IEnumerable<string> tagNames, bool excludeSubject, ProviderFilter provider)
|
||||
SearchArea searchArea, bool withoutTags, IEnumerable<string> tagNames, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter)
|
||||
{
|
||||
var securityDao = _daoFactory.GetSecurityDao<int>();
|
||||
|
||||
var subjectEntries = subjectFilter is SubjectFilter.Member
|
||||
? await securityDao.GetSharesAsync(new[] { subjectId }).Where(r => r.EntryType == FileEntryType.Folder).Select(r => r.EntryId.ToString()).ToListAsync()
|
||||
: null;
|
||||
|
||||
if (_fileSecurityCommon.IsDocSpaceAdministrator(_authContext.CurrentAccount.ID))
|
||||
{
|
||||
return await GetVirtualRoomsForDocSpaceAdminAsync(filterType, subjectId, searchText, searchInContent, withSubfolders, searchArea, withoutTags, tagNames, excludeSubject, provider);
|
||||
return await GetVirtualRoomsForDocSpaceAdminAsync(filterType, subjectId, searchText, searchInContent, withSubfolders, searchArea, withoutTags, tagNames, excludeSubject, provider, subjectFilter, subjectEntries);
|
||||
}
|
||||
|
||||
var securityDao = _daoFactory.GetSecurityDao<int>();
|
||||
var subjects = GetUserSubjects(_authContext.CurrentAccount.ID);
|
||||
var records = await securityDao.GetSharesAsync(subjects).ToListAsync();
|
||||
var currentUserSubjects = GetUserSubjects(_authContext.CurrentAccount.ID);
|
||||
var currentUsersRecords = await securityDao.GetSharesAsync(currentUserSubjects).ToListAsync();
|
||||
var thirdpartyIds = await GetThirdpartyRoomsIdsAsync(searchArea);
|
||||
var entries = new List<FileEntry>();
|
||||
|
||||
var rooms = await GetVirtualRoomsForUserAsync(records.Where(r => r.EntryId is int), Array.Empty<int>(), subjects, filterType, subjectId, searchText, searchInContent,
|
||||
withSubfolders, searchArea, withoutTags, tagNames, excludeSubject, provider);
|
||||
var thirdPartyRooms = await GetVirtualRoomsForUserAsync(records.Where(r => r.EntryId is string), thirdpartyIds, subjects, filterType, subjectId, searchText,
|
||||
searchInContent, withSubfolders, searchArea, withoutTags, tagNames, excludeSubject, provider);
|
||||
var rooms = await GetVirtualRoomsForUserAsync(currentUsersRecords.Where(r => r.EntryId is int), Array.Empty<int>(), currentUserSubjects, filterType, subjectId, searchText, searchInContent,
|
||||
withSubfolders, searchArea, withoutTags, tagNames, excludeSubject, provider, subjectFilter, subjectEntries);
|
||||
var thirdPartyRooms = await GetVirtualRoomsForUserAsync(currentUsersRecords.Where(r => r.EntryId is string), thirdpartyIds, currentUserSubjects, filterType, subjectId, searchText,
|
||||
searchInContent, withSubfolders, searchArea, withoutTags, tagNames, excludeSubject, provider, subjectFilter, subjectEntries);
|
||||
|
||||
entries.AddRange(rooms);
|
||||
entries.AddRange(thirdPartyRooms);
|
||||
@ -1047,7 +1070,7 @@ public class FileSecurity : IFileSecurity
|
||||
}
|
||||
|
||||
private async Task<List<FileEntry>> GetVirtualRoomsForDocSpaceAdminAsync(FilterType filterType, Guid subjectId, string search, bool searchInContent, bool withSubfolders,
|
||||
SearchArea searchArea, bool withoutTags, IEnumerable<string> tagNames, bool excludeSubject, ProviderFilter provider)
|
||||
SearchArea searchArea, bool withoutTags, IEnumerable<string> tagNames, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntries)
|
||||
{
|
||||
var folderDao = _daoFactory.GetFolderDao<int>();
|
||||
var folderThirdPartyDao = _daoFactory.GetFolderDao<string>();
|
||||
@ -1064,8 +1087,8 @@ public class FileSecurity : IFileSecurity
|
||||
var roomsFolderId = await _globalFolder.GetFolderVirtualRoomsAsync<int>(_daoFactory);
|
||||
var thirdPartyRoomsIds = await providerDao.GetProvidersInfoAsync(FolderType.VirtualRooms).Select(p => p.FolderId).ToListAsync();
|
||||
|
||||
var roomsEntries = await folderDao.GetRoomsAsync(roomsFolderId, filterType, tagNames, subjectId, search, withSubfolders, withoutTags, excludeSubject, provider).ToListAsync();
|
||||
var thirdPartyRoomsEntries = await folderThirdPartyDao.GetRoomsAsync(Array.Empty<string>(), thirdPartyRoomsIds, filterType, tagNames, subjectId, search, withSubfolders, withoutTags, excludeSubject, provider)
|
||||
var roomsEntries = await folderDao.GetRoomsAsync(roomsFolderId, filterType, tagNames, subjectId, search, withSubfolders, withoutTags, excludeSubject, provider, subjectFilter, subjectEntries).ToListAsync();
|
||||
var thirdPartyRoomsEntries = await folderThirdPartyDao.GetRoomsAsync(Array.Empty<string>(), thirdPartyRoomsIds, filterType, tagNames, subjectId, search, withSubfolders, withoutTags, excludeSubject, provider, subjectFilter, subjectEntries)
|
||||
.ToListAsync();
|
||||
|
||||
foldersInt.AddRange(roomsEntries);
|
||||
@ -1096,8 +1119,8 @@ public class FileSecurity : IFileSecurity
|
||||
var archiveFolderId = await _globalFolder.GetFolderArchiveAsync<int>(_daoFactory);
|
||||
var thirdPartyRoomsIds = await providerDao.GetProvidersInfoAsync(FolderType.Archive).Select(p => p.FolderId).ToListAsync();
|
||||
|
||||
var roomsEntries = await folderDao.GetRoomsAsync(archiveFolderId, filterType, tagNames, subjectId, search, withSubfolders, withoutTags, excludeSubject, provider).ToListAsync();
|
||||
var thirdPartyRoomsEntries = await folderThirdPartyDao.GetRoomsAsync(Array.Empty<string>(), thirdPartyRoomsIds, filterType, tagNames, subjectId, search, withSubfolders, withoutTags, excludeSubject, provider)
|
||||
var roomsEntries = await folderDao.GetRoomsAsync(archiveFolderId, filterType, tagNames, subjectId, search, withSubfolders, withoutTags, excludeSubject, provider, subjectFilter, subjectEntries).ToListAsync();
|
||||
var thirdPartyRoomsEntries = await folderThirdPartyDao.GetRoomsAsync(Array.Empty<string>(), thirdPartyRoomsIds, filterType, tagNames, subjectId, search, withSubfolders, withoutTags, excludeSubject, provider, subjectFilter, subjectEntries)
|
||||
.ToListAsync();
|
||||
|
||||
foldersInt.AddRange(roomsEntries);
|
||||
@ -1136,7 +1159,7 @@ public class FileSecurity : IFileSecurity
|
||||
}
|
||||
|
||||
private async Task<List<FileEntry>> GetVirtualRoomsForUserAsync<T>(IEnumerable<FileShareRecord> records, IEnumerable<T> proivdersIds, List<Guid> subjects, FilterType filterType, Guid subjectId, string search,
|
||||
bool searchInContent, bool withSubfolders, SearchArea searchArea, bool withoutTags, IEnumerable<string> tagNames, bool excludeSubject, ProviderFilter provider)
|
||||
bool searchInContent, bool withSubfolders, SearchArea searchArea, bool withoutTags, IEnumerable<string> tagNames, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntries)
|
||||
{
|
||||
var folderDao = _daoFactory.GetFolderDao<T>();
|
||||
var fileDao = _daoFactory.GetFileDao<T>();
|
||||
@ -1193,7 +1216,7 @@ public class FileSecurity : IFileSecurity
|
||||
return false;
|
||||
};
|
||||
|
||||
var fileEntries = await folderDao.GetRoomsAsync(rootFoldersIds, roomsIds.Keys, filterType, tagNames, subjectId, search, withSubfolders, withoutTags, excludeSubject, provider)
|
||||
var fileEntries = await folderDao.GetRoomsAsync(rootFoldersIds, roomsIds.Keys, filterType, tagNames, subjectId, search, withSubfolders, withoutTags, excludeSubject, provider, subjectFilter, subjectEntries)
|
||||
.Where(filter).ToListAsync();
|
||||
|
||||
await SetTagsAsync(fileEntries);
|
||||
|
33
products/ASC.Files/Core/Core/SubjectFilter.cs
Normal file
33
products/ASC.Files/Core/Core/SubjectFilter.cs
Normal file
@ -0,0 +1,33 @@
|
||||
// (c) Copyright Ascensio System SIA 2010-2022
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
namespace ASC.Files.Core.Core;
|
||||
|
||||
public enum SubjectFilter
|
||||
{
|
||||
Owner = 0,
|
||||
Member = 1,
|
||||
}
|
@ -75,7 +75,7 @@ internal class BoxFolderDao : BoxDaoBase, IFolderDao<string>
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders,
|
||||
bool withoutTags, bool excludeSubject, ProviderFilter provider)
|
||||
bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
|
||||
{
|
||||
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.Box))
|
||||
{
|
||||
@ -85,7 +85,7 @@ internal class BoxFolderDao : BoxDaoBase, IFolderDao<string>
|
||||
var rooms = GetFoldersAsync(parentId);
|
||||
|
||||
rooms = FilterByRoomType(rooms, filterType);
|
||||
rooms = FilterBySubject(rooms, subjectId, excludeSubject);
|
||||
rooms = FilterBySubject(rooms, subjectId, excludeSubject, subjectFilter, subjectEntriesIds);
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
@ -98,7 +98,7 @@ internal class BoxFolderDao : BoxDaoBase, IFolderDao<string>
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText,
|
||||
bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider)
|
||||
bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
|
||||
{
|
||||
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.Box))
|
||||
{
|
||||
@ -108,7 +108,7 @@ internal class BoxFolderDao : BoxDaoBase, IFolderDao<string>
|
||||
var folders = roomsIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false));
|
||||
|
||||
folders = FilterByRoomType(folders, filterType);
|
||||
folders = FilterBySubject(folders, subjectId, excludeSubject);
|
||||
folders = FilterBySubject(folders, subjectId, excludeSubject, subjectFilter, subjectEntriesIds);
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
|
@ -77,7 +77,7 @@ internal class DropboxFolderDao : DropboxDaoBase, IFolderDao<string>
|
||||
return GetRootFolderAsync(fileId);
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider)
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
|
||||
{
|
||||
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.DropBox))
|
||||
{
|
||||
@ -87,7 +87,7 @@ internal class DropboxFolderDao : DropboxDaoBase, IFolderDao<string>
|
||||
var rooms = GetFoldersAsync(parentId);
|
||||
|
||||
rooms = FilterByRoomType(rooms, filterType);
|
||||
rooms = FilterBySubject(rooms, subjectId, excludeSubject);
|
||||
rooms = FilterBySubject(rooms, subjectId, excludeSubject, subjectFilter, subjectEntriesIds);
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
@ -99,7 +99,7 @@ internal class DropboxFolderDao : DropboxDaoBase, IFolderDao<string>
|
||||
return rooms;
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider)
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
|
||||
{
|
||||
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.DropBox))
|
||||
{
|
||||
@ -109,7 +109,7 @@ internal class DropboxFolderDao : DropboxDaoBase, IFolderDao<string>
|
||||
var folders = roomsIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false));
|
||||
|
||||
folders = FilterByRoomType(folders, filterType);
|
||||
folders = FilterBySubject(folders, subjectId, excludeSubject);
|
||||
folders = FilterBySubject(folders, subjectId, excludeSubject, subjectFilter, subjectEntriesIds);
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
|
@ -74,7 +74,7 @@ internal class GoogleDriveFolderDao : GoogleDriveDaoBase, IFolderDao<string>
|
||||
return GetRootFolderAsync("");
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider)
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
|
||||
{
|
||||
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.GoogleDrive))
|
||||
{
|
||||
@ -84,7 +84,7 @@ internal class GoogleDriveFolderDao : GoogleDriveDaoBase, IFolderDao<string>
|
||||
var rooms = GetFoldersAsync(parentId);
|
||||
|
||||
rooms = FilterByRoomType(rooms, filterType);
|
||||
rooms = FilterBySubject(rooms, subjectId, excludeSubject);
|
||||
rooms = FilterBySubject(rooms, subjectId, excludeSubject, subjectFilter, subjectEntriesIds);
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
@ -96,7 +96,8 @@ internal class GoogleDriveFolderDao : GoogleDriveDaoBase, IFolderDao<string>
|
||||
return rooms;
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider)
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter,
|
||||
IEnumerable<string> subjectEntriesIds)
|
||||
{
|
||||
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.GoogleDrive))
|
||||
{
|
||||
@ -106,7 +107,7 @@ internal class GoogleDriveFolderDao : GoogleDriveDaoBase, IFolderDao<string>
|
||||
var folders = roomsIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false));
|
||||
|
||||
folders = FilterByRoomType(folders, filterType);
|
||||
folders = FilterBySubject(folders, subjectId, excludeSubject);
|
||||
folders = FilterBySubject(folders, subjectId, excludeSubject, subjectFilter, subjectEntriesIds);
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
|
@ -456,12 +456,20 @@ internal abstract class ThirdPartyProviderDao<T> : ThirdPartyProviderDao, IDispo
|
||||
return rooms.Where(f => f != null && (f.FolderType == filter || filter == FolderType.DEFAULT));
|
||||
}
|
||||
|
||||
protected IAsyncEnumerable<Folder<string>> FilterBySubject(IAsyncEnumerable<Folder<string>> rooms, Guid subjectId, bool excludeSubject)
|
||||
protected IAsyncEnumerable<Folder<string>> FilterBySubject(IAsyncEnumerable<Folder<string>> rooms, Guid subjectId, bool excludeSubject, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds = null)
|
||||
{
|
||||
if (subjectId != Guid.Empty)
|
||||
{
|
||||
if (subjectFilter == SubjectFilter.Owner)
|
||||
{
|
||||
rooms = excludeSubject ? rooms.Where(f => f != null && f.CreateBy != subjectId) : rooms.Where(f => f != null && f.CreateBy == subjectId);
|
||||
}
|
||||
else if (subjectFilter == SubjectFilter.Member)
|
||||
{
|
||||
rooms = excludeSubject ? rooms.Where(f => f != null && f.CreateBy != subjectId && !subjectEntriesIds.Contains(f.Id))
|
||||
: rooms.Where(f => f != null && (f.CreateBy == subjectId || subjectEntriesIds.Contains(f.Id)));
|
||||
}
|
||||
}
|
||||
|
||||
return rooms;
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ internal class OneDriveFolderDao : OneDriveDaoBase, IFolderDao<string>
|
||||
return GetRootFolderAsync(fileId);
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider)
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
|
||||
{
|
||||
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.OneDrive))
|
||||
{
|
||||
@ -84,7 +84,7 @@ internal class OneDriveFolderDao : OneDriveDaoBase, IFolderDao<string>
|
||||
var rooms = GetFoldersAsync(parentId);
|
||||
|
||||
rooms = FilterByRoomType(rooms, filterType);
|
||||
rooms = FilterBySubject(rooms, subjectId, excludeSubject);
|
||||
rooms = FilterBySubject(rooms, subjectId, excludeSubject, subjectFilter, subjectEntriesIds);
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
@ -96,7 +96,7 @@ internal class OneDriveFolderDao : OneDriveDaoBase, IFolderDao<string>
|
||||
return rooms;
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider)
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
|
||||
{
|
||||
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.OneDrive))
|
||||
{
|
||||
@ -106,7 +106,7 @@ internal class OneDriveFolderDao : OneDriveDaoBase, IFolderDao<string>
|
||||
var folders = roomsIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false));
|
||||
|
||||
folders = FilterByRoomType(folders, filterType);
|
||||
folders = FilterBySubject(folders, subjectId, excludeSubject);
|
||||
folders = FilterBySubject(folders, subjectId, excludeSubject, subjectFilter, subjectEntriesIds);
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
|
@ -90,11 +90,11 @@ internal class ProviderFolderDao : ProviderDaoBase, IFolderDao<string>
|
||||
return folderDao.GetRootFolderByFileAsync(selector.ConvertId(fileId));
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<Folder<string>> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider)
|
||||
public async IAsyncEnumerable<Folder<string>> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
|
||||
{
|
||||
var selector = GetSelector(parentId);
|
||||
var folderDao = selector.GetFolderDao(parentId);
|
||||
var rooms = folderDao.GetRoomsAsync(selector.ConvertId(parentId), filterType, tags, subjectId, searchText, withSubfolders, withoutTags, excludeSubject, provider);
|
||||
var rooms = folderDao.GetRoomsAsync(selector.ConvertId(parentId), filterType, tags, subjectId, searchText, withSubfolders, withoutTags, excludeSubject, provider, subjectFilter, subjectEntriesIds);
|
||||
|
||||
var result = await FilterByProvider(rooms.Where(r => r != null), provider).ToListAsync();
|
||||
|
||||
@ -106,7 +106,7 @@ internal class ProviderFolderDao : ProviderDaoBase, IFolderDao<string>
|
||||
}
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider)
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
|
||||
{
|
||||
var result = AsyncEnumerable.Empty<Folder<string>>();
|
||||
|
||||
@ -126,7 +126,7 @@ internal class ProviderFolderDao : ProviderDaoBase, IFolderDao<string>
|
||||
{
|
||||
var folderDao = selectorLocal.GetFolderDao(matchedId.FirstOrDefault());
|
||||
|
||||
return folderDao.GetRoomsAsync(parentsIds, matchedId.Select(selectorLocal.ConvertId).ToList(), filterType, tags, subjectId, searchText, withSubfolders, withoutTags, excludeSubject, provider);
|
||||
return folderDao.GetRoomsAsync(parentsIds, matchedId.Select(selectorLocal.ConvertId).ToList(), filterType, tags, subjectId, searchText, withSubfolders, withoutTags, excludeSubject, provider, subjectFilter, subjectEntriesIds);
|
||||
})
|
||||
.Where(r => r != null));
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ internal class SharePointFolderDao : SharePointDaoBase, IFolderDao<string>
|
||||
return Task.FromResult(ProviderInfo.ToFolder(ProviderInfo.RootFolder));
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider)
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
|
||||
{
|
||||
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.SharePoint))
|
||||
{
|
||||
@ -90,7 +90,7 @@ internal class SharePointFolderDao : SharePointDaoBase, IFolderDao<string>
|
||||
var rooms = GetFoldersAsync(parentId);
|
||||
|
||||
rooms = FilterByRoomType(rooms, filterType);
|
||||
rooms = FilterBySubject(rooms, subjectId, excludeSubject);
|
||||
rooms = FilterBySubject(rooms, subjectId, excludeSubject, subjectFilter, subjectEntriesIds);
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
@ -102,7 +102,7 @@ internal class SharePointFolderDao : SharePointDaoBase, IFolderDao<string>
|
||||
return rooms;
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider)
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
|
||||
{
|
||||
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.SharePoint))
|
||||
{
|
||||
@ -112,7 +112,7 @@ internal class SharePointFolderDao : SharePointDaoBase, IFolderDao<string>
|
||||
var folders = roomsIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false));
|
||||
|
||||
folders = FilterByRoomType(folders, filterType);
|
||||
folders = FilterBySubject(folders, subjectId, excludeSubject);
|
||||
folders = FilterBySubject(folders, subjectId, excludeSubject, subjectFilter, subjectEntriesIds);
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
|
@ -79,7 +79,7 @@ internal class SharpBoxFolderDao : SharpBoxDaoBase, IFolderDao<string>
|
||||
return Task.FromResult(ToFolder(RootFolder()));
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider)
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(string parentId, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider, SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
|
||||
{
|
||||
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.kDrive && provider != ProviderFilter.WebDav && provider != ProviderFilter.Yandex))
|
||||
{
|
||||
@ -89,7 +89,7 @@ internal class SharpBoxFolderDao : SharpBoxDaoBase, IFolderDao<string>
|
||||
var rooms = GetFoldersAsync(parentId);
|
||||
|
||||
rooms = FilterByRoomType(rooms, filterType);
|
||||
rooms = FilterBySubject(rooms, subjectId, excludeSubject);
|
||||
rooms = FilterBySubject(rooms, subjectId, excludeSubject, subjectFilter, subjectEntriesIds);
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
@ -101,7 +101,8 @@ internal class SharpBoxFolderDao : SharpBoxDaoBase, IFolderDao<string>
|
||||
return rooms;
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider)
|
||||
public IAsyncEnumerable<Folder<string>> GetRoomsAsync(IEnumerable<string> parentsIds, IEnumerable<string> roomsIds, FilterType filterType, IEnumerable<string> tags, Guid subjectId, string searchText, bool withSubfolders, bool withoutTags, bool excludeSubject, ProviderFilter provider,
|
||||
SubjectFilter subjectFilter, IEnumerable<string> subjectEntriesIds)
|
||||
{
|
||||
if (CheckInvalidFilter(filterType) || (provider != ProviderFilter.None && provider != ProviderFilter.kDrive && provider != ProviderFilter.WebDav && provider != ProviderFilter.Yandex))
|
||||
{
|
||||
@ -111,7 +112,7 @@ internal class SharpBoxFolderDao : SharpBoxDaoBase, IFolderDao<string>
|
||||
var folders = roomsIds.ToAsyncEnumerable().SelectAwait(async e => await GetFolderAsync(e).ConfigureAwait(false));
|
||||
|
||||
folders = FilterByRoomType(folders, filterType);
|
||||
folders = FilterBySubject(folders, subjectId, excludeSubject);
|
||||
folders = FilterBySubject(folders, subjectId, excludeSubject, subjectFilter, subjectEntriesIds);
|
||||
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
{
|
||||
|
@ -29,13 +29,6 @@ namespace ASC.Files.Core.Mapping;
|
||||
[Scope]
|
||||
public class FolderMappingAction : IMappingAction<DbFolderQuery, Folder<int>>
|
||||
{
|
||||
private readonly CoreBaseSettings _coreBaseSettings;
|
||||
|
||||
public FolderMappingAction(CoreBaseSettings coreBaseSettings)
|
||||
{
|
||||
_coreBaseSettings = coreBaseSettings;
|
||||
}
|
||||
|
||||
public void Process(DbFolderQuery source, Folder<int> destination, ResolutionContext context)
|
||||
{
|
||||
switch (destination.FolderType)
|
||||
@ -44,7 +37,7 @@ public class FolderMappingAction : IMappingAction<DbFolderQuery, Folder<int>>
|
||||
destination.Title = FilesUCResource.CorporateFiles;
|
||||
break;
|
||||
case FolderType.USER:
|
||||
destination.Title = _coreBaseSettings.DisableDocSpace ? FilesUCResource.MyFiles : FilesUCResource.Personal;
|
||||
destination.Title = FilesUCResource.MyFiles;
|
||||
break;
|
||||
case FolderType.SHARE:
|
||||
destination.Title = FilesUCResource.SharedForMe;
|
||||
|
@ -61,7 +61,7 @@ namespace ASC.Files.Core.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Archived.
|
||||
/// Looks up a localized string similar to My archive.
|
||||
/// </summary>
|
||||
public static string Archive {
|
||||
get {
|
||||
@ -169,7 +169,7 @@ namespace ASC.Files.Core.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Shared.
|
||||
/// Looks up a localized string similar to My rooms.
|
||||
/// </summary>
|
||||
public static string VirtualRooms {
|
||||
get {
|
||||
|
@ -118,7 +118,7 @@
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Archive" xml:space="preserve">
|
||||
<value>Archived</value>
|
||||
<value>My archive</value>
|
||||
</data>
|
||||
<data name="CorporateFiles" xml:space="preserve">
|
||||
<value>Common</value>
|
||||
@ -154,6 +154,6 @@
|
||||
<value>Trash</value>
|
||||
</data>
|
||||
<data name="VirtualRooms" xml:space="preserve">
|
||||
<value>Shared</value>
|
||||
<value>My rooms</value>
|
||||
</data>
|
||||
</root>
|
@ -388,7 +388,7 @@ public class EntryManager
|
||||
|
||||
public async Task<(IEnumerable<FileEntry> Entries, int Total)> GetEntriesAsync<T>(Folder<T> parent, int from, int count, FilterType filterType, bool subjectGroup, Guid subjectId,
|
||||
string searchText, bool searchInContent, bool withSubfolders, OrderBy orderBy, SearchArea searchArea = SearchArea.Active, bool withoutTags = false, IEnumerable<string> tagNames = null,
|
||||
bool excludeSubject = false, ProviderFilter provider = ProviderFilter.None)
|
||||
bool excludeSubject = false, ProviderFilter provider = ProviderFilter.None, SubjectFilter subjectFilter = SubjectFilter.Owner)
|
||||
{
|
||||
var total = 0;
|
||||
|
||||
@ -471,7 +471,7 @@ public class EntryManager
|
||||
}
|
||||
else if ((parent.FolderType == FolderType.VirtualRooms || parent.FolderType == FolderType.Archive) && !parent.ProviderEntry)
|
||||
{
|
||||
entries = await _fileSecurity.GetVirtualRoomsAsync(filterType, subjectId, searchText, searchInContent, withSubfolders, searchArea, withoutTags, tagNames, excludeSubject, provider);
|
||||
entries = await _fileSecurity.GetVirtualRoomsAsync(filterType, subjectId, searchText, searchInContent, withSubfolders, searchArea, withoutTags, tagNames, excludeSubject, provider, subjectFilter);
|
||||
|
||||
CalculateTotal();
|
||||
}
|
||||
|
@ -653,7 +653,7 @@ public class VirtualRoomsCommonController : ApiControllerBase
|
||||
/// </returns>
|
||||
[HttpGet("rooms")]
|
||||
public async Task<FolderContentDto<int>> GetRoomsFolderAsync(RoomFilterType? type, string subjectId, bool? searchInContent, bool? withSubfolders, SearchArea? searchArea, bool? withoutTags, string tags, bool? excludeSubject,
|
||||
ProviderFilter? provider)
|
||||
ProviderFilter? provider, SubjectFilter? subjectFilter)
|
||||
{
|
||||
ErrorIfNotDocSpace();
|
||||
|
||||
@ -685,7 +685,7 @@ public class VirtualRoomsCommonController : ApiControllerBase
|
||||
|
||||
var content = await _fileStorageServiceInt.GetFolderItemsAsync(parentId, startIndex, count, filter, false, subjectId, filterValue,
|
||||
searchInContent ?? false, withSubfolders ?? false, orderBy, searchArea ?? SearchArea.Active, withoutTags ?? false, tagNames, excludeSubject ?? false,
|
||||
provider ?? ProviderFilter.None);
|
||||
provider ?? ProviderFilter.None, subjectFilter ?? SubjectFilter.Owner);
|
||||
|
||||
var dto = await _folderContentDtoHelper.GetAsync(content, startIndex);
|
||||
|
||||
|
@ -28,7 +28,6 @@ namespace ASC.Files.Helpers;
|
||||
|
||||
public class FoldersControllerHelper<T> : FilesHelperBase<T>
|
||||
{
|
||||
private readonly EntryManager _entryManager;
|
||||
private readonly UserManager _userManager;
|
||||
private readonly SecurityContext _securityContext;
|
||||
private readonly GlobalFolderHelper _globalFolderHelper;
|
||||
@ -45,7 +44,6 @@ public class FoldersControllerHelper<T> : FilesHelperBase<T>
|
||||
FolderContentDtoHelper folderContentDtoHelper,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
FolderDtoHelper folderDtoHelper,
|
||||
EntryManager entryManager,
|
||||
UserManager userManager,
|
||||
SecurityContext securityContext,
|
||||
GlobalFolderHelper globalFolderHelper,
|
||||
@ -66,7 +64,6 @@ public class FoldersControllerHelper<T> : FilesHelperBase<T>
|
||||
_coreBaseSettings = coreBaseSettings;
|
||||
_fileUtility = fileUtility;
|
||||
_securityContext = securityContext;
|
||||
_entryManager = entryManager;
|
||||
_userManager = userManager;
|
||||
}
|
||||
|
||||
@ -108,8 +105,10 @@ public class FoldersControllerHelper<T> : FilesHelperBase<T>
|
||||
yield return _globalFolderHelper.FolderMy;
|
||||
}
|
||||
|
||||
if (!_coreBaseSettings.Personal && _coreBaseSettings.DisableDocSpace
|
||||
&& !_userManager.IsOutsider(user))
|
||||
if (_coreBaseSettings.DisableDocSpace)
|
||||
{
|
||||
if (!_coreBaseSettings.Personal &&
|
||||
!_userManager.IsOutsider(user))
|
||||
{
|
||||
yield return await _globalFolderHelper.FolderShareAsync;
|
||||
}
|
||||
@ -128,26 +127,25 @@ public class FoldersControllerHelper<T> : FilesHelperBase<T>
|
||||
|
||||
if (!IsUser &&
|
||||
!_coreBaseSettings.Personal &&
|
||||
_coreBaseSettings.DisableDocSpace &&
|
||||
PrivacyRoomSettings.IsAvailable())
|
||||
{
|
||||
yield return await _globalFolderHelper.FolderPrivacyAsync;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_coreBaseSettings.Personal && _coreBaseSettings.DisableDocSpace)
|
||||
if (!_coreBaseSettings.Personal)
|
||||
{
|
||||
yield return await _globalFolderHelper.FolderCommonAsync;
|
||||
}
|
||||
|
||||
if (!IsUser
|
||||
&& _coreBaseSettings.DisableDocSpace
|
||||
&& !withoutAdditionalFolder
|
||||
&& _fileUtility.ExtsWebTemplate.Count > 0
|
||||
&& _filesSettingsHelper.TemplatesSection)
|
||||
if (!IsUser &&
|
||||
!withoutAdditionalFolder &&
|
||||
_fileUtility.ExtsWebTemplate.Count > 0 &&
|
||||
_filesSettingsHelper.TemplatesSection)
|
||||
{
|
||||
yield return await _globalFolderHelper.FolderTemplatesAsync;
|
||||
}
|
||||
}
|
||||
|
||||
if (!withoutTrash && !IsUser)
|
||||
{
|
||||
|
@ -555,13 +555,13 @@ public class UserController : PeopleControllerBase
|
||||
_apiContext.SetDataFiltered();
|
||||
}
|
||||
|
||||
return GetFullByFilter(status, groupId, null, null, null);
|
||||
return GetFullByFilter(status, groupId, null, null, null, null);
|
||||
}
|
||||
|
||||
[HttpGet("filter")]
|
||||
public async IAsyncEnumerable<EmployeeFullDto> GetFullByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
|
||||
public async IAsyncEnumerable<EmployeeFullDto> GetFullByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator, Payments? payments)
|
||||
{
|
||||
var users = GetByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator);
|
||||
var users = GetByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator, payments);
|
||||
|
||||
foreach (var user in users)
|
||||
{
|
||||
@ -607,9 +607,9 @@ public class UserController : PeopleControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("simple/filter")]
|
||||
public async IAsyncEnumerable<EmployeeDto> GetSimpleByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator)
|
||||
public async IAsyncEnumerable<EmployeeDto> GetSimpleByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isAdministrator, Payments? payments)
|
||||
{
|
||||
var users = GetByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator);
|
||||
var users = GetByFilter(employeeStatus, groupId, activationStatus, employeeType, isAdministrator, payments);
|
||||
|
||||
foreach (var user in users)
|
||||
{
|
||||
@ -1274,7 +1274,7 @@ public class UserController : PeopleControllerBase
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private IQueryable<UserInfo> GetByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isDocSpaceAdministrator)
|
||||
private IQueryable<UserInfo> GetByFilter(EmployeeStatus? employeeStatus, Guid? groupId, EmployeeActivationStatus? activationStatus, EmployeeType? employeeType, bool? isDocSpaceAdministrator, Payments? payments)
|
||||
{
|
||||
if (_coreBaseSettings.Personal)
|
||||
{
|
||||
@ -1296,8 +1296,12 @@ public class UserController : PeopleControllerBase
|
||||
{
|
||||
switch (employeeType)
|
||||
{
|
||||
case EmployeeType.DocSpaceAdmin:
|
||||
includeGroups.Add(new List<Guid> { Constants.GroupAdmin.ID });
|
||||
break;
|
||||
case EmployeeType.RoomAdmin:
|
||||
excludeGroups.Add(Constants.GroupUser.ID);
|
||||
excludeGroups.Add(Constants.GroupAdmin.ID);
|
||||
break;
|
||||
case EmployeeType.User:
|
||||
includeGroups.Add(new List<Guid> { Constants.GroupUser.ID });
|
||||
@ -1305,6 +1309,19 @@ public class UserController : PeopleControllerBase
|
||||
}
|
||||
}
|
||||
|
||||
if (payments != null)
|
||||
{
|
||||
switch (payments)
|
||||
{
|
||||
case Payments.Paid:
|
||||
excludeGroups.Add(Constants.GroupUser.ID);
|
||||
break;
|
||||
case Payments.Free:
|
||||
includeGroups.Add(new List<Guid> { Constants.GroupUser.ID });
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isDocSpaceAdministrator.HasValue && isDocSpaceAdministrator.Value)
|
||||
{
|
||||
var adminGroups = new List<Guid>
|
||||
|
@ -194,6 +194,7 @@
|
||||
"NoTags": "No tags",
|
||||
"Title": "Title",
|
||||
"TitleSelectFile": "Select",
|
||||
"Today": "Today",
|
||||
"Type": "Type",
|
||||
"Terabyte": "TB",
|
||||
"Unknown": "Unknown",
|
||||
@ -214,6 +215,7 @@
|
||||
"HelpCenter": "Help center",
|
||||
"FeedbackAndSupport": "Feedback & Support",
|
||||
"VideoGuides": "Video Guides",
|
||||
"Yesterday": "Yesterday",
|
||||
"SelectFile": "Select file",
|
||||
"HideArticleMenu": "Hide menu"
|
||||
}
|
||||
|
@ -175,6 +175,7 @@
|
||||
"NoTags": "Нет тэгов",
|
||||
"Title": "Заголовок",
|
||||
"TitleSelectFile": "Выделить",
|
||||
"Today": "Сегодня",
|
||||
"Type": "Тип",
|
||||
"Terabyte": "Тб",
|
||||
"Unknown": "Неизвестный",
|
||||
@ -191,6 +192,7 @@
|
||||
"AboutCompanyTitle": "О программе",
|
||||
"LogoutButton": "Выйти",
|
||||
"HelpCenter": "Справочный центр",
|
||||
"Yesterday": "Вчера",
|
||||
"SelectFile": "Выбрать файл",
|
||||
"HideArticleMenu": "Скрыть меню"
|
||||
}
|
||||
|
@ -371,8 +371,7 @@ public class SettingsController : BaseSettingsController
|
||||
_settingsManager.SaveForCurrentUser(collaboratorPopupSettings);
|
||||
}
|
||||
|
||||
[AllowNotPayment]
|
||||
[AllowAnonymous]
|
||||
[AllowAnonymous, AllowNotPayment, AllowSuspended]
|
||||
[HttpGet("colortheme")]
|
||||
public CustomColorThemesSettingsDto GetColorTheme()
|
||||
{
|
||||
|
@ -1149,6 +1149,51 @@ namespace ASC.Web.Core.PublicResources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Telegram.
|
||||
/// </summary>
|
||||
public static string ConsumersTelegram {
|
||||
get {
|
||||
return ResourceManager.GetString("ConsumersTelegram", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Bot username.
|
||||
/// </summary>
|
||||
public static string ConsumersTelegramBotName {
|
||||
get {
|
||||
return ResourceManager.GetString("ConsumersTelegramBotName", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Bot token.
|
||||
/// </summary>
|
||||
public static string ConsumersTelegramBotToken {
|
||||
get {
|
||||
return ResourceManager.GetString("ConsumersTelegramBotToken", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Connect Telegram account to receive portal notifications via Telegram..
|
||||
/// </summary>
|
||||
public static string ConsumersTelegramDescription {
|
||||
get {
|
||||
return ResourceManager.GetString("ConsumersTelegramDescription", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to To receive portal notifications via Telegram, enable Telegram bot. You can create a new bot using BotFather in Telegram Desktop. To use this bot, portal users need to enable Telegram notifications on their Profile Page. {0}Paste bot’s username and the token you received in the fields below..
|
||||
/// </summary>
|
||||
public static string ConsumersTelegramInstructionV11 {
|
||||
get {
|
||||
return ResourceManager.GetString("ConsumersTelegramInstructionV11", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Twilio.
|
||||
/// </summary>
|
||||
|
@ -909,4 +909,19 @@
|
||||
<data name="ErrorIpSecurity" xml:space="preserve">
|
||||
<value>The access to the portal is restricted</value>
|
||||
</data>
|
||||
<data name="ConsumersTelegram" xml:space="preserve">
|
||||
<value>Telegram</value>
|
||||
</data>
|
||||
<data name="ConsumersTelegramBotName" xml:space="preserve">
|
||||
<value>Bot username</value>
|
||||
</data>
|
||||
<data name="ConsumersTelegramBotToken" xml:space="preserve">
|
||||
<value>Bot token</value>
|
||||
</data>
|
||||
<data name="ConsumersTelegramDescription" xml:space="preserve">
|
||||
<value>Connect Telegram account to receive portal notifications via Telegram.</value>
|
||||
</data>
|
||||
<data name="ConsumersTelegramInstructionV11" xml:space="preserve">
|
||||
<value>To receive portal notifications via Telegram, enable Telegram bot. You can create a new bot using BotFather in Telegram Desktop. To use this bot, portal users need to enable Telegram notifications on their Profile Page. {0}Paste bot’s username and the token you received in the fields below.</value>
|
||||
</data>
|
||||
</root>
|
Loading…
Reference in New Issue
Block a user