Merge branch 'release/rc-v1.2.0' of github.com:ONLYOFFICE/DocSpace into release/rc-v1.2.0

# Conflicts:
#	packages/client/src/store/FilesStore.js
This commit is contained in:
Akmal Isomadinov 2022-12-16 17:31:44 +05:00
commit 3f19ea513a
49 changed files with 5553 additions and 581 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ASC.Migrations.MySql.Migrations.FilesDb
{
public partial class FilesDbContext_Upgrade1 : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "has_logo",
table: "files_thirdparty_account",
type: "tinyint(1)",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<bool>(
name: "has_logo",
table: "files_folder",
type: "tinyint(1)",
nullable: false,
defaultValue: false);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "has_logo",
table: "files_thirdparty_account");
migrationBuilder.DropColumn(
name: "has_logo",
table: "files_folder");
}
}
}

View File

@ -2329,6 +2329,10 @@ namespace ASC.Migrations.MySql.Migrations
.HasColumnName("folder_type")
.HasDefaultValueSql("'0'");
b.Property<bool>("HasLogo")
.HasColumnType("tinyint(1)")
.HasColumnName("has_logo");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("varchar(512)")
@ -2502,6 +2506,10 @@ namespace ASC.Migrations.MySql.Migrations
.HasColumnName("foldersCount")
.HasDefaultValueSql("'0'");
b.Property<bool>("HasLogo")
.HasColumnType("tinyint(1)")
.HasColumnName("has_logo");
b.Property<string>("ModifiedBy")
.IsRequired()
.HasColumnType("char(38)")

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ASC.Migrations.PostgreSql.Migrations.FilesDb
{
public partial class FilesDbContext_Upgrade1 : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "has_logo",
schema: "onlyoffice",
table: "files_thirdparty_account",
type: "boolean",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<bool>(
name: "has_logo",
schema: "onlyoffice",
table: "files_folder",
type: "boolean",
nullable: false,
defaultValue: false);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "has_logo",
schema: "onlyoffice",
table: "files_thirdparty_account");
migrationBuilder.DropColumn(
name: "has_logo",
schema: "onlyoffice",
table: "files_folder");
}
}
}

View File

@ -2283,6 +2283,10 @@ namespace ASC.Migrations.PostgreSql.Migrations
.HasColumnType("integer")
.HasColumnName("folder_type");
b.Property<bool>("HasLogo")
.HasColumnType("boolean")
.HasColumnName("has_logo");
b.Property<string>("Password")
.IsRequired()
.HasMaxLength(100)
@ -2430,6 +2434,10 @@ namespace ASC.Migrations.PostgreSql.Migrations
.HasColumnType("integer")
.HasColumnName("foldersCount");
b.Property<bool>("HasLogo")
.HasColumnType("boolean")
.HasColumnName("has_logo");
b.Property<Guid>("ModifiedBy")
.HasMaxLength(38)
.HasColumnType("uuid")

View File

@ -19,7 +19,6 @@ const PureSettingsItem = ({
setExpandSettingsTree,
setSelectedFolder,
history,
setIsLoading,
t,
showText,
toggleArticleOpen,
@ -27,10 +26,8 @@ const PureSettingsItem = ({
const { setting } = match.params;
React.useEffect(() => {
setIsLoading(true);
setSelectedNode([setting]);
setIsLoading(false);
}, [setting, setIsLoading, setSelectedNode]);
}, [setting, setSelectedNode]);
React.useEffect(() => {
if (setting && !expandedSetting) setExpandSettingsTree(["settings"]);
@ -73,20 +70,13 @@ const SettingsItem = withTranslation(["FilesSettings", "Common"])(
);
export default inject(
({
auth,
filesStore,
settingsStore,
treeFoldersStore,
selectedFolderStore,
}) => {
const { setIsLoading } = filesStore;
({ auth, settingsStore, treeFoldersStore, selectedFolderStore }) => {
const { setSelectedFolder } = selectedFolderStore;
const { setSelectedNode } = treeFoldersStore;
const { expandedSetting, setExpandSettingsTree } = settingsStore;
return {
expandedSetting,
setIsLoading,
setSelectedFolder,
setSelectedNode,
setExpandSettingsTree,

View File

@ -101,13 +101,13 @@ const CreateEvent = ({
setStartValue(newValue);
}
// let tab =
// !isDesktop && extension && open
// ? window.open(
// combineUrl(AppServerConfig.proxyURL, config.homepage, `/doceditor`),
// "_blank"
// )
// : null;
let tab =
!isDesktop && extension && open
? window.open(
combineUrl(AppServerConfig.proxyURL, config.homepage, `/doceditor`),
"_blank"
)
: null;
if (!extension) {
createFolder(parentId, newValue)
@ -135,7 +135,7 @@ const CreateEvent = ({
createdFileId = file.id;
addActiveItems([file.id]);
open && openDocEditor(file.id, file.providerKey, null);
open && openDocEditor(file.id, file.providerKey, tab);
})
.then(() => editCompleteAction(item, type))
.catch((err) => {
@ -196,7 +196,7 @@ const CreateEvent = ({
setCreatedItem({ id: createdFileId, type: "file" });
addActiveItems([file.id]);
return open && openDocEditor(file.id, file.providerKey, null);
return open && openDocEditor(file.id, file.providerKey, tab);
})
.then(() => editCompleteAction(item, type))
.catch((e) => toastr.error(e))
@ -227,12 +227,12 @@ const CreateEvent = ({
true,
false
).then(
() => open && openDocEditor(file.id, file.providerKey, null)
() => open && openDocEditor(file.id, file.providerKey, tab)
);
});
}
return open && openDocEditor(file.id, file.providerKey, null);
return open && openDocEditor(file.id, file.providerKey, tab);
})
.then(() => editCompleteAction(item, type))
.catch((e) => toastr.error(e))

View File

@ -32,7 +32,6 @@ const EditRoomEvent = ({
withPaging,
reloadSelection,
getRoomLogo,
}) => {
const { t } = useTranslation(["CreateEditRoomDialog", "Common", "Files"]);
@ -107,12 +106,6 @@ const EditRoomEvent = ({
});
if (!withPaging) {
const newLogo = await getRoomLogo(room.logo);
room.logoHandlers = room.logo;
room.logo = newLogo;
room.isLogoLoading = false;
setFolder(room);
}
@ -125,12 +118,6 @@ const EditRoomEvent = ({
});
} else {
if (!withPaging) {
const newLogo = await getRoomLogo(room.logo);
room.logoHandlers = room.logo;
room.logo = newLogo;
room.isLogoLoading = false;
setFolder(room);
}
// to update state info panel
@ -149,9 +136,7 @@ const EditRoomEvent = ({
};
useEffect(async () => {
const logo = item?.logo?.original
? item.logo.original
: await api.rooms.getLogoIcon(item?.logoHandlers?.original);
const logo = item?.logo?.original ? item.logo.original : "";
if (logo) {
const imgExst = logo.slice(".")[1];
@ -212,7 +197,6 @@ export default inject(
setFolder,
addLogoToRoom,
removeLogoFromRoom,
getRoomLogo,
} = filesStore;
const { createTag, fetchTags } = tagsStore;
@ -226,7 +210,6 @@ export default inject(
editRoom,
addTagsToRoom,
removeTagsFromRoom,
getRoomLogo,
createTag,
fetchTags,

View File

@ -37,7 +37,10 @@ const InvitePanel = ({
adminLink,
defaultAccess,
inviteUsers,
setInfoPanelIsMobileHidden,
reloadSelectionParentRoom,
setUpdateRoomMembers,
roomsView,
}) => {
const [selectedRoom, setSelectedRoom] = useState(null);
const [hasErrors, setHasErrors] = useState(false);
@ -118,6 +121,7 @@ const InvitePanel = ({
}, [inviteItems]);
const onClose = () => {
setInfoPanelIsMobileHidden(false);
setInvitePanelOptions({
visible: false,
hideSelector: false,
@ -160,6 +164,8 @@ const InvitePanel = ({
roomId === -1
? await inviteUsers(data)
: await setRoomSecurity(roomId, data);
if (roomsView === "info_members") setUpdateRoomMembers(true);
onClose();
toastr.success(t("Common:UsersInvited"));
reloadSelectionParentRoom();
@ -244,7 +250,13 @@ export default inject(({ auth, peopleStore, filesStore, dialogsStore }) => {
const { theme } = auth.settingsStore;
const { getUsersByQuery, inviteUsers } = peopleStore.usersStore;
const { reloadSelectionParentRoom } = auth.infoPanelStore;
const {
setIsMobileHidden: setInfoPanelIsMobileHidden,
reloadSelectionParentRoom,
setUpdateRoomMembers,
roomsView,
filesView,
} = auth.infoPanelStore;
const {
getPortalInviteLinks,
@ -285,7 +297,10 @@ export default inject(({ auth, peopleStore, filesStore, dialogsStore }) => {
guestLink,
adminLink,
inviteUsers,
setInfoPanelIsMobileHidden,
reloadSelectionParentRoom,
setUpdateRoomMembers,
roomsView,
};
})(
withTranslation([

View File

@ -30,10 +30,7 @@ const FilesItemTitle = ({
</StyledTitle>
);
const icon =
selection?.isRoom && selection?.logo?.medium
? selection.logo.medium
: selection.icon;
const icon = selection.icon;
return (
<StyledTitle ref={itemTitleRef}>

View File

@ -22,7 +22,6 @@ const Details = ({
isVisitor,
}) => {
const [itemProperties, setItemProperties] = useState([]);
const [largeLogoIcon, setLargeLogoIcon] = useState("");
const [isThumbnailError, setIsThumbmailError] = useState(false);
const onThumbnailError = () => setIsThumbmailError(true);
@ -39,24 +38,9 @@ const Details = ({
culture,
});
const getLargeRoomLogo = React.useCallback(
async (url) => {
if (selection?.logo?.large) return setLargeLogoIcon(selection.logo.large);
const icon = await api.rooms.getLogoIcon(url);
setLargeLogoIcon(icon);
},
[selection?.logo?.large]
);
useEffect(async () => {
setItemProperties(detailsHelper.getPropertyList());
if ((selection?.isRoom || selection?.roomType) && !selection.isArchive) {
getLargeRoomLogo(selection?.logoHandlers?.large);
}
if (
!selection.isFolder &&
selection.thumbnailStatus === 0 &&
@ -67,11 +51,12 @@ const Details = ({
) {
await createThumbnail(selection.id);
}
}, [selection, getLargeRoomLogo]);
}, [selection]);
const currentIcon = largeLogoIcon
? largeLogoIcon
: getInfoPanelItemIcon(selection, 96);
const currentIcon =
!selection.isArchive && selection?.logo?.large
? selection?.logo?.large
: getInfoPanelItemIcon(selection, 96);
return (
<>
@ -89,7 +74,10 @@ const Details = ({
<StyledNoThumbnail>
<img
className={`no-thumbnail-img ${selection.isRoom && "is-room"} ${
selection.isRoom && selection.logo?.large && "custom-logo"
selection.isRoom &&
!selection.isArchive &&
selection.logo?.large &&
"custom-logo"
}`}
src={currentIcon}
alt="thumbnail-icon-big"

View File

@ -21,6 +21,10 @@ const Members = ({
isAdmin,
selection,
setIsMobileHidden,
updateRoomMembers,
setUpdateRoomMembers,
selectionParentRoom,
setSelectionParentRoom,
@ -64,6 +68,7 @@ const Members = ({
});
setShowLoader(false);
setUpdateRoomMembers(false);
return {
inRoom: inRoomMembers,
expected: expectedMembers,
@ -95,7 +100,20 @@ const Members = ({
});
}, [selection]);
useEffect(async () => {
if (!updateRoomMembers) return;
const fetchedMembers = await fetchMembers(selection.id);
setSelectionParentRoom({
...selectionParentRoom,
members: fetchedMembers,
});
setMembers(fetchedMembers);
}, [selectionParentRoom, selection?.id, updateRoomMembers]);
const onClickInviteUsers = () => {
setIsMobileHidden(true);
const parentRoomId = selectionParentRoom.id;
setInvitePanelOptions({
@ -205,7 +223,15 @@ const Members = ({
export default inject(
({ auth, filesStore, peopleStore, dialogsStore, accessRightsStore }) => {
const { selectionParentRoom, setSelectionParentRoom } = auth.infoPanelStore;
const {
setIsMobileHidden,
selectionParentRoom,
setSelectionParentRoom,
roomsView,
updateRoomMembers,
setUpdateRoomMembers,
} = auth.infoPanelStore;
const {
getRoomMembers,
updateRoomMemberRole,
@ -221,12 +247,16 @@ export default inject(
} = accessRightsStore;
return {
setIsMobileHidden,
selectionParentRoom,
setSelectionParentRoom,
getRoomMembers,
updateRoomMemberRole,
updateRoomMembers,
setUpdateRoomMembers,
isOwner,
isAdmin,
selfId,

View File

@ -231,7 +231,7 @@ const SimpleFilesRow = (props) => {
const element = (
<ItemIcon
id={item.id}
icon={item.isRoom && item.logo.medium ? item.logo.medium : item.icon}
icon={item.icon}
fileExst={item.fileExst}
isRoom={item.isRoom}
/>

View File

@ -324,7 +324,7 @@ const FilesTableRow = (props) => {
const element = (
<ItemIcon
id={item.id}
icon={item.isRoom && item.logo.medium ? item.logo.medium : item.icon}
icon={item.icon}
fileExst={item.fileExst}
isRoom={item.isRoom}
/>

View File

@ -68,7 +68,7 @@ const FileTile = (props) => {
const element = (
<ItemIcon
id={item.id}
icon={item.isRoom && item.logo.medium ? item.logo.medium : item.icon}
icon={item.icon}
fileExst={item.fileExst}
isRoom={item.isRoom}
/>

View File

@ -263,6 +263,8 @@ class ContextOptionsStore {
};
gotoDocEditor = (preview = false, item) => {
const { isDesktopClient } = this.authStore.settingsStore;
const { id, providerKey, fileExst } = item;
const urlFormation = preview
@ -274,13 +276,9 @@ class ContextOptionsStore {
: null;
let tab =
!this.authStore.isDesktopClient && fileExst
!isDesktopClient && fileExst
? window.open(
combineUrl(
AppServerConfig.proxyURL,
config.homepage,
`/doceditor?fileId=${id}`
),
combineUrl(AppServerConfig.proxyURL, config.homepage, `/doceditor`),
"_blank"
)
: null;

View File

@ -277,6 +277,7 @@ class FilesActionStore {
this.isMediaOpen();
try {
this.filesStore.setOperationAction(true);
await removeFiles(folderIds, fileIds, deleteAfter, immediately)
.then(async (res) => {
if (res[0]?.error) return Promise.reject(res[0].error);
@ -330,6 +331,8 @@ class FilesActionStore {
});
setTimeout(() => clearSecondaryProgressData(), TIMEOUT);
return toastr.error(err.message ? err.message : err);
} finally {
this.filesStore.setOperationAction(false);
}
}
};
@ -675,24 +678,28 @@ class FilesActionStore {
label: translations?.deleteOperation,
};
this.filesStore.setOperationAction(true);
if (isFile) {
addActiveItems([itemId]);
this.isMediaOpen();
return deleteFile(itemId).then(async (res) => {
if (res[0]?.error) return Promise.reject(res[0].error);
const data = res[0] ? res[0] : null;
await this.uploadDataStore.loopFilesOperations(data, pbData);
return deleteFile(itemId)
.then(async (res) => {
if (res[0]?.error) return Promise.reject(res[0].error);
const data = res[0] ? res[0] : null;
await this.uploadDataStore.loopFilesOperations(data, pbData);
if (withPaging) {
this.updateCurrentFolder([itemId]);
toastr.success(translations.successRemoveFile);
} else {
this.updateFilesAfterDelete();
this.filesStore.removeFiles([itemId], null, () =>
toastr.success(translations.successRemoveFile)
);
}
});
if (withPaging) {
this.updateCurrentFolder([itemId]);
toastr.success(translations.successRemoveFile);
} else {
this.updateFilesAfterDelete();
this.filesStore.removeFiles([itemId], null, () =>
toastr.success(translations.successRemoveFile)
);
}
})
.finally(() => this.filesStore.setOperationAction(false));
} else if (isRoom) {
const items = Array.isArray(itemId) ? itemId : [itemId];
addActiveItems(null, items);
@ -715,23 +722,25 @@ class FilesActionStore {
);
} else {
addActiveItems(null, [itemId]);
return deleteFolder(itemId).then(async (res) => {
if (res[0]?.error) return Promise.reject(res[0].error);
const data = res[0] ? res[0] : null;
await this.uploadDataStore.loopFilesOperations(data, pbData);
return deleteFolder(itemId)
.then(async (res) => {
if (res[0]?.error) return Promise.reject(res[0].error);
const data = res[0] ? res[0] : null;
await this.uploadDataStore.loopFilesOperations(data, pbData);
if (withPaging) {
this.updateCurrentFolder(null, [itemId]);
toastr.success(translations.successRemoveFolder);
} else {
this.updateFilesAfterDelete([itemId]);
this.filesStore.removeFiles(null, [itemId], () =>
toastr.success(translations.successRemoveFolder)
);
}
if (withPaging) {
this.updateCurrentFolder(null, [itemId]);
toastr.success(translations.successRemoveFolder);
} else {
this.updateFilesAfterDelete([itemId]);
this.filesStore.removeFiles(null, [itemId], () =>
toastr.success(translations.successRemoveFolder)
);
}
getIsEmptyTrash();
});
getIsEmptyTrash();
})
.finally(() => this.filesStore.setOperationAction(false));
}
};

View File

@ -27,6 +27,7 @@ import { isDesktop } from "@docspace/components/utils/device";
import { getContextMenuKeysByType } from "SRC_DIR/helpers/plugins";
import { PluginContextMenuItemType } from "SRC_DIR/helpers/plugins/constants";
import { getArchiveRoomRoleActions } from "@docspace/common/utils/actions";
import debounce from "lodash.debounce";
const { FilesFilter, RoomsFilter } = api;
const storageViewAs = localStorage.getItem("viewAs");
@ -102,7 +103,12 @@ class FilesStore {
isEmptyPage = false;
isLoadedFetchFiles = false;
tempActionFilesIds = [];
operationAction = false;
isErrorRoomNotAvailable = false;
constructor(
authStore,
selectedFolderStore,
@ -128,7 +134,7 @@ class FilesStore {
socketHelper.on("s:modify-folder", async (opt) => {
console.log("[WS] s:modify-folder", opt);
if (this.isLoading) return;
if (this.isLoading || this.operationAction) return;
switch (opt?.cmd) {
case "create":
@ -203,15 +209,23 @@ class FilesStore {
this.files[foundIndex].title
);
this.setFiles(
this.files.filter((_, index) => {
return index !== foundIndex;
})
);
// this.setFiles(
// this.files.filter((_, index) => {
// return index !== foundIndex;
// })
// );
const newFilter = this.filter.clone();
newFilter.total -= 1;
this.setFilter(newFilter);
// const newFilter = this.filter.clone();
// newFilter.total -= 1;
// this.setFilter(newFilter);
const tempActionFilesIds = JSON.parse(
JSON.stringify(this.tempActionFilesIds)
);
tempActionFilesIds.push(this.files[foundIndex].id);
this.setTempActionFilesIds(tempActionFilesIds);
this.debounceRemoveFiles();
// Hide pagination when deleting files
runInAction(() => {
@ -239,7 +253,10 @@ class FilesStore {
// `selected folder id ${this.selectedFolderStore.id} an changed folder id ${id}`
//);
if (this.selectedFolderStore.id == id) {
if (
this.selectedFolderStore.id == id &&
this.authStore.settingsStore.withPaging //TODO: no longer deletes the folder in other tabs
) {
console.log("[WS] refresh-folder", id);
this.fetchFiles(id, this.filter);
}
@ -317,6 +334,18 @@ class FilesStore {
});
}
debounceRemoveFiles = debounce(() => {
this.removeFiles(this.tempActionFilesIds);
}, 1000);
setTempActionFilesIds = (tempActionFilesIds) => {
this.tempActionFilesIds = tempActionFilesIds;
};
setOperationAction = (operationAction) => {
this.operationAction = operationAction;
};
updateSelectionStatus = (id, status, isEditing) => {
const index = this.selection.findIndex((x) => x.id === id);
@ -1050,8 +1079,6 @@ class FilesStore {
this.setCreatedItem(null);
}
this.updateRoomLoadingLogo();
this.isErrorRoomNotAvailable = false;
return Promise.resolve(selectedFolder);
})
@ -1832,9 +1859,13 @@ class FilesStore {
showToast && showToast();
})
.catch(() => {
.catch((err) => {
toastr.error(err);
console.log("Need page reload");
})
.finally(() => {
this.setOperationAction(false);
this.setTempActionFilesIds([]);
});
};
@ -2027,48 +2058,6 @@ class FilesStore {
return folderUrl;
};
getRoomLogo = async (logoHandlers) => {
const newLogos = {};
for (let key in logoHandlers) {
let icon = "";
if (key === "medium") {
icon = await api.rooms.getLogoIcon(logoHandlers[key]);
// check for null
icon = icon ? icon : "";
}
newLogos[key] = icon;
}
return newLogos;
};
updateRoomLoadingLogo = async () => {
const newRooms = await Promise.all(
this.folders.map(async (f) => {
const newRoom = JSON.parse(JSON.stringify(f));
if (!newRoom.isLogoLoading) return newRoom;
newRoom.isLogoLoading = false;
newRoom.logo = await this.getRoomLogo(newRoom.logoHandlers);
return newRoom;
})
);
if (
(this.treeFoldersStore.isRoomsFolder ||
this.treeFoldersStore.isArchiveFolder) &&
this.selectedFolderStore.navigationPath.length === 0
) {
this.setFolders(newRooms);
}
};
get filesList() {
const { getIcon } = this.filesSettingsStore;
//return [...this.folders, ...this.files];
@ -2099,8 +2088,6 @@ class FilesStore {
foldersCount,
id,
logo,
logoHandlers,
isLogoLoading,
locked,
parentId,
pureContentLength,
@ -2150,14 +2137,6 @@ class FilesStore {
const isThirdPartyFolder = providerKey && id === rootFolderId;
const iconSize = this.viewAs === "table" ? 24 : 32;
const icon = getIcon(
iconSize,
fileExst,
providerKey,
contentLength,
roomType,
isArchive
);
let isFolder = false;
this.folders.map((x) => {
@ -2188,6 +2167,18 @@ class FilesStore {
const isRoom = !!roomType;
const icon =
isRoom && !isArchive && logo?.medium
? logo?.medium
: getIcon(
iconSize,
fileExst,
providerKey,
contentLength,
roomType,
isArchive
);
return {
access,
//checked,
@ -2206,9 +2197,8 @@ class FilesStore {
icon,
id,
isFolder,
isLogoLoading,
logo,
logoHandlers,
locked,
new: item.new,
parentId,
@ -2846,8 +2836,6 @@ class FilesStore {
this.setFolders([...this.folders, ...newFiles.folders]);
this.setFilesIsLoading(false);
});
if (isRooms) this.updateRoomLoadingLogo();
};
//Duplicate of countTilesInRow, used to update the number of tiles in a row after the window is resized.

View File

@ -24,8 +24,8 @@ class SelectedFolderStore {
roomType = null;
pinned = null;
isRoom = null;
isArchive = null;
logo = null;
logoHandlers = null;
tags = null;
rootFolderId = null;
settingsStore = null;

View File

@ -431,7 +431,7 @@ class UploadDataStore {
}
});
// storeOriginalFiles && this.refreshFiles(file);
storeOriginalFiles && this.refreshFiles(file);
if (fileInfo && fileInfo !== "password") {
file.fileInfo = fileInfo;
@ -653,6 +653,8 @@ class UploadDataStore {
}
}
}
this.filesStore.setOperationAction(false);
};
const isFiltered =
@ -694,6 +696,7 @@ class UploadDataStore {
file,
path
) => {
this.filesStore.setOperationAction(true);
const length = requestsDataArray.length;
for (let index = 0; index < length; index++) {
if (
@ -769,9 +772,7 @@ class UploadDataStore {
return Promise.resolve();
} else {
if (currentFile.action === "uploaded") {
if (currentFile?.path?.length > 1) {
this.refreshFiles(currentFile);
}
this.refreshFiles(currentFile);
}
return Promise.resolve();
}

View File

@ -5,7 +5,7 @@ import { FolderType, RoomSearchArea } from "../../constants";
import find from "lodash/find";
import { getFolderOptions, decodeDisplayName } from "../../utils";
import { Encoder } from "../../utils/encoder";
import { getLogoIcon, getRooms } from "../rooms";
import { getRooms } from "../rooms";
import RoomsFilter from "../rooms/filter";
export function openEdit(fileId, version, doc, view) {
@ -39,45 +39,7 @@ export function getFolderInfo(folderId) {
url: `/files/folder/${folderId}`,
};
return request(options).then((res) => {
if (res.roomType) {
return new Promise((resolve, reject) => {
if (res.rootFolderType === FolderType.Archive) {
res.isLogoLoading = false;
for (let key in room.logo) {
room.logo[key] = "";
}
return resolve(res);
}
res.isLogoLoading = false;
res.logoHandlers = res.logo;
const newLogos = {};
const actions = [];
const getLogo = async (key) => {
const logo = await getLogoIcon(res.logo[key]);
newLogos[key] = logo;
};
for (let key in res.logo) {
actions.push(getLogo(key));
}
return Promise.all(actions).then(() => {
res.logo = newLogos;
resolve(res);
});
});
}
return res;
});
return request(options);
}
export function getFolderPath(folderId) {
@ -95,40 +57,9 @@ export function getFolder(folderId, filter) {
res.files = decodeDisplayName(res.files);
res.folders = decodeDisplayName(res.folders);
const { current } = res;
if (current.roomType) {
res.current.isLogoLoading = false;
res.current.logoHandlers = current.logo;
if (current.rootFolderType === FolderType.Rooms) {
return new Promise((resolve, reject) => {
const actions = [];
const newLogos = {};
const getLogo = async (key) => {
const logo = await getLogoIcon(current.logo[key]);
newLogos[key] = logo;
};
for (let key in current.logo) {
actions.push(getLogo(key));
}
return Promise.all(actions).then(() => {
res.current.logo = newLogos;
resolve(res);
});
});
} else {
for (let key in res.current.logo) {
res.current.logo[key] = "";
}
}
}
res.current.isArchive =
!!res.current.roomType &&
res.current.rootFolderType === FolderType.Archive;
return res;
});

View File

@ -15,23 +15,6 @@ export function getRooms(filter) {
if (res.current.rootFolderType === FolderType.Archive) {
res.folders.forEach((room) => {
room.isArchive = true;
room.isLogoLoading = false;
for (let key in room.logo) {
room.logo[key] = "";
}
});
} else {
res.folders.forEach((f, index) => {
res.folders[index].isLogoLoading = true;
res.folders[index].logoHandlers = f.logo;
const newLogos = {};
for (let key in f.logo) {
newLogos[key] = "";
}
res.folders[index].logo = newLogos;
});
}
@ -39,60 +22,16 @@ export function getRooms(filter) {
});
}
export function getLogoIcon(url) {
if (!url) return "";
const options = {
// baseURL: combineUrl(AppServerConfig.proxyURL, config.homepage),
method: "get",
url: `/products/files/httphandlers${url}`,
responseType: "text",
};
return request(options);
}
export function getRoomInfo(id) {
const options = {
method: "get",
url: `/files/rooms/${id}`,
};
return request(options).then(async (res) => {
return new Promise((resolve, reject) => {
if (res.rootFolderType === FolderType.Archive) {
res.isLogoLoading = false;
res.isArchive = true;
for (let key in res.logo) {
res.logo[key] = "";
}
return request(options).then((res) => {
if (res.rootFolderType === FolderType.Archive) res.isArchive = true;
return resolve(res);
}
res.isLogoLoading = false;
res.logoHandlers = res.logo;
const newLogos = {};
const actions = [];
const getLogo = async (key) => {
const logo = await getLogoIcon(res.logo[key]);
newLogos[key] = logo;
};
for (let key in res.logo) {
actions.push(getLogo(key));
}
return Promise.all(actions).then(() => {
res.logo = newLogos;
resolve(res);
});
});
return res;
});
}

View File

@ -77,13 +77,11 @@ const FilterBlockItem = ({
return !item.isSelected ||
item.selectedKey === "me" ||
item.selectedKey === "other" ? (
<StyledFilterBlockItemSelector key={item.key}>
<SelectorAddButton
onClick={(event) =>
showSelectorAction(event, isAuthor, item.group, [])
}
id="filter_add-author"
/>
<StyledFilterBlockItemSelector
key={item.key}
onClick={(event) => showSelectorAction(event, isAuthor, item.group, [])}
>
<SelectorAddButton id="filter_add-author" />
<StyledFilterBlockItemSelectorText noSelect={true}>
{item.label}
</StyledFilterBlockItemSelectorText>

View File

@ -151,8 +151,8 @@ const StyledFilterBlockItemSelectorText = styled(Text)`
font-size: 13px;
line-height: 15px;
color: ${(props) => props.theme.filterInput.filter.color};
margin-left: 8px;
cursor: pointer;
`;
StyledFilterBlockItemSelectorText.defaultProps = { theme: Base };

View File

@ -83,11 +83,10 @@ const StyledInfoPanel = styled.div`
const StyledControlContainer = styled.div`
display: none;
width: 24px;
height: 24px;
width: 17px;
height: 17px;
position: absolute;
border-radius: 100px;
cursor: pointer;
align-items: center;
@ -97,22 +96,22 @@ const StyledControlContainer = styled.div`
@media ${tablet} {
display: flex;
top: 16px;
left: -34px;
top: 18px;
left: -27px;
}
${isMobile &&
css`
display: flex;
top: 16px;
left: -34px;
top: 18px;
left: -27px;
`}
@media (max-width: 428px) {
display: flex;
top: -34px;
top: -27px;
right: 10px;
left: unset;
}
@ -134,11 +133,14 @@ StyledCrossIcon.defaultProps = { theme: Base };
const InfoPanel = ({
children,
isVisible,
isMobileHidden,
setIsVisible,
canDisplay,
viewAs,
}) => {
if (!isVisible || !canDisplay) return null;
if ((isTablet() || isMobile || isMobileUtils()) && isMobileHidden)
return null;
const closeInfoPanel = () => setIsVisible(false);
@ -180,13 +182,14 @@ const InfoPanel = ({
);
const renderPortalInfoPanel = () => {
console.log(isMobileHidden);
const rootElement = document.getElementById("root");
return (
<Portal
element={infoPanelComponent}
appendTo={rootElement}
visible={isVisible}
visible={isVisible && !isMobileHidden}
/>
);
};
@ -208,12 +211,18 @@ StyledInfoPanel.defaultProps = { theme: Base };
InfoPanel.defaultProps = { theme: Base };
export default inject(({ auth }) => {
const { isVisible, setIsVisible, getCanDisplay } = auth.infoPanelStore;
const {
isVisible,
isMobileHidden,
setIsVisible,
getCanDisplay,
} = auth.infoPanelStore;
const canDisplay = getCanDisplay();
return {
isVisible,
isMobileHidden,
setIsVisible,
canDisplay,
};

View File

@ -19,6 +19,7 @@ const observedKeys = [
class InfoPanelStore {
isVisible = false;
isMobileHidden = false;
selection = null;
selectionParentRoom = null;
@ -26,6 +27,8 @@ class InfoPanelStore {
roomsView = "info_details";
fileView = "info_history";
updateRoomMembers = null;
authStore = null;
settingsStore = null;
peopleStore = null;
@ -40,6 +43,7 @@ class InfoPanelStore {
// Setters
setIsVisible = (bool) => (this.isVisible = bool);
setIsMobileHidden = (bool) => (this.isMobileHidden = bool);
setSelection = (selection) => {
if (this.getIsAccounts() && (!selection.email || !selection.displayName)) {
@ -57,6 +61,10 @@ class InfoPanelStore {
this.fileView = view === "info_members" ? "info_history" : view;
};
setUpdateRoomMembers = (updateRoomMembers) => {
this.updateRoomMembers = updateRoomMembers;
};
// Selection helpers //
getSelectedItems = () => {

View File

@ -78,29 +78,37 @@ const StyledAside = styled(Container)`
StyledAside.defaultProps = { theme: Base };
const StyledControlContainer = styled.div`
display: flex;
display: none;
width: 24px;
height: 24px;
width: 17px;
height: 17px;
position: absolute;
border-radius: 100px;
cursor: pointer;
align-items: center;
justify-content: center;
z-index: 450;
top: 14px;
left: -34px;
@media ${tablet} {
display: flex;
top: 18px;
left: -27px;
}
${isMobile &&
css`
top: 14px;
display: flex;
top: 18px;
left: -27px;
`}
@media (max-width: 428px) {
top: -34px;
display: flex;
top: -27px;
right: 10px;
left: unset;
}

View File

@ -110,7 +110,7 @@ public class FolderDtoHelper : FileEntryDtoHelper
result.Tags = folder.Tags.Select(t => t.Name);
}
result.Logo = _roomLogoManager.GetLogo(folder);
result.Logo = await _roomLogoManager.GetLogoAsync(folder);
result.RoomType = folder.FolderType switch
{
FolderType.FillingFormsRoom => RoomType.FillingFormsRoom,

View File

@ -35,6 +35,7 @@ public interface IProviderDao
IAsyncEnumerable<IProviderInfo> GetProvidersInfoAsync(Guid userId);
Task<int> SaveProviderInfoAsync(string providerKey, string customerTitle, AuthData authData, FolderType folderType);
Task<bool> UpdateProviderInfoAsync(int linkId, FolderType rootFolderType);
Task<bool> UpdateProviderInfoAsync(int linkId, bool hasLogo);
Task<bool> UpdateProviderInfoAsync(int linkId, string folderId, FolderType folderType, bool @private);
Task<int> UpdateProviderInfoAsync(int linkId, string customerTitle, AuthData authData, FolderType folderType, Guid? userId = null);
Task<int> UpdateBackupProviderInfoAsync(string providerKey, string customerTitle, AuthData authData);

View File

@ -446,6 +446,7 @@ internal class FolderDao : AbstractDao, IFolderDao<int>
toUpdate.CreateBy = folder.CreateBy;
toUpdate.ModifiedOn = _tenantUtil.DateTimeToUtc(folder.ModifiedOn);
toUpdate.ModifiedBy = folder.ModifiedBy;
toUpdate.HasLogo = folder.HasLogo;
await filesDbContext.SaveChangesAsync();

View File

@ -42,6 +42,7 @@ public class DbFilesThirdpartyAccount : BaseEntity, IDbFile, IDbSearch
public int TenantId { get; set; }
public string FolderId { get; set; }
public bool Private { get; set; }
public bool HasLogo { get; set; }
public override object[] GetKeys()
{
@ -137,6 +138,8 @@ public static class DbFilesThirdpartyAccountExtension
.UseCollation("utf8_general_ci");
entity.Property(e => e.Private).HasColumnName("private");
entity.Property(e => e.HasLogo).HasColumnName("has_logo");
});
}
public static void PgSqlAddDbFilesThirdpartyAccount(this ModelBuilder modelBuilder)
@ -188,7 +191,9 @@ public static class DbFilesThirdpartyAccountExtension
entity.Property(e => e.FolderId).HasColumnName("folder_id");
entity.Property(e => e.Private).HasColumnName("private");
entity.Property(e => e.Private).HasColumnName("private");
entity.Property(e => e.HasLogo).HasColumnName("has_logo");
});
}
}

View File

@ -44,6 +44,7 @@ public class DbFolder : IDbFile, IDbSearch, ISearchItem
public int FoldersCount { get; set; }
public int FilesCount { get; set; }
public bool Private { get; set; }
public bool HasLogo { get; set; }
[Ignore]
public string IndexName => Tables.Folder;
@ -130,6 +131,8 @@ public static class DbFolderExtension
.UseCollation("utf8_general_ci");
entity.Property(e => e.Private).HasColumnName("private");
entity.Property(e => e.HasLogo).HasColumnName("has_logo");
});
}
public static void PgSqlAddDbFolder(this ModelBuilder modelBuilder)
@ -178,6 +181,8 @@ public static class DbFolderExtension
.HasMaxLength(400);
entity.Property(e => e.Private).HasColumnName("private");
entity.Property(e => e.HasLogo).HasColumnName("has_logo");
});
}
}

View File

@ -73,6 +73,7 @@ public class Folder<T> : FileEntry<T>, IFolder
public string FolderUrl { get; set; }
public bool Pinned { get; set; }
public bool Private { get; set; }
public bool HasLogo { get; set; }
public override bool IsNew
{
get => Convert.ToBoolean(NewForMe);

View File

@ -124,6 +124,7 @@ internal abstract class BoxDaoBase : ThirdPartyProviderDao<BoxProviderInfo>
folder.FilesCount = boxFolder.ItemCollection != null ? boxFolder.ItemCollection.Entries.Count(item => item is BoxFile) : 0;
folder.FoldersCount = boxFolder.ItemCollection != null ? boxFolder.ItemCollection.Entries.Count(item => item is BoxFolder) : 0;
folder.Private = ProviderInfo.Private;
folder.HasLogo = ProviderInfo.HasLogo;
SetFolderType(folder, isRoot);
if (folder.CreateOn != DateTime.MinValue && folder.CreateOn.Kind == DateTimeKind.Utc)

View File

@ -57,6 +57,7 @@ internal class BoxProviderInfo : IProviderInfo
public FolderType FolderType { get; set; }
public string FolderId { get; set; }
public bool Private { get; set; }
public bool HasLogo { get; set; }
public string BoxRootId
{

View File

@ -128,6 +128,7 @@ internal abstract class DropboxDaoBase : ThirdPartyProviderDao<DropboxProviderIn
folder.ModifiedOn = isRoot ? ProviderInfo.CreateOn : default;
folder.Title = MakeFolderTitle(dropboxFolder);
folder.Private = ProviderInfo.Private;
folder.HasLogo = ProviderInfo.HasLogo;
SetFolderType(folder, isRoot);
if (folder.CreateOn != DateTime.MinValue && folder.CreateOn.Kind == DateTimeKind.Utc)

View File

@ -56,6 +56,7 @@ internal class DropboxProviderInfo : IProviderInfo
public FolderType FolderType { get; set; }
public string FolderId { get; set; }
public bool Private { get; set; }
public bool HasLogo { get; set; }
private readonly DropboxStorageDisposableWrapper _wrapper;
private readonly DropboxProviderInfoHelper _dropboxProviderInfoHelper;

View File

@ -140,6 +140,7 @@ internal abstract class GoogleDriveDaoBase : ThirdPartyProviderDao<GoogleDrivePr
folder.CreateOn = isRoot ? ProviderInfo.CreateOn : (driveEntry.CreatedTime ?? default);
folder.ModifiedOn = isRoot ? ProviderInfo.CreateOn : (driveEntry.ModifiedTime ?? default);
folder.Private = ProviderInfo.Private;
folder.HasLogo = ProviderInfo.HasLogo;
SetFolderType(folder, isRoot);
folder.Title = MakeFolderTitle(driveEntry);

View File

@ -60,6 +60,7 @@ internal class GoogleDriveProviderInfo : IProviderInfo
public FolderType FolderType { get; set; }
public string FolderId { get; set; }
public bool Private { get; set; }
public bool HasLogo { get; set; }
public string DriveRootId
{
get

View File

@ -127,6 +127,7 @@ internal abstract class OneDriveDaoBase : ThirdPartyProviderDao<OneDriveProvider
folder.CreateOn = isRoot ? ProviderInfo.CreateOn : (onedriveFolder.CreatedDateTime.HasValue ? _tenantUtil.DateTimeFromUtc(onedriveFolder.CreatedDateTime.Value.DateTime) : default);
folder.ModifiedOn = isRoot ? ProviderInfo.CreateOn : (onedriveFolder.LastModifiedDateTime.HasValue ? _tenantUtil.DateTimeFromUtc(onedriveFolder.LastModifiedDateTime.Value.DateTime) : default);
folder.Private = ProviderInfo.Private;
folder.HasLogo = ProviderInfo.HasLogo;
SetFolderType(folder, isRoot);
folder.Title = MakeItemTitle(onedriveFolder);

View File

@ -57,6 +57,7 @@ internal class OneDriveProviderInfo : IProviderInfo
public FolderType FolderType { get; set; }
public string FolderId { get; set; }
public bool Private { get; set; }
public bool HasLogo { get; set; }
private readonly OneDriveStorageDisposableWrapper _wrapper;
private readonly OneDriveProviderInfoHelper _oneDriveProviderInfoHelper;

View File

@ -229,6 +229,26 @@ internal class ProviderAccountDao : IProviderDao
return true;
}
public async Task<bool> UpdateProviderInfoAsync(int linkId, bool hasLogo)
{
using var filesDbContext = _dbContextFactory.CreateDbContext();
var forUpdate = await filesDbContext.ThirdpartyAccount
.Where(r => r.Id == linkId)
.Where(r => r.TenantId == TenantID)
.FirstOrDefaultAsync();
if (forUpdate == null)
{
return false;
}
forUpdate.HasLogo = hasLogo;
await filesDbContext.SaveChangesAsync();
return true;
}
public async Task<bool> UpdateProviderInfoAsync(int linkId, string folderId, FolderType roomType, bool @private)
{
using var filesDbContext = _dbContextFactory.CreateDbContext();
@ -496,6 +516,7 @@ internal class ProviderAccountDao : IProviderDao
var folderId = input.FolderId;
var createOn = _tenantUtil.DateTimeFromUtc(input.CreateOn);
var authData = new AuthData(input.Url, input.UserName, DecryptPassword(input.Password, id), token);
var hasLogo = input.HasLogo;
if (key == ProviderTypes.Box)
{
@ -515,6 +536,7 @@ internal class ProviderAccountDao : IProviderDao
box.FolderType = folderType;
box.FolderId = folderId;
box.Private = privateRoom;
box.HasLogo = hasLogo;
return box;
}
@ -537,6 +559,7 @@ internal class ProviderAccountDao : IProviderDao
drop.FolderType = folderType;
drop.FolderId = folderId;
drop.Private = privateRoom;
drop.HasLogo = hasLogo;
return drop;
}
@ -559,6 +582,7 @@ internal class ProviderAccountDao : IProviderDao
sh.FolderType = folderType;
sh.FolderId = folderId;
sh.Private = privateRoom;
sh.HasLogo = hasLogo;
return sh;
}
@ -581,6 +605,7 @@ internal class ProviderAccountDao : IProviderDao
gd.FolderType = folderType;
gd.FolderId = folderId;
gd.Private = privateRoom;
gd.HasLogo = hasLogo;
return gd;
}
@ -603,6 +628,7 @@ internal class ProviderAccountDao : IProviderDao
od.FolderType = folderType;
od.FolderId = folderId;
od.Private = privateRoom;
od.HasLogo = hasLogo;
return od;
}
@ -633,6 +659,7 @@ internal class ProviderAccountDao : IProviderDao
sharpBoxProviderInfo.FolderType = folderType;
sharpBoxProviderInfo.FolderId = folderId;
sharpBoxProviderInfo.Private = privateRoom;
sharpBoxProviderInfo.HasLogo = hasLogo;
return sharpBoxProviderInfo;
}

View File

@ -45,6 +45,7 @@ public class SharePointProviderInfo : IProviderInfo
public string SpRootFolderId { get; set; } = "/Shared Documents";
public string FolderId { get; set; }
public bool Private { get; set; }
public bool HasLogo { get; set; }
public SharePointProviderInfo(
ILogger<SharePointProviderInfo> logger,
@ -576,6 +577,7 @@ public class SharePointProviderInfo : IProviderInfo
result.FoldersCount = 0;
result.Error = errorFolder.Error;
result.Private = Private;
result.HasLogo = HasLogo;
return result;
}
@ -599,6 +601,7 @@ public class SharePointProviderInfo : IProviderInfo
result.FilesCount = 0;
result.FoldersCount = 0;
result.Private = Private;
result.HasLogo = HasLogo;
SetFolderType(result, isRoot);

View File

@ -310,6 +310,7 @@ internal abstract class SharpBoxDaoBase : ThirdPartyProviderDao<SharpBoxProvider
folder.FilesCount = 0; /*fsEntry.Count - childFoldersCount NOTE: Removed due to performance isssues*/
folder.FoldersCount = 0; /*childFoldersCount NOTE: Removed due to performance isssues*/
folder.Private = ProviderInfo.Private;
folder.HasLogo = ProviderInfo.HasLogo;
SetFolderType(folder, isRoot);
if (folder.CreateOn != DateTime.MinValue && folder.CreateOn.Kind == DateTimeKind.Utc)

View File

@ -112,6 +112,7 @@ internal class SharpBoxProviderInfo : IProviderInfo
public FolderType FolderType { get; set; }
public string FolderId { get; set; }
public bool Private { get; set; }
public bool HasLogo { get; set; }
private readonly SharpBoxStorageDisposableWrapper _wrapper;
}

View File

@ -31,16 +31,14 @@ namespace ASC.Files.Core.VirtualRooms;
[Scope]
public class RoomLogoManager
{
private const string LogosPath = "{0}_size_{1}-{2}.{3}";
private const string LogosPath = "{0}_{1}.png";
private const string ModuleName = "room_logos";
private const string TempDomainPath = "logos_temp";
private const string ActionName = "logo";
private const string Default = "default";
private static Size _originalLogoSize = new Size(1280, 1280);
private static Size _largeLogoSize = new Size(96, 96);
private static Size _mediumLogoSize = new Size(32, 32);
private static Size _smallLogoSize = new Size(16, 16);
private static (SizeName, Size) _originalLogoSize = (SizeName.Original, new Size(1280, 1280));
private static (SizeName, Size) _largeLogoSize = (SizeName.Large, new Size(96, 96));
private static (SizeName, Size) _mediumLogoSize = (SizeName.Medium, new Size(32, 32));
private static (SizeName, Size) _smallLogoSize = (SizeName.Small, new Size(16, 16));
private readonly IDaoFactory _daoFactory;
private readonly FileSecurity _fileSecurity;
@ -48,13 +46,8 @@ public class RoomLogoManager
private readonly StorageFactory _storageFactory;
private readonly TenantManager _tenantManager;
private IDataStore _dataStore;
private readonly ICache _cache;
private readonly FilesMessageService _filesMessageService;
private static readonly Regex _pattern = new Regex(@"\d+-\d+", RegexOptions.Compiled);
private static readonly Regex _cachePattern = new Regex(@"\d+\/\S+\/\d+\/\d+", RegexOptions.Compiled);
private static readonly TimeSpan _cacheLifeTime = TimeSpan.FromMinutes(30);
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly FilesLinkUtility _filesLinkUtility;
public RoomLogoManager(
StorageFactory storageFactory,
@ -62,20 +55,16 @@ public class RoomLogoManager
IDaoFactory daoFactory,
FileSecurity fileSecurity,
ILogger<RoomLogoManager> logger,
AscCache cache,
FilesMessageService filesMessageService,
IHttpContextAccessor httpContextAccessor,
FilesLinkUtility filesLinkUtility)
IHttpContextAccessor httpContextAccessor)
{
_storageFactory = storageFactory;
_tenantManager = tenantManager;
_daoFactory = daoFactory;
_fileSecurity = fileSecurity;
_logger = logger;
_cache = cache;
_filesMessageService = filesMessageService;
_httpContextAccessor = httpContextAccessor;
_filesLinkUtility = filesLinkUtility;
}
public bool EnableAudit { get; set; } = true;
@ -108,8 +97,19 @@ public class RoomLogoManager
id = GetId(room);
await DeleteLogo(id);
await SaveWithProcessAsync(id, data, -1, new Point(x, y), new Size(width, height));
await RemoveTempAsync(fileName);
room.HasLogo = true;
if (room.ProviderEntry)
{
await _daoFactory.ProviderDao.UpdateProviderInfoAsync(room.ProviderId, true);
}
else
{
await folderDao.SaveFolderAsync(room);
}
if (EnableAudit)
{
@ -133,14 +133,24 @@ public class RoomLogoManager
try
{
await DeleteLogo(id);
await DataStore.DeleteFilesAsync(string.Empty, $"{ProcessFolderId(id)}*.*", false);
room.HasLogo = false;
if (room.ProviderEntry)
{
await _daoFactory.ProviderDao.UpdateProviderInfoAsync(room.ProviderId, false);
}
else
{
await folderDao.SaveFolderAsync(room);
}
if (EnableAudit)
{
_filesMessageService.Send(room, Headers, MessageAction.RoomLogoDeleted);
}
}
catch (DirectoryNotFoundException e)
catch (Exception e)
{
_logger.ErrorRemoveRoomLogo(e);
}
@ -148,24 +158,35 @@ public class RoomLogoManager
return room;
}
public Logo GetLogo<T>(Folder<T> room)
public async ValueTask<Logo> GetLogoAsync<T>(Folder<T> room)
{
var id = room.Id;
return new Logo
if (!room.HasLogo)
{
Original = GetOriginalLogoUrl(id),
Large = GetLargeLogoUrl(id),
Medium = GetMediumLogoUrl(id),
Small = GetSmallLogoUrl(id)
return new Logo
{
Original = string.Empty,
Large = string.Empty,
Medium = string.Empty,
Small = string.Empty,
};
}
var id = GetId(room);
return new Logo()
{
Original = await GetLogoPathAsync(id, SizeName.Original),
Large = await GetLogoPathAsync(id, SizeName.Large),
Medium = await GetLogoPathAsync(id, SizeName.Medium),
Small = await GetLogoPathAsync(id, SizeName.Small),
};
}
public async Task<string> SaveTempAsync(byte[] data, long maxFileSize)
{
data = UserPhotoThumbnailManager.TryParseImage(data, maxFileSize, _originalLogoSize, out var imgFormat, out _, out _);
data = UserPhotoThumbnailManager.TryParseImage(data, maxFileSize, _originalLogoSize.Item2, out _, out _, out _);
var fileName = Guid.NewGuid() + "." + CommonPhotoManager.GetImgFormatName(imgFormat);
var fileName = $"{Guid.NewGuid()}.png";
using var stream = new MemoryStream(data);
var path = await DataStore.SaveAsync(TempDomainPath, fileName, stream);
@ -177,89 +198,31 @@ public class RoomLogoManager
if (pathAsString.IndexOf('?') > 0)
{
pathWithoutQuery = pathAsString.Substring(0, pathAsString.IndexOf('?'));
}
}
return pathWithoutQuery;
}
public string GetOriginalLogoUrl<T>(T id)
public async Task RemoveTempAsync(string fileName)
{
return GetLogoUrl(id, RoomLogoSize.Original);
}
var index = fileName.LastIndexOf('.');
var fileNameWithoutExt = (index != -1) ? fileName.Substring(0, index) : fileName;
public string GetLargeLogoUrl<T>(T id)
{
return GetLogoUrl(id, RoomLogoSize.Large);
}
public string GetMediumLogoUrl<T>(T id)
{
return GetLogoUrl(id, RoomLogoSize.Medium);
}
public string GetSmallLogoUrl<T>(T id)
{
return GetLogoUrl(id, RoomLogoSize.Small);
}
public async ValueTask<string> GetMediumLogoPathAsync<T>(T id)
{
return await GetLogoPathAsync(id, _mediumLogoSize);
}
public async ValueTask<string> GetSmallLogoPathAsync<T>(T id)
{
return await GetLogoPathAsync(id, _smallLogoSize);
}
public async ValueTask<string> GetLargeLogoPathAsync<T>(T id)
{
return await GetLogoPathAsync(id, _largeLogoSize);
}
public async ValueTask<string> GetOriginalLogoPathAsync<T>(T id)
{
return await GetLogoPathAsync(id, null, true);
}
public async Task<string> GetLogoPathAsync<T>(T id, string size)
{
var room = await _daoFactory.GetFolderDao<T>().GetFolderAsync(id);
if (room == null)
try
{
throw new ItemNotFoundException("Room not found");
await DataStore.DeleteFilesAsync(TempDomainPath, "", fileNameWithoutExt + "*.*", false);
}
if (!await _fileSecurity.CanReadAsync(room))
catch(Exception e)
{
throw new SecurityException("You don't have permission to read the room");
_logger.ErrorRemoveTempPhoto(e);
}
if (!RoomLogoSizeExtensions.TryParse(size, true, out var result))
{
throw new ArgumentException("Size not valid", nameof(size));
}
id = GetId(room);
return result switch
{
RoomLogoSize.Original => await GetOriginalLogoPathAsync(id),
RoomLogoSize.Large => await GetLargeLogoPathAsync(id),
RoomLogoSize.Medium => await GetMediumLogoPathAsync(id),
RoomLogoSize.Small => await GetSmallLogoPathAsync(id),
_ => throw new NotImplementedException()
};
}
private async Task<string> SaveWithProcessAsync<T>(T id, byte[] imageData, long maxFileSize, Point position, Size cropSize)
{
imageData = UserPhotoThumbnailManager.TryParseImage(imageData, maxFileSize, _originalLogoSize, out var imageFormat, out var width, out var height);
imageData = UserPhotoThumbnailManager.TryParseImage(imageData, maxFileSize, _originalLogoSize.Item2, out var _, out var _, out var _);
var imageExtension = CommonPhotoManager.GetImgFormatName(imageFormat);
var fileName = $"{ProcessFolderId(id)}_orig_{width}-{height}.{imageExtension}";
var fileName = string.Format(LogosPath, ProcessFolderId(id), SizeName.Original.ToStringLowerFast());
if (imageData == null || imageData.Length == 0)
{
@ -276,7 +239,7 @@ public class RoomLogoManager
return path.ToString();
}
private async Task ResizeAndSaveAsync<T>(T id, byte[] data, long maxFileSize, Size size, Point position, Size cropSize)
private async Task ResizeAndSaveAsync<T>(T id, byte[] data, long maxFileSize, (SizeName, Size) size, Point position, Size cropSize)
{
if (data == null || data.Length <= 0)
{
@ -293,9 +256,9 @@ public class RoomLogoManager
using var img = Image.Load(stream, out var format);
var imgFormat = format;
if (size != img.Size())
if (size.Item2 != img.Size())
{
using var img2 = UserPhotoThumbnailManager.GetImage(img, size, new UserPhotoThumbnailSettings(position, cropSize));
using var img2 = UserPhotoThumbnailManager.GetImage(img, size.Item2, new UserPhotoThumbnailSettings(position, cropSize));
data = CommonPhotoManager.SaveToBytes(img2);
}
else
@ -304,7 +267,7 @@ public class RoomLogoManager
}
var extension = CommonPhotoManager.GetImgFormatName(imgFormat);
var fileName = string.Format(LogosPath, ProcessFolderId(id), size.Width, size.Height, extension);
var fileName = string.Format(LogosPath, ProcessFolderId(id), size.Item1.ToStringLowerFast());
using var stream2 = new MemoryStream(data);
await DataStore.SaveAsync(fileName, stream2);
@ -315,33 +278,12 @@ public class RoomLogoManager
}
}
private string GetLogoUrl<T>(T id, RoomLogoSize size)
private async ValueTask<string> GetLogoPathAsync<T>(T id, SizeName size)
{
return $"{_filesLinkUtility.FileHandlerPath}?{FilesLinkUtility.Action}={ActionName}" +
$"&{FilesLinkUtility.FolderId}={Uri.EscapeDataString(id.ToString())}" +
$"&{FilesLinkUtility.Size}={size.ToStringLowerFast()}";
}
var fileName = string.Format(LogosPath, ProcessFolderId(id), size.ToStringLowerFast());
var uri = await DataStore.GetUriAsync(fileName);
private async ValueTask<string> GetLogoPathAsync<T>(T id, Size? size, bool original = false)
{
var key = original ? GetKey(id) : GetKey(id, size.Value);
var path = _cache.Get<string>(key);
if (path == Default)
{
return string.Empty;
}
if (!string.IsNullOrEmpty(path))
{
return await ValueTask.FromResult(path);
}
await LoadPathToCacheAsync(id);
path = _cache.Get<string>(key);
return path == null || path == Default ? string.Empty : path;
return uri.ToString();
}
private async Task<byte[]> GetTempAsync(string fileName)
@ -364,37 +306,6 @@ public class RoomLogoManager
return data.ToArray();
}
private async Task LoadPathToCacheAsync<T>(T id)
{
var logoPath = await DataStore.ListFilesAsync(string.Empty, $"{ProcessFolderId(id)}*", false)
.Select(u => u.ToString()).ToListAsync();
if (logoPath.Count == 0)
{
SetDefaultCache(id);
return;
}
var original = logoPath.Where(u => u.Contains("orig")).FirstOrDefault();
_cache.Insert(GetKey(id), original, _cacheLifeTime);
logoPath.Remove(original);
foreach (var (k, v) in logoPath.ToDictionary(p => _pattern.Match(p).Value.Split('-')))
{
_cache.Insert(GetKey(id, new Size(int.Parse(k[0]), int.Parse(k[1]))), v, _cacheLifeTime);
}
}
private async Task DeleteLogo<T>(T id)
{
await DataStore.DeleteFilesAsync(string.Empty, $"{ProcessFolderId(id)}*.*", false);
_cache.Remove(_cachePattern);
_cache.Remove(GetKey(id));
}
private string ProcessFolderId<T>(T id)
{
ArgumentNullException.ThrowIfNull(id, nameof(id));
@ -404,24 +315,6 @@ public class RoomLogoManager
: id.ToString()?.Replace("-", "").Replace("|", "");
}
private string GetKey<T>(T id, Size size)
{
return $"{TenantId}/{id}/{size.Width}/{size.Height}";
}
private string GetKey<T>(T id)
{
return $"{TenantId}/{id}/orig";
}
private void SetDefaultCache<T>(T id)
{
_cache.Insert(GetKey(id), Default, _cacheLifeTime);
_cache.Insert(GetKey(id, _largeLogoSize), Default, _cacheLifeTime);
_cache.Insert(GetKey(id, _mediumLogoSize), Default, _cacheLifeTime);
_cache.Insert(GetKey(id, _smallLogoSize), Default, _cacheLifeTime);
}
private T GetId<T>(Folder<T> room)
{
return room.ProviderEntry && (room.RootId.ToString().Contains("sbox")
@ -430,7 +323,7 @@ public class RoomLogoManager
}
[EnumExtensions]
public enum RoomLogoSize
public enum SizeName
{
Original = 0,
Large = 1,

View File

@ -196,9 +196,6 @@ public class FileHandlerService
case "track":
await TrackFile(context);
break;
case "logo":
await GetRoomLogoPathAsync(context);
break;
default:
throw new HttpException((int)HttpStatusCode.BadRequest, FilesCommonResource.ErrorMassage_BadRequest);
}
@ -1569,60 +1566,6 @@ public class FileHandlerService
await context.Response.WriteAsync(TrackResponse.Serialize(result));
}
private async Task GetRoomLogoPathAsync(HttpContext context)
{
if (!_securityContext.IsAuthenticated)
{
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return;
}
var folderId = context.Request.Query[FilesLinkUtility.FolderId].FirstOrDefault();
var size = context.Request.Query[FilesLinkUtility.Size].FirstOrDefault();
string result;
try
{
if (int.TryParse(folderId, out var id))
{
result = await _roomLogoManager.GetLogoPathAsync(id, size);
}
else
{
result = await _roomLogoManager.GetLogoPathAsync(folderId, size);
}
}
catch(ItemNotFoundException)
{
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
return;
}
catch (SecurityException)
{
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return;
}
catch
{
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
return;
}
context.Response.Clear();
await context.Response.WriteAsync(result);
try
{
await context.Response.Body.FlushAsync();
await context.Response.CompleteAsync();
}
catch (HttpException ex)
{
_logger.Error(ex.Message);
}
}
}
public static class FileHandlerExtensions

View File

@ -30,4 +30,7 @@ public static partial class RoomLogoManagerLogger
{
[LoggerMessage(Level = LogLevel.Error, Message = "RemoveRoomLogo")]
public static partial void ErrorRemoveRoomLogo(this ILogger<RoomLogoManager> logger, Exception exception);
[LoggerMessage(Level = LogLevel.Error, Message = "RemoveTempPhoto")]
public static partial void ErrorRemoveTempPhoto(this ILogger<RoomLogoManager> logger, Exception exception);
}