Merge branch 'develop' into bugfix/smart-banner
This commit is contained in:
commit
1cb56a31fe
@ -44,14 +44,16 @@ public static class CustomHealthCheck
|
||||
{
|
||||
hcBuilder.AddMySql(connectionString.ConnectionString,
|
||||
name: "mysqldb",
|
||||
tags: new string[] { "mysqldb" });
|
||||
tags: new string[] { "mysqldb" },
|
||||
timeout: new TimeSpan(0, 0, 15));
|
||||
}
|
||||
|
||||
if (string.Equals(connectionString.ProviderName, "Npgsql"))
|
||||
{
|
||||
hcBuilder.AddNpgSql(connectionString.ConnectionString,
|
||||
name: "postgredb",
|
||||
tags: new string[] { "postgredb" });
|
||||
tags: new string[] { "postgredb" },
|
||||
timeout: new TimeSpan(0, 0, 15));
|
||||
}
|
||||
|
||||
var kafkaSettings = configurationExtension.GetSetting<KafkaSettings>("kafka");
|
||||
@ -61,7 +63,9 @@ public static class CustomHealthCheck
|
||||
|
||||
hcBuilder.AddKafka(new ProducerConfig(clientConfig),
|
||||
name: "kafka",
|
||||
tags: new string[] { "kafka" });
|
||||
tags: new string[] { "kafka" },
|
||||
timeout: new TimeSpan(0,0,15)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@ -88,7 +92,8 @@ public static class CustomHealthCheck
|
||||
{
|
||||
hcBuilder.AddRedis(redisConfiguration.ConfigurationOptions.ToString(),
|
||||
name: "redis",
|
||||
tags: new string[] { "redis" });
|
||||
tags: new string[] { "redis" },
|
||||
timeout: new TimeSpan(0, 0, 15));
|
||||
}
|
||||
|
||||
var rabbitMQConfiguration = configuration.GetSection("RabbitMQ").Get<RabbitMQSettings>();
|
||||
@ -97,7 +102,8 @@ public static class CustomHealthCheck
|
||||
{
|
||||
hcBuilder.AddRabbitMQ(x => rabbitMQConfiguration.GetConnectionFactory(),
|
||||
name: "rabbitMQ",
|
||||
tags: new string[] { "rabbitMQ" });
|
||||
tags: new string[] { "rabbitMQ" },
|
||||
timeout: new TimeSpan(0, 0, 15));
|
||||
}
|
||||
|
||||
return services;
|
||||
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.5 KiB |
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 9.4 KiB |
@ -9,8 +9,9 @@
|
||||
"SubmenuHistory": "History",
|
||||
"SubmenuDetails": "Details",
|
||||
|
||||
"RecentActivities": "Recent activities",
|
||||
"UsersInRoom": "Users in room",
|
||||
"ExpectPeople": "Expect people",
|
||||
"RecentActivities": "Recent activities",
|
||||
"Properties": "Properties",
|
||||
"Data": "Data",
|
||||
|
||||
|
@ -38,7 +38,7 @@
|
||||
"SendRequest": "Send request",
|
||||
"TotalPricePerMonth": "<1>{{currencySymbol}}</1><2>{{price}}</2><3>/month</3>",
|
||||
"UpgradeNow": "Upgrade now",
|
||||
"UserNotFound": "User <1>«{{email}}»</1> is not found",
|
||||
"UserNotFound": "User <1>{{email}}</1> is not found",
|
||||
"YourPrice": "Your price",
|
||||
"PaymentOverdue": "Cannot add new users.",
|
||||
"BusinessPlanPaymentOverdue": "Cannot add new users. Business plan payment overdue",
|
||||
|
@ -25,6 +25,7 @@
|
||||
"SuccessChangeUserStatus": "The user status was successfully changed",
|
||||
"SuccessDeletePersonalData": "Personal data has been successfully deleted",
|
||||
"SuccessSentInvitation": "The invitation was successfully sent",
|
||||
"SuccessSentMultipleInvitatios": "Invitations were successfully sent",
|
||||
"maxSizeFileError": "Maximum file size exceeded",
|
||||
"orDropFileHereLabel": "or drop a file here",
|
||||
"selectNewPhotoLabel": "Select new photo"
|
||||
|
@ -9,8 +9,9 @@
|
||||
"SubmenuHistory": "История",
|
||||
"SubmenuDetails": "Детали",
|
||||
|
||||
"RecentActivities": "Недавние действия",
|
||||
"UsersInRoom": "Пользователей в комнате",
|
||||
"ExpectPeople": "Приглашенные люди",
|
||||
"RecentActivities": "Недавние действия",
|
||||
"Properties": "Cвойства",
|
||||
"Data": "Данные",
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
"ActivateBusinessPlan": "Активировать {{planName}} план?",
|
||||
"AdministratorDescription": "Настройка DocSpace, создание и администрирование комнат, возможность приглашать пользователей и управлять ими в DocSpace и в виртуальных комнатах, возможность управлять правами доступа.",
|
||||
"Benefits": "Преимущества",
|
||||
"PlanTitle": "Вы используете {{planName}} план",
|
||||
"BusinessTitle": "Вы используете {{planName}} план",
|
||||
"BusinessSuggestion": "Настройте свой {{planName}} план",
|
||||
"BusinessFinalDateInfo": "Подписка будет автоматически продлена {{finalDate}} с обновленными ценами и техническими характеристиками. Вы можете отменить его или изменить свою платежную информацию на клиентский портал Stripe.",
|
||||
"BusinessRequestDescription": "Тарифные планы с более чем {{peopleNumber}} менеджерами доступны только по запросу",
|
||||
@ -37,6 +37,6 @@
|
||||
"SendRequest": "Отправить запрос",
|
||||
"TotalPricePerMonth": "<1>{{currencySymbol}}</1><2>{{price}}</2><3>/месяц</3>",
|
||||
"UpgradeNow": "Обновить прямо сейчас",
|
||||
"UserNotFound": "Пользователь <1>«{{email}}»</1> не найден",
|
||||
"UserNotFound": "Пользователь <1>{{email}}</1> не найден",
|
||||
"YourPrice": "Ваша стоимость"
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
"SuccessChangeUserStatus": "Статус пользователя успешно изменен",
|
||||
"SuccessDeletePersonalData": "Персональные данные успешно удалены",
|
||||
"SuccessSentInvitation": "Приглашение было успешно отправлено",
|
||||
"SuccessSentMultipleInvitatios": "Приглашения были успешно отправлены",
|
||||
"maxSizeFileError": "Превышен максимальный размер файла",
|
||||
"orDropFileHereLabel": "или перетащите файл сюда",
|
||||
"selectNewPhotoLabel": "Выбрать новое фото"
|
||||
|
@ -104,7 +104,6 @@ const RenameEvent = ({
|
||||
clearTimeout(timerId);
|
||||
timerId = null;
|
||||
clearActiveOperations(null, [item.id]);
|
||||
|
||||
onClose();
|
||||
});
|
||||
}, []);
|
||||
|
@ -28,6 +28,7 @@ import { getLink, checkIfModuleOld, onItemClick } from "SRC_DIR/helpers/utils";
|
||||
import StyledExternalLinkIcon from "@docspace/client/src/components/StyledExternalLinkIcon";
|
||||
import HeaderCatalogBurger from "./header-catalog-burger";
|
||||
import { Base } from "@docspace/components/themes";
|
||||
import { ReactSVG } from "react-svg";
|
||||
|
||||
const { proxyURL } = AppServerConfig;
|
||||
|
||||
@ -57,6 +58,12 @@ const Header = styled.header`
|
||||
transform: translateX(50%);
|
||||
height: 24px;
|
||||
cursor: pointer;
|
||||
|
||||
svg {
|
||||
path:last-child {
|
||||
fill: ${(props) => props.theme.client.home.logoColor};
|
||||
}
|
||||
}
|
||||
}
|
||||
.mobile-short-logo {
|
||||
width: 146px;
|
||||
@ -225,7 +232,15 @@ const HeaderComponent = ({
|
||||
!isFormGallery && <HeaderCatalogBurger onClick={toggleArticleOpen} />}
|
||||
<LinkWithoutRedirect className="header-logo-wrapper" to={defaultPage}>
|
||||
{!isPersonal ? (
|
||||
<img alt="logo" src={props.logoUrl} className="header-logo-icon" />
|
||||
props.logoUrl.includes(".svg") ? (
|
||||
<ReactSVG src={props.logoUrl} className="header-logo-icon" />
|
||||
) : (
|
||||
<img
|
||||
alt="logo"
|
||||
src={props.logoUrl}
|
||||
className="header-logo-icon"
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
<img
|
||||
alt="logo"
|
||||
|
@ -35,6 +35,7 @@ const InvitePanel = ({
|
||||
adminLink,
|
||||
defaultAccess,
|
||||
inviteUsers,
|
||||
reloadSelectionParentRoom,
|
||||
}) => {
|
||||
const [selectedRoom, setSelectedRoom] = useState(null);
|
||||
const [hasErrors, setHasErrors] = useState(false);
|
||||
@ -159,6 +160,7 @@ const InvitePanel = ({
|
||||
: await setRoomSecurity(roomId, data);
|
||||
onClose();
|
||||
toastr.success(`Users invited`);
|
||||
reloadSelectionParentRoom();
|
||||
} catch (err) {
|
||||
toastr.error(err);
|
||||
}
|
||||
@ -225,6 +227,7 @@ export default inject(({ auth, peopleStore, filesStore, dialogsStore }) => {
|
||||
const { theme } = auth.settingsStore;
|
||||
|
||||
const { getUsersByQuery, inviteUsers } = peopleStore.usersStore;
|
||||
const { reloadSelectionParentRoom } = auth.infoPanelStore;
|
||||
|
||||
const {
|
||||
getPortalInviteLinks,
|
||||
@ -265,6 +268,7 @@ export default inject(({ auth, peopleStore, filesStore, dialogsStore }) => {
|
||||
guestLink,
|
||||
adminLink,
|
||||
inviteUsers,
|
||||
reloadSelectionParentRoom,
|
||||
};
|
||||
})(
|
||||
withTranslation([
|
||||
|
@ -57,6 +57,9 @@ const StyledAboutBody = styled.div`
|
||||
}
|
||||
|
||||
.logo-docspace-theme {
|
||||
height: 24px;
|
||||
width: 211px;
|
||||
|
||||
svg {
|
||||
path:nth-child(4) {
|
||||
fill: ${(props) => props.theme.client.about.logoColor};
|
||||
@ -107,7 +110,7 @@ const AboutContent = (props) => {
|
||||
className="logo-theme no-select"
|
||||
/>
|
||||
) : (
|
||||
<ReactSVG
|
||||
<img
|
||||
src={docSpaceLogo}
|
||||
alt="Logo"
|
||||
className="logo-docspace-theme no-select"
|
||||
|
@ -6,46 +6,51 @@ const excludeOptionsIntoFolder = ["open", "separator0", "separator1"];
|
||||
class ContextHelper {
|
||||
constructor(props) {
|
||||
this.t = props.t;
|
||||
this.selection = { ...props.selection };
|
||||
this.isUser = props.isUser;
|
||||
this.selection = props.selection;
|
||||
this.getContextOptions = props.getContextOptions;
|
||||
this.getUserContextOptions = props.getUserContextOptions;
|
||||
this.getContextOptionActions = props.getContextOptionActions;
|
||||
|
||||
this.selectedFolderId = props.selectedFolderId;
|
||||
|
||||
if (this.selection) this.fixItemContextOptions();
|
||||
}
|
||||
|
||||
fixItemContextOptions = () => {
|
||||
if (this.isUser) {
|
||||
if (!this.selection?.options) return;
|
||||
const newOptions = this.selection.options.filter(
|
||||
(option) => option !== "details"
|
||||
);
|
||||
this.selection.options = newOptions;
|
||||
return;
|
||||
}
|
||||
|
||||
const options = this.getContextOptions(this.selection, false);
|
||||
|
||||
excludeGeneralOptions.forEach((excludeOption) => {
|
||||
const idx = options.findIndex((o) => o === excludeOption);
|
||||
|
||||
if (idx !== -1) options.splice(idx, 1);
|
||||
});
|
||||
|
||||
if (this.selection?.isRoom) {
|
||||
excludeRoomOptions.forEach((excludeOption) => {
|
||||
const idx = options.findIndex((o) => o === excludeOption);
|
||||
|
||||
if (idx !== -1) options.splice(idx, 1);
|
||||
});
|
||||
|
||||
if (this.selection.id === this.selectedFolderId) {
|
||||
if (this.selection.isSelectedFolder) {
|
||||
excludeOptionsIntoRoom.forEach((excludeOption) => {
|
||||
const idx = options.findIndex((o) => o === excludeOption);
|
||||
|
||||
if (idx !== -1) options.splice(idx, 1);
|
||||
});
|
||||
}
|
||||
} else if (this.selection?.isFolder) {
|
||||
if (this.selection.id === this.selectedFolderId) {
|
||||
excludeOptionsIntoFolder.forEach((excludeOption) => {
|
||||
const idx = options.findIndex((o) => o === excludeOption);
|
||||
}
|
||||
|
||||
if (idx !== -1) options.splice(idx, 1);
|
||||
});
|
||||
}
|
||||
if (this.selection?.isSelectedFolder) {
|
||||
excludeOptionsIntoFolder.forEach((excludeOption) => {
|
||||
const idx = options.findIndex((o) => o === excludeOption);
|
||||
if (idx !== -1) options.splice(idx, 1);
|
||||
});
|
||||
}
|
||||
|
||||
const length = options.length;
|
||||
@ -76,7 +81,13 @@ class ContextHelper {
|
||||
};
|
||||
|
||||
getItemContextOptions = () => {
|
||||
return this.getContextOptionActions(this.selection, this.t);
|
||||
return this.isUser
|
||||
? this.getUserContextOptions(
|
||||
this.t,
|
||||
this.selection.options || [],
|
||||
this.selection
|
||||
)
|
||||
: this.getContextOptionActions(this.selection, this.t);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,118 @@
|
||||
import {
|
||||
ShareAccessRights,
|
||||
EmployeeType,
|
||||
RoomsType,
|
||||
} from "@docspace/common/constants";
|
||||
|
||||
class MembersHelper {
|
||||
constructor(props) {
|
||||
this.t = props.t;
|
||||
}
|
||||
|
||||
getOptions = () => {
|
||||
return {
|
||||
docSpaceAdmin: {
|
||||
key: "docSpaceAdmin",
|
||||
label: this.t("Common:DocSpaceAdmin"),
|
||||
access: ShareAccessRights.FullAccess,
|
||||
},
|
||||
roomAdmin: {
|
||||
key: "roomAdmin",
|
||||
label: this.t("Common:RoomAdmin"),
|
||||
access: ShareAccessRights.RoomManager,
|
||||
},
|
||||
viewer: {
|
||||
key: "viewer",
|
||||
label: this.t("Translations:RoleViewer"),
|
||||
access: ShareAccessRights.ReadOnly,
|
||||
},
|
||||
editor: {
|
||||
key: "editor",
|
||||
label: this.t("Translations:RoleEditor"),
|
||||
access: ShareAccessRights.Editing,
|
||||
},
|
||||
formFiller: {
|
||||
key: "formFiller",
|
||||
label: this.t("Translations:RoleFormFiller"),
|
||||
access: ShareAccessRights.FormFilling,
|
||||
},
|
||||
reviewer: {
|
||||
key: "reviewer",
|
||||
label: this.t("Translations:RoleReviewer"),
|
||||
access: ShareAccessRights.Review,
|
||||
},
|
||||
commentator: {
|
||||
key: "commentator",
|
||||
label: this.t("Translations:RoleCommentator"),
|
||||
access: ShareAccessRights.Comment,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
getOptionsByRoomType = (roomType, withDeleteOption = false) => {
|
||||
if (!roomType) return;
|
||||
|
||||
const options = this.getOptions();
|
||||
|
||||
const deleteOption = withDeleteOption
|
||||
? [
|
||||
{ key: "s2", isSeparator: true },
|
||||
{
|
||||
key: "remove",
|
||||
label: this.t("Translations:Remove"),
|
||||
access: ShareAccessRights.None,
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
switch (roomType) {
|
||||
case RoomsType.FillingFormsRoom:
|
||||
return [
|
||||
options.roomAdmin,
|
||||
options.formFiller,
|
||||
options.viewer,
|
||||
...deleteOption,
|
||||
];
|
||||
case RoomsType.EditingRoom:
|
||||
return [
|
||||
options.roomAdmin,
|
||||
options.editor,
|
||||
options.viewer,
|
||||
...deleteOption,
|
||||
];
|
||||
case RoomsType.ReviewRoom:
|
||||
return [
|
||||
options.roomAdmin,
|
||||
options.reviewer,
|
||||
options.commentator,
|
||||
options.viewer,
|
||||
...deleteOption,
|
||||
];
|
||||
case RoomsType.ReadOnlyRoom:
|
||||
return [options.roomAdmin, options.viewer, ...deleteOption];
|
||||
case RoomsType.CustomRoom:
|
||||
return [
|
||||
options.roomAdmin,
|
||||
options.editor,
|
||||
options.formFiller,
|
||||
options.reviewer,
|
||||
options.commentator,
|
||||
options.viewer,
|
||||
...deleteOption,
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
getOptionByUserAccess = (access) => {
|
||||
if (!access) return;
|
||||
|
||||
const options = this.getOptions();
|
||||
const [userOption] = Object.values(options).filter(
|
||||
(opt) => opt.access === access
|
||||
);
|
||||
|
||||
return userOption;
|
||||
};
|
||||
}
|
||||
|
||||
export default MembersHelper;
|
@ -9,12 +9,11 @@ import { StyledInfoPanelBody } from "./styles/common";
|
||||
import { getRoomInfo } from "@docspace/common/api/rooms";
|
||||
|
||||
const InfoPanelBodyContent = ({
|
||||
t,
|
||||
selection,
|
||||
setSelection,
|
||||
updateSelection,
|
||||
setUpdateSelection,
|
||||
calculateSelection,
|
||||
normalizeSelection,
|
||||
isItemChanged,
|
||||
selectionParentRoom,
|
||||
setSelectionParentRoom,
|
||||
roomsView,
|
||||
@ -24,10 +23,7 @@ const InfoPanelBodyContent = ({
|
||||
getIsAccounts,
|
||||
getIsGallery,
|
||||
gallerySelected,
|
||||
setBufferSelection,
|
||||
isRootFolder,
|
||||
getIcon,
|
||||
getFolderIcon,
|
||||
...props
|
||||
}) => {
|
||||
const [selectedItems, setSelectedItems] = useState(props.selectedItems);
|
||||
@ -37,9 +33,7 @@ const InfoPanelBodyContent = ({
|
||||
const isRooms = getIsRooms();
|
||||
const isAccounts = getIsAccounts();
|
||||
const isGallery = getIsGallery();
|
||||
|
||||
const isSeveralItems = props.selectedItems.length > 1;
|
||||
|
||||
const isNoItem =
|
||||
(isGallery && !gallerySelected) ||
|
||||
(!selection?.title && !isSeveralItems && !isAccounts) ||
|
||||
@ -47,61 +41,25 @@ const InfoPanelBodyContent = ({
|
||||
selection?.isSelectedFolder &&
|
||||
!selection?.wasContextMenuSelection);
|
||||
|
||||
const viewHelper = new ViewHelper({
|
||||
defaultProps: {
|
||||
selection,
|
||||
isFiles,
|
||||
isRooms,
|
||||
isAccounts,
|
||||
isGallery,
|
||||
isRootFolder,
|
||||
personal: props.personal,
|
||||
culture: props.culture,
|
||||
},
|
||||
detailsProps: {},
|
||||
membersProps: {
|
||||
selectionParentRoom,
|
||||
setSelectionParentRoom,
|
||||
selfId: props.selfId,
|
||||
isOwner: props.isOwner,
|
||||
isAdmin: props.isAdmin,
|
||||
getRoomMembers: props.getRoomMembers,
|
||||
changeUserType: props.changeUserType,
|
||||
setInvitePanelOptions: props.setInvitePanelOptions,
|
||||
canInviteUserInRoom: props.canInviteUserInRoom,
|
||||
},
|
||||
historyProps: {
|
||||
selectedFolder: selectedFolder,
|
||||
},
|
||||
accountsProps: {
|
||||
selfId: props.selfId,
|
||||
isOwner: props.isOwner,
|
||||
isAdmin: props.isAdmin,
|
||||
changeUserType: props.changeUserType,
|
||||
canChangeUserType: props.canChangeUserType,
|
||||
},
|
||||
galleryProps: {
|
||||
getIcon,
|
||||
gallerySelected,
|
||||
},
|
||||
});
|
||||
|
||||
const getSelection = () => {
|
||||
return selectedItems.length === 0
|
||||
? normalizeSelection({
|
||||
...selectedFolder,
|
||||
isSelectedFolder: true,
|
||||
isSelectedItem: false,
|
||||
})
|
||||
: selectedItems.length === 1
|
||||
? normalizeSelection({
|
||||
...selectedItems[0],
|
||||
isSelectedFolder: false,
|
||||
isSelectedItem: true,
|
||||
})
|
||||
: [...Array(props.selectedItems.length).keys()];
|
||||
const defaultProps = {
|
||||
selection,
|
||||
isFiles,
|
||||
isRooms,
|
||||
isAccounts,
|
||||
isGallery,
|
||||
isRootFolder,
|
||||
isSeveralItems,
|
||||
};
|
||||
|
||||
const viewHelper = new ViewHelper({
|
||||
defaultProps: defaultProps,
|
||||
detailsProps: {},
|
||||
membersProps: {},
|
||||
historyProps: { selectedFolder },
|
||||
accountsProps: {},
|
||||
galleryProps: {},
|
||||
});
|
||||
|
||||
const getView = () => {
|
||||
if (isNoItem) return viewHelper.NoItemView();
|
||||
if (isSeveralItems) return viewHelper.SeveralItemsView();
|
||||
@ -123,39 +81,18 @@ const InfoPanelBodyContent = ({
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
// Removing mark set with choosing item from context menu
|
||||
// for it to updated after selctedItems or selectedFolder change
|
||||
// (only for non-oforms items)
|
||||
useEffect(() => {
|
||||
if (selection && selection.isContextMenuSelection)
|
||||
setSelection({ ...selection, isContextMenuSelection: false });
|
||||
}, [selection]);
|
||||
|
||||
// Setting selection after selectedItems or selectedFolder update
|
||||
useEffect(() => {
|
||||
if (selection?.isContextMenuSelection) return;
|
||||
|
||||
const newSelection = getSelection();
|
||||
if (
|
||||
selection?.id === newSelection.id &&
|
||||
selection?.isFolder === newSelection.isFolder &&
|
||||
!newSelection.length
|
||||
)
|
||||
return;
|
||||
|
||||
setSelection(normalizeSelection(newSelection));
|
||||
}, [selectedItems, selectedFolder]);
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
// Updating SelectedItems only if
|
||||
// a) Length of an array changed
|
||||
// b) Single chosen item changed
|
||||
useEffect(() => {
|
||||
const selectedItemsLengthChanged =
|
||||
selectedItems.length !== props.selectedItems.length;
|
||||
|
||||
const singleSelectedItemChanged =
|
||||
selectedItems[0]?.id !== props.selectedItems[0]?.id;
|
||||
selectedItems[0] &&
|
||||
props.selectedItems[0] &&
|
||||
isItemChanged(selectedItems[0], props.selectedItems[0]);
|
||||
|
||||
if (selectedItemsLengthChanged || singleSelectedItemChanged)
|
||||
setSelectedItems(props.selectedItems);
|
||||
}, [props.selectedItems]);
|
||||
@ -163,29 +100,39 @@ const InfoPanelBodyContent = ({
|
||||
// Updating SelectedFolder only if
|
||||
// a) Selected folder changed
|
||||
useEffect(() => {
|
||||
if (selectedFolder.id !== props.selectedFolder.id)
|
||||
setSelectedFolder(props.selectedFolder);
|
||||
const selectedFolderChanged = isItemChanged(
|
||||
selectedFolder,
|
||||
props.selectedFolder
|
||||
);
|
||||
if (selectedFolderChanged) setSelectedFolder(props.selectedFolder);
|
||||
}, [props.selectedFolder]);
|
||||
|
||||
// Updating selectionParentRoom after selectFolder change
|
||||
// if it is located in another room
|
||||
useEffect(async () => {
|
||||
if (!isRooms) return;
|
||||
if (selection?.isRoom && roomsView === "members") return;
|
||||
|
||||
const currentFolderRoomId =
|
||||
selectedFolder?.pathParts && selectedFolder.pathParts[1];
|
||||
const storeRoomId = selectionParentRoom?.id;
|
||||
|
||||
if (!currentFolderRoomId) return;
|
||||
if (currentFolderRoomId === storeRoomId) return;
|
||||
if (!currentFolderRoomId || currentFolderRoomId === storeRoomId) return;
|
||||
|
||||
const newSelectionParentRoom = await getRoomInfo(currentFolderRoomId);
|
||||
if (storeRoomId !== newSelectionParentRoom.id)
|
||||
setSelectionParentRoom(normalizeSelection(newSelectionParentRoom));
|
||||
if (storeRoomId === newSelectionParentRoom.id) return;
|
||||
|
||||
setSelectionParentRoom(normalizeSelection(newSelectionParentRoom));
|
||||
}, [selectedFolder]);
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
// Setting selection after selectedItems or selectedFolder update
|
||||
useEffect(() => {
|
||||
setSelection(calculateSelection());
|
||||
}, [selectedItems, selectedFolder]);
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
// useEffect(() => {
|
||||
// console.log("\nfor-dev Selected items: ", selectedItems);
|
||||
// console.log("\nfor-dev Selected folder: ", selectedFolder);
|
||||
@ -198,156 +145,52 @@ const InfoPanelBodyContent = ({
|
||||
return (
|
||||
<StyledInfoPanelBody>
|
||||
{!isNoItem && (
|
||||
<ItemTitle
|
||||
selection={selection}
|
||||
selectionParentRoom={selectionParentRoom}
|
||||
roomsView={roomsView}
|
||||
isRooms={isRooms}
|
||||
isAccounts={isAccounts}
|
||||
isSeveralItems={isSeveralItems}
|
||||
severalItemsLength={selectedItems.length}
|
||||
isGallery={isGallery}
|
||||
getIcon={getIcon}
|
||||
setBufferSelection={setBufferSelection}
|
||||
getContextOptions={props.getContextOptions}
|
||||
getContextOptionActions={props.getContextOptionActions}
|
||||
getUserContextOptions={props.getUserContextOptions}
|
||||
selectedFolderId={selectedFolder.id}
|
||||
/>
|
||||
<ItemTitle {...defaultProps} selectionLength={selectedItems.length} />
|
||||
)}
|
||||
{getView()}
|
||||
</StyledInfoPanelBody>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(
|
||||
({
|
||||
auth,
|
||||
filesStore,
|
||||
settingsStore,
|
||||
filesActionsStore,
|
||||
dialogsStore,
|
||||
selectedFolderStore,
|
||||
oformsStore,
|
||||
contextOptionsStore,
|
||||
peopleStore,
|
||||
accessRightsStore,
|
||||
}) => {
|
||||
const { isOwner, isAdmin, id: selfId } = auth.userStore.user;
|
||||
const { personal, culture } = auth.settingsStore;
|
||||
const { getIcon, getFolderIcon } = settingsStore;
|
||||
const { onSelectItem, openLocationAction } = filesActionsStore;
|
||||
const { changeType: changeUserType } = peopleStore;
|
||||
const { setSharingPanelVisible, setInvitePanelOptions } = dialogsStore;
|
||||
const { isRootFolder } = selectedFolderStore;
|
||||
const { gallerySelected } = oformsStore;
|
||||
const {
|
||||
getFilesContextOptions: getContextOptionActions,
|
||||
} = contextOptionsStore;
|
||||
const { canChangeUserType, canInviteUserInRoom } = accessRightsStore;
|
||||
export default inject(({ auth, selectedFolderStore }) => {
|
||||
const {
|
||||
selection,
|
||||
setSelection,
|
||||
calculateSelection,
|
||||
normalizeSelection,
|
||||
isItemChanged,
|
||||
selectionParentRoom,
|
||||
setSelectionParentRoom,
|
||||
roomsView,
|
||||
fileView,
|
||||
getIsFiles,
|
||||
getIsRooms,
|
||||
getIsAccounts,
|
||||
getIsGallery,
|
||||
} = auth.infoPanelStore;
|
||||
|
||||
const {
|
||||
selection,
|
||||
setSelection,
|
||||
updateSelection,
|
||||
setUpdateSelection,
|
||||
selectionParentRoom,
|
||||
setSelectionParentRoom,
|
||||
normalizeSelection,
|
||||
roomsView,
|
||||
fileView,
|
||||
getItemIcon,
|
||||
getIsFiles,
|
||||
getIsRooms,
|
||||
getIsAccounts,
|
||||
getIsGallery,
|
||||
} = auth.infoPanelStore;
|
||||
const { isRootFolder } = selectedFolderStore;
|
||||
|
||||
const {
|
||||
selection: filesStoreSelection,
|
||||
getFilesContextOptions: getContextOptions,
|
||||
setBufferSelection,
|
||||
getFolderInfo,
|
||||
getShareUsers,
|
||||
getRoomMembers,
|
||||
getHistory,
|
||||
getRoomHistory,
|
||||
getFileHistory,
|
||||
createThumbnail,
|
||||
} = filesStore;
|
||||
const selectedItems = auth.infoPanelStore.getSelectedItems();
|
||||
const selectedFolder = auth.infoPanelStore.getSelectedFolder();
|
||||
|
||||
const {
|
||||
selection: peopleStoreSelection,
|
||||
bufferSelection: peopleStoreBufferSelection,
|
||||
} = peopleStore.selectionStore;
|
||||
const { getUserContextOptions } = peopleStore.contextOptionsStore;
|
||||
return {
|
||||
selection,
|
||||
setSelection,
|
||||
calculateSelection,
|
||||
normalizeSelection,
|
||||
isItemChanged,
|
||||
setSelectionParentRoom,
|
||||
roomsView,
|
||||
fileView,
|
||||
getIsFiles,
|
||||
getIsRooms,
|
||||
getIsAccounts,
|
||||
getIsGallery,
|
||||
|
||||
const selectedFiles =
|
||||
filesStoreSelection?.length > 0 ? [...filesStoreSelection] : [];
|
||||
const selectedUsers = peopleStoreSelection.length
|
||||
? [...peopleStoreSelection]
|
||||
: peopleStoreBufferSelection
|
||||
? [peopleStoreBufferSelection]
|
||||
: [];
|
||||
selectedItems,
|
||||
selectedFolder,
|
||||
|
||||
const selectedItems = getIsAccounts() ? selectedUsers : selectedFiles;
|
||||
const selectedFolder = {
|
||||
...selectedFolderStore,
|
||||
isFolder: true,
|
||||
isRoom: !!selectedFolderStore.roomType,
|
||||
};
|
||||
|
||||
return {
|
||||
selfId,
|
||||
isOwner,
|
||||
isAdmin,
|
||||
personal,
|
||||
culture,
|
||||
|
||||
selection,
|
||||
setSelection,
|
||||
updateSelection,
|
||||
setUpdateSelection,
|
||||
selectionParentRoom,
|
||||
setSelectionParentRoom,
|
||||
normalizeSelection,
|
||||
roomsView,
|
||||
fileView,
|
||||
getItemIcon,
|
||||
getIsFiles,
|
||||
getIsRooms,
|
||||
getIsAccounts,
|
||||
getIsGallery,
|
||||
|
||||
selectedItems,
|
||||
selectedFolder,
|
||||
setBufferSelection,
|
||||
|
||||
getContextOptions,
|
||||
getContextOptionActions,
|
||||
getUserContextOptions,
|
||||
|
||||
getFolderInfo,
|
||||
onSelectItem,
|
||||
getShareUsers,
|
||||
getRoomMembers,
|
||||
changeUserType,
|
||||
getHistory,
|
||||
getRoomHistory,
|
||||
getFileHistory,
|
||||
setSharingPanelVisible,
|
||||
setInvitePanelOptions,
|
||||
|
||||
getIcon,
|
||||
getFolderIcon,
|
||||
createThumbnail,
|
||||
openLocationAction,
|
||||
|
||||
gallerySelected,
|
||||
|
||||
isRootFolder,
|
||||
canChangeUserType,
|
||||
canInviteUserInRoom,
|
||||
};
|
||||
}
|
||||
)(withRouter(observer(InfoPanelBodyContent)));
|
||||
isRootFolder,
|
||||
};
|
||||
})(withRouter(observer(InfoPanelBodyContent)));
|
||||
|
@ -6,7 +6,8 @@ const StyledUserTypeHeader = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 8px 0 12px;
|
||||
padding-top: ${(props) => (props.isExpect ? "20px" : "8px")};
|
||||
padding-bottom: 12px;
|
||||
|
||||
.title {
|
||||
font-weight: 600;
|
||||
@ -20,6 +21,13 @@ const StyledUserTypeHeader = styled.div`
|
||||
rect {
|
||||
fill: ${(props) => props.theme.infoPanel.members.iconColor};
|
||||
}
|
||||
|
||||
&:hover {
|
||||
path,
|
||||
rect {
|
||||
fill: ${(props) => props.theme.infoPanel.members.iconHoverColor};
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@ -35,15 +43,17 @@ const StyledUser = styled.div`
|
||||
padding: 8px 0;
|
||||
|
||||
.avatar {
|
||||
opacity: ${(props) => (props.isExpect ? 0.5 : 1)};
|
||||
min-width: 32px;
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
.name {
|
||||
opacity: ${(props) => (props.isExpect ? 0.5 : 1)};
|
||||
${(props) =>
|
||||
props.isExpect && `color: ${props.theme.infoPanel.members.isExpectName}`};
|
||||
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
@ -53,6 +63,7 @@ const StyledUser = styled.div`
|
||||
.me-label {
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
color: ${(props) => props.theme.infoPanel.members.meLabelColor};
|
||||
margin-left: -8px;
|
||||
}
|
||||
|
@ -1,44 +1,47 @@
|
||||
import React from "react";
|
||||
import React, { useRef } from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
|
||||
import Text from "@docspace/components/text";
|
||||
import ContextMenuButton from "@docspace/components/context-menu-button";
|
||||
|
||||
import { Avatar } from "@docspace/components";
|
||||
import { Avatar, ContextMenuButton } from "@docspace/components";
|
||||
import Badges from "@docspace/client/src/pages/AccountsHome/Section/Body/Badges";
|
||||
import { StyledAccountsItemTitle } from "../../styles/accounts";
|
||||
import { StyledTitle } from "../../styles/common";
|
||||
import ItemContextOptions from "./ItemContextOptions";
|
||||
|
||||
const AccountsItemTitle = ({
|
||||
t,
|
||||
isSeveralItems,
|
||||
selection,
|
||||
getUserContextOptions,
|
||||
severalItemsLength,
|
||||
selectionLength,
|
||||
}) => {
|
||||
const isPending =
|
||||
selection.statusType === "pending" || selection.statusType === "disabled";
|
||||
|
||||
const getData = () => {
|
||||
const newOptions = selection.options.filter(
|
||||
(option) => option !== "details"
|
||||
);
|
||||
return getUserContextOptions(t, newOptions, selection);
|
||||
};
|
||||
|
||||
if (isSeveralItems) {
|
||||
return (
|
||||
<StyledTitle>
|
||||
<Avatar size={"min"} role={"user"} />
|
||||
<Text className="text" fontWeight={600} fontSize="16px">
|
||||
{`${t("InfoPanel:SelectedUsers")}: ${severalItemsLength}`}
|
||||
{`${t("InfoPanel:SelectedUsers")}: ${selectionLength}`}
|
||||
</Text>
|
||||
</StyledTitle>
|
||||
);
|
||||
}
|
||||
|
||||
const itemTitleRef = useRef();
|
||||
|
||||
const isPending =
|
||||
selection.statusType === "pending" || selection.statusType === "disabled";
|
||||
|
||||
const getData = () => {
|
||||
const newOptions = selection.options?.filter(
|
||||
(option) => option !== "details"
|
||||
);
|
||||
return getUserContextOptions(t, newOptions || [], selection);
|
||||
};
|
||||
const contextOptions = getData();
|
||||
|
||||
return (
|
||||
<StyledAccountsItemTitle isPending={isPending}>
|
||||
<StyledAccountsItemTitle isPending={isPending} ref={itemTitleRef}>
|
||||
<Avatar
|
||||
className="avatar"
|
||||
role={selection.role ? selection.role : "user"}
|
||||
@ -67,7 +70,9 @@ const AccountsItemTitle = ({
|
||||
<Badges withoutPaid={true} statusType={selection.statusType} />
|
||||
)}
|
||||
</div>
|
||||
<ContextMenuButton className="context-button" getData={getData} />
|
||||
{!!contextOptions.length && (
|
||||
<ContextMenuButton className="context-button" getData={getData} />
|
||||
)}
|
||||
</StyledAccountsItemTitle>
|
||||
);
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React, { useRef } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { ReactSVG } from "react-svg";
|
||||
|
||||
@ -10,19 +11,13 @@ import { StyledTitle } from "../../styles/common";
|
||||
|
||||
const FilesItemTitle = ({
|
||||
t,
|
||||
|
||||
selection,
|
||||
isSeveralItems,
|
||||
|
||||
setBufferSelection,
|
||||
getIcon,
|
||||
|
||||
getContextOptions,
|
||||
getContextOptionActions,
|
||||
severalItemsLength,
|
||||
|
||||
selectedFolderId,
|
||||
selectionLength,
|
||||
}) => {
|
||||
const itemTitleRef = useRef();
|
||||
|
||||
if (isSeveralItems)
|
||||
return (
|
||||
<StyledTitle>
|
||||
@ -30,13 +25,11 @@ const FilesItemTitle = ({
|
||||
<ReactSVG className="icon" src={getIcon(32, ".file")} />
|
||||
</div>
|
||||
<Text className="text">
|
||||
{`${t("InfoPanel:ItemsSelected")}: ${severalItemsLength}`}
|
||||
{`${t("InfoPanel:ItemsSelected")}: ${selectionLength}`}
|
||||
</Text>
|
||||
</StyledTitle>
|
||||
);
|
||||
|
||||
const itemTitleRef = useRef();
|
||||
|
||||
return (
|
||||
<StyledTitle ref={itemTitleRef}>
|
||||
<div className="item-icon">
|
||||
@ -52,10 +45,6 @@ const FilesItemTitle = ({
|
||||
t={t}
|
||||
itemTitleRef={itemTitleRef}
|
||||
selection={selection}
|
||||
setBufferSelection={setBufferSelection}
|
||||
getContextOptions={getContextOptions}
|
||||
getContextOptionActions={getContextOptionActions}
|
||||
selectedFolderId={selectedFolderId}
|
||||
/>
|
||||
)}
|
||||
</StyledTitle>
|
||||
@ -68,4 +57,4 @@ export default withTranslation([
|
||||
"Translations",
|
||||
"InfoPanel",
|
||||
"SharingPanel",
|
||||
])(FilesItemTitle);
|
||||
])(observer(FilesItemTitle));
|
||||
|
@ -1,11 +1,8 @@
|
||||
import React, { useRef, useEffect } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import {
|
||||
ContextMenu,
|
||||
ContextMenuButton,
|
||||
IconButton,
|
||||
} from "@docspace/components";
|
||||
import { ContextMenu, ContextMenuButton } from "@docspace/components";
|
||||
|
||||
import ContextHelper from "../../helpers/ContextHelper";
|
||||
|
||||
@ -14,23 +11,30 @@ const StyledItemContextOptions = styled.div`
|
||||
`;
|
||||
|
||||
const ItemContextOptions = ({
|
||||
t,
|
||||
selection,
|
||||
getContextOptions,
|
||||
getContextOptionActions,
|
||||
getUserContextOptions,
|
||||
setBufferSelection,
|
||||
|
||||
isUser = false,
|
||||
itemTitleRef,
|
||||
selectedFolderId,
|
||||
...props
|
||||
}) => {
|
||||
if (!selection) return null;
|
||||
|
||||
const contextMenuRef = useRef();
|
||||
|
||||
const contextHelper = new ContextHelper({
|
||||
t,
|
||||
isUser,
|
||||
selection,
|
||||
selectedFolderId,
|
||||
...props,
|
||||
getContextOptions,
|
||||
getContextOptionActions,
|
||||
getUserContextOptions,
|
||||
});
|
||||
|
||||
const setItemAsBufferSelection = () => setBufferSelection(selection);
|
||||
if (!selection) return null;
|
||||
|
||||
const onContextMenu = (e) => {
|
||||
e.button === 2;
|
||||
@ -43,12 +47,13 @@ const ItemContextOptions = ({
|
||||
}, [selection]);
|
||||
|
||||
const options = contextHelper.getItemContextOptions();
|
||||
const getData = () => options;
|
||||
|
||||
return (
|
||||
<StyledItemContextOptions onClick={setItemAsBufferSelection}>
|
||||
<StyledItemContextOptions onClick={() => setBufferSelection(selection)}>
|
||||
<ContextMenu
|
||||
ref={contextMenuRef}
|
||||
getContextModel={contextHelper.getItemContextOptions}
|
||||
getContextModel={getData}
|
||||
withBackdrop={false}
|
||||
/>
|
||||
{options.length > 0 && (
|
||||
@ -56,7 +61,7 @@ const ItemContextOptions = ({
|
||||
className="expandButton"
|
||||
title={"Show item actions"}
|
||||
onClick={onContextMenu}
|
||||
getData={contextHelper.getItemContextOptions}
|
||||
getData={getData}
|
||||
directionX="right"
|
||||
isNew={true}
|
||||
/>
|
||||
@ -65,4 +70,20 @@ const ItemContextOptions = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default ItemContextOptions;
|
||||
export default inject(({ filesStore, peopleStore, contextOptionsStore }) => {
|
||||
const { getUserContextOptions } = peopleStore.contextOptionsStore;
|
||||
const {
|
||||
setBufferSelection,
|
||||
getFilesContextOptions: getContextOptions,
|
||||
} = filesStore;
|
||||
const {
|
||||
getFilesContextOptions: getContextOptionActions,
|
||||
} = contextOptionsStore;
|
||||
|
||||
return {
|
||||
setBufferSelection,
|
||||
getContextOptions,
|
||||
getContextOptionActions,
|
||||
getUserContextOptions,
|
||||
};
|
||||
})(observer(ItemContextOptions));
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
import AccountsItemTitle from "./AccountsItemTitle";
|
||||
import FilesItemTitle from "./FilesItemTitle";
|
||||
@ -6,23 +7,15 @@ import GalleryItemTitle from "./GalleryItemTitle";
|
||||
|
||||
const ItemTitle = ({
|
||||
selection,
|
||||
selectionParentRoom,
|
||||
roomsView,
|
||||
|
||||
isRooms,
|
||||
isAccounts,
|
||||
isGallery,
|
||||
isSeveralItems,
|
||||
|
||||
selectedFolderId,
|
||||
|
||||
setBufferSelection,
|
||||
selectionLength,
|
||||
selectionParentRoom,
|
||||
roomsView,
|
||||
getIcon,
|
||||
|
||||
getContextOptions,
|
||||
getContextOptionActions,
|
||||
getUserContextOptions,
|
||||
severalItemsLength,
|
||||
}) => {
|
||||
if (!selection) return null;
|
||||
|
||||
@ -32,7 +25,7 @@ const ItemTitle = ({
|
||||
selection={selection}
|
||||
isSeveralItems={isSeveralItems}
|
||||
getUserContextOptions={getUserContextOptions}
|
||||
severalItemsLength={severalItemsLength}
|
||||
selectionLength={selectionLength}
|
||||
/>
|
||||
);
|
||||
|
||||
@ -50,16 +43,23 @@ const ItemTitle = ({
|
||||
|
||||
return (
|
||||
<FilesItemTitle
|
||||
severalItemsLength={severalItemsLength}
|
||||
selectionLength={selectionLength}
|
||||
selection={filesItemSelection}
|
||||
isSeveralItems={isSeveralItems}
|
||||
setBufferSelection={setBufferSelection}
|
||||
getIcon={getIcon}
|
||||
getContextOptions={getContextOptions}
|
||||
getContextOptionActions={getContextOptionActions}
|
||||
selectedFolderId={selectedFolderId}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default ItemTitle;
|
||||
export default inject(({ auth, settingsStore, peopleStore }) => {
|
||||
const { selectionParentRoom, roomsView } = auth.infoPanelStore;
|
||||
const { getIcon } = settingsStore;
|
||||
const { getUserContextOptions } = peopleStore.contextOptionsStore;
|
||||
|
||||
return {
|
||||
getUserContextOptions,
|
||||
selectionParentRoom,
|
||||
roomsView,
|
||||
getIcon,
|
||||
};
|
||||
})(observer(ItemTitle));
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
|
||||
import withLoader from "@docspace/client/src/HOCs/withLoader";
|
||||
@ -17,7 +18,6 @@ const Accounts = ({
|
||||
isAdmin,
|
||||
changeUserType,
|
||||
canChangeUserType,
|
||||
selfId,
|
||||
}) => {
|
||||
const [statusLabel, setStatusLabel] = React.useState("");
|
||||
|
||||
@ -185,15 +185,33 @@ const Accounts = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default withTranslation([
|
||||
"People",
|
||||
"InfoPanel",
|
||||
"ConnectDialog",
|
||||
"Common",
|
||||
"PeopleTranslations",
|
||||
"People",
|
||||
"Settings",
|
||||
"SmartBanner",
|
||||
"DeleteProfileEverDialog",
|
||||
"Translations",
|
||||
])(withLoader(Accounts)(<Loaders.InfoPanelViewLoader view="accounts" />));
|
||||
export default inject(({ auth, peopleStore, accessRightsStore }) => {
|
||||
const { isOwner, isAdmin, id: selfId } = auth.userStore.user;
|
||||
const { changeType: changeUserType } = peopleStore;
|
||||
const { canChangeUserType } = accessRightsStore;
|
||||
|
||||
return {
|
||||
isOwner,
|
||||
isAdmin,
|
||||
changeUserType,
|
||||
selfId,
|
||||
canChangeUserType,
|
||||
};
|
||||
})(
|
||||
withTranslation([
|
||||
"People",
|
||||
"InfoPanel",
|
||||
"ConnectDialog",
|
||||
"Common",
|
||||
"PeopleTranslations",
|
||||
"People",
|
||||
"Settings",
|
||||
"SmartBanner",
|
||||
"DeleteProfileEverDialog",
|
||||
"Translations",
|
||||
])(
|
||||
withLoader(observer(Accounts))(
|
||||
<Loaders.InfoPanelViewLoader view="accounts" />
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -16,7 +16,7 @@ const Details = ({
|
||||
personal,
|
||||
culture,
|
||||
createThumbnail,
|
||||
getItemIcon,
|
||||
getInfoPanelItemIcon,
|
||||
openUser,
|
||||
}) => {
|
||||
const [itemProperties, setItemProperties] = useState([]);
|
||||
@ -68,7 +68,7 @@ const Details = ({
|
||||
className={`no-thumbnail-img ${selection.isRoom && "is-room"} ${
|
||||
selection.isRoom && selection.logo?.large && "custom-logo"
|
||||
}`}
|
||||
src={getItemIcon(selection, 96)}
|
||||
src={getInfoPanelItemIcon(selection, 96)}
|
||||
alt="thumbnail-icon-big"
|
||||
/>
|
||||
</StyledNoThumbnail>
|
||||
@ -95,7 +95,7 @@ const Details = ({
|
||||
};
|
||||
|
||||
export default inject(({ auth, filesStore }) => {
|
||||
const { selection, getItemIcon, openUser } = auth.infoPanelStore;
|
||||
const { selection, getInfoPanelItemIcon, openUser } = auth.infoPanelStore;
|
||||
const { createThumbnail } = filesStore;
|
||||
const { personal, culture } = auth.settingsStore;
|
||||
|
||||
@ -104,7 +104,7 @@ export default inject(({ auth, filesStore }) => {
|
||||
culture,
|
||||
selection,
|
||||
createThumbnail,
|
||||
getItemIcon,
|
||||
getInfoPanelItemIcon,
|
||||
openUser,
|
||||
};
|
||||
})(withTranslation(["InfoPanel", "Common", "Translations"])(Details));
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { ReactSVG } from "react-svg";
|
||||
|
||||
@ -63,9 +64,20 @@ const Gallery = ({ t, gallerySelected, getIcon, culture, personal }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default withTranslation([
|
||||
"InfoPanel",
|
||||
"FormGallery",
|
||||
"Common",
|
||||
"Translations",
|
||||
])(withLoader(Gallery)(<Loaders.InfoPanelViewLoader view="gallery" />));
|
||||
export default inject(({ auth, settingsStore, oformsStore }) => {
|
||||
const { personal, culture } = auth.settingsStore;
|
||||
const { gallerySelected } = oformsStore;
|
||||
const { getIcon } = settingsStore;
|
||||
return {
|
||||
getIcon,
|
||||
gallerySelected,
|
||||
personal,
|
||||
culture,
|
||||
};
|
||||
})(
|
||||
withTranslation(["InfoPanel", "FormGallery", "Common", "Translations"])(
|
||||
withLoader(observer(Gallery))(
|
||||
<Loaders.InfoPanelViewLoader view="gallery" />
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -13,7 +13,7 @@ import { RoomsType } from "@docspace/common/constants";
|
||||
export const HistoryBlockItemList = ({
|
||||
t,
|
||||
items,
|
||||
getItemIcon,
|
||||
getInfoPanelItemIcon,
|
||||
checkAndOpenLocationAction,
|
||||
}) => {
|
||||
const [isShowMore, setIsShowMore] = useState(items.length <= 3);
|
||||
@ -39,7 +39,7 @@ export const HistoryBlockItemList = ({
|
||||
if (!isShowMore && i > 2) return null;
|
||||
return (
|
||||
<StyledHistoryBlockFile isRoom={item.isRoom} key={i}>
|
||||
<ReactSVG className="icon" src={getItemIcon(item, 24)} />
|
||||
<ReactSVG className="icon" src={getInfoPanelItemIcon(item, 24)} />
|
||||
<div className="item-title">
|
||||
<span className="name">{item.title}</span>
|
||||
{item.fileExst && <span className="exst">{item.fileExst}</span>}
|
||||
|
@ -5,11 +5,11 @@ import Link from "@docspace/components/link";
|
||||
import { StyledUserNameLink } from "../../styles/history";
|
||||
|
||||
const HistoryBlockUser = ({ user, withComma, openUser }) => {
|
||||
const username = user.displayName || user.email;
|
||||
const username = user.displayName;
|
||||
const history = useHistory();
|
||||
|
||||
const onUserClick = () => {
|
||||
openUser(user.id, history);
|
||||
openUser(user, history);
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { inject } from "mobx-react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
|
||||
import {
|
||||
@ -15,6 +15,7 @@ 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";
|
||||
|
||||
const History = ({
|
||||
t,
|
||||
@ -24,7 +25,7 @@ const History = ({
|
||||
selectedFolder,
|
||||
selectionParentRoom,
|
||||
setSelection,
|
||||
getItemIcon,
|
||||
getInfoPanelItemIcon,
|
||||
getHistory,
|
||||
checkAndOpenLocationAction,
|
||||
openUser,
|
||||
@ -32,6 +33,21 @@ const History = ({
|
||||
const [history, setHistory] = useState(null);
|
||||
const [showLoader, setShowLoader] = useState(false);
|
||||
|
||||
const fetchHistory = async (itemId) => {
|
||||
let module = "files";
|
||||
if (selection.isRoom) module = "rooms";
|
||||
else if (selection.isFolder) module = "folders";
|
||||
|
||||
let timerId = setTimeout(() => setShowLoader(true), 1500);
|
||||
let fetchedHistory = await getHistory(module, itemId);
|
||||
fetchedHistory = parseHistoryJSON(fetchedHistory);
|
||||
clearTimeout(timerId);
|
||||
|
||||
setHistory(fetchedHistory);
|
||||
setSelection({ ...selection, history: fetchedHistory });
|
||||
setShowLoader(false);
|
||||
};
|
||||
|
||||
const parseHistoryJSON = (fetchedHistory) => {
|
||||
let feeds = fetchedHistory.feeds;
|
||||
let newFeeds = [];
|
||||
@ -59,21 +75,6 @@ const History = ({
|
||||
return { ...fetchedHistory, feeds: newFeeds };
|
||||
};
|
||||
|
||||
const fetchHistory = async (itemId) => {
|
||||
let module = "files";
|
||||
if (selection.isRoom) module = "rooms";
|
||||
else if (selection.isFolder) module = "folders";
|
||||
|
||||
let timerId = setTimeout(() => setShowLoader(true), 1500);
|
||||
let fetchedHistory = await getHistory(module, itemId);
|
||||
fetchedHistory = parseHistoryJSON(fetchedHistory);
|
||||
clearTimeout(timerId);
|
||||
|
||||
setHistory(fetchedHistory);
|
||||
setSelection({ ...selection, history: fetchedHistory });
|
||||
setShowLoader(false);
|
||||
};
|
||||
|
||||
useEffect(async () => {
|
||||
if (selection.history) {
|
||||
setHistory(selection.history);
|
||||
@ -93,7 +94,7 @@ const History = ({
|
||||
{history.feeds.map((feed) => (
|
||||
<StyledHistoryBlock
|
||||
key={feed.json.Id}
|
||||
isUserAction={feed.json.Item === "sharedRoom" && feed.target}
|
||||
isUserAction={feed.json.Item === FeedItemTypes.User && feed.target}
|
||||
>
|
||||
<Avatar
|
||||
role="user"
|
||||
@ -134,16 +135,17 @@ const History = ({
|
||||
selectionParentRoom={selectionParentRoom}
|
||||
/>
|
||||
|
||||
{(feed.json.Item === "file" || feed.json.Item === "folder") && (
|
||||
{(feed.json.Item === FeedItemTypes.File ||
|
||||
feed.json.Item === FeedItemTypes.Folder) && (
|
||||
<HistoryBlockItemList
|
||||
t={t}
|
||||
items={[feed.json, ...feed.groupedFeeds]}
|
||||
getItemIcon={getItemIcon}
|
||||
getInfoPanelItemIcon={getInfoPanelItemIcon}
|
||||
checkAndOpenLocationAction={checkAndOpenLocationAction}
|
||||
/>
|
||||
)}
|
||||
|
||||
{feed.json.Item === "sharedRoom" &&
|
||||
{feed.json.Item === FeedItemTypes.User &&
|
||||
feed.target &&
|
||||
[feed.target, ...feed.groupedFeeds].map((user, i) => (
|
||||
<HistoryBlockUser
|
||||
@ -166,7 +168,7 @@ export default inject(({ auth, filesStore, filesActionsStore }) => {
|
||||
selection,
|
||||
selectionParentRoom,
|
||||
setSelection,
|
||||
getItemIcon,
|
||||
getInfoPanelItemIcon,
|
||||
openUser,
|
||||
} = auth.infoPanelStore;
|
||||
const { personal, culture } = auth.settingsStore;
|
||||
@ -180,9 +182,9 @@ export default inject(({ auth, filesStore, filesActionsStore }) => {
|
||||
selection,
|
||||
selectionParentRoom,
|
||||
setSelection,
|
||||
getItemIcon,
|
||||
getInfoPanelItemIcon,
|
||||
getHistory,
|
||||
checkAndOpenLocationAction,
|
||||
openUser,
|
||||
};
|
||||
})(withTranslation(["InfoPanel", "Common", "Translations"])(History));
|
||||
})(withTranslation(["InfoPanel", "Common", "Translations"])(observer(History)));
|
||||
|
@ -1,111 +1,111 @@
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { StyledUser } from "../../styles/members";
|
||||
import Avatar from "@docspace/components/avatar";
|
||||
import { ComboBox } from "@docspace/components";
|
||||
import { ShareAccessRights } from "@docspace/common/constants";
|
||||
|
||||
const User = ({
|
||||
t,
|
||||
user,
|
||||
isOwner,
|
||||
isAdmin,
|
||||
selfId,
|
||||
isExpect,
|
||||
changeUserType,
|
||||
membersHelper,
|
||||
currentMember,
|
||||
updateRoomMemberRole,
|
||||
|
||||
selectionParentRoom,
|
||||
setSelectionParentRoom,
|
||||
}) => {
|
||||
if (!selectionParentRoom) return null;
|
||||
if (!user.displayName && !user.email) return null;
|
||||
|
||||
const roles = {
|
||||
admin: {
|
||||
key: "admin",
|
||||
title: t("People:Administrator"),
|
||||
label: t("People:Administrator"),
|
||||
action: "admin",
|
||||
},
|
||||
manager: {
|
||||
key: "manager",
|
||||
title: t("People:Manager"),
|
||||
label: t("People:Manager"),
|
||||
action: "manager",
|
||||
},
|
||||
user: {
|
||||
key: "user",
|
||||
title: t("Common:User"),
|
||||
label: t("Common:User"),
|
||||
action: "user",
|
||||
},
|
||||
};
|
||||
const [userIsRemoved, setUserIsRemoved] = useState(false);
|
||||
if (userIsRemoved) return null;
|
||||
|
||||
const getUserRole = () => {
|
||||
if (user.isOwner) return roles.admin;
|
||||
if (user.isAdmin) return roles.manager;
|
||||
return roles.user;
|
||||
};
|
||||
const currCanEditUsers =
|
||||
currentMember.isOwner ||
|
||||
currentMember.isAdmin ||
|
||||
currentMember?.access === ShareAccessRights.FullAccess ||
|
||||
currentMember?.access === ShareAccessRights.RoomManager;
|
||||
|
||||
const getUserOptions = () => {
|
||||
let options = [];
|
||||
if (isOwner) options.push(roles.admin);
|
||||
if (isAdmin) options.push(roles.manager);
|
||||
options.push(roles.user);
|
||||
return options;
|
||||
};
|
||||
|
||||
const getNotAuthorizedToEdit = () => {
|
||||
if (selfId === user.id) return true;
|
||||
if (isOwner) return false;
|
||||
if (!isAdmin) return true;
|
||||
};
|
||||
|
||||
const userRole = getUserRole();
|
||||
const userOptions = getUserOptions();
|
||||
const userNotAuthorizedToEdit = getNotAuthorizedToEdit();
|
||||
|
||||
const onTypeChange = React.useCallback(
|
||||
({ action }) => {
|
||||
changeUserType(action, [user], t, false, false);
|
||||
},
|
||||
[user, changeUserType, t]
|
||||
const fullRoomRoleOptions = membersHelper.getOptionsByRoomType(
|
||||
selectionParentRoom.roomType,
|
||||
currCanEditUsers
|
||||
);
|
||||
|
||||
const userRole = membersHelper.getOptionByUserAccess(user.access);
|
||||
const userRoleOptions = fullRoomRoleOptions?.filter(
|
||||
(role) => role.key !== userRole.key
|
||||
);
|
||||
|
||||
const onOptionClick = (option) => {
|
||||
updateRoomMemberRole(selectionParentRoom.id, {
|
||||
invitations: [{ id: user.id, access: option.access }],
|
||||
notify: false,
|
||||
sharingMessage: "",
|
||||
});
|
||||
|
||||
const inRoomMembers = selectionParentRoom.members.inRoom;
|
||||
const expectedMembers = selectionParentRoom.members.expected;
|
||||
if (option.key === "remove") {
|
||||
setUserIsRemoved(true);
|
||||
setSelectionParentRoom({
|
||||
...selectionParentRoom,
|
||||
members: {
|
||||
inRoom: inRoomMembers?.filter((m) => m.id !== user.id),
|
||||
expected: expectedMembers?.filter((m) => m.id !== user.id),
|
||||
},
|
||||
});
|
||||
} else {
|
||||
setSelectionParentRoom({
|
||||
...selectionParentRoom,
|
||||
members: {
|
||||
inRoom: inRoomMembers?.map((m) =>
|
||||
m.id === user.id ? { ...m, access: option.access } : m
|
||||
),
|
||||
expected: expectedMembers?.map((m) =>
|
||||
m.id === user.id ? { ...m, access: option.access } : m
|
||||
),
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledUser
|
||||
isExpect={isExpect}
|
||||
key={user.id}
|
||||
canEditRole={user.role !== "Owner"}
|
||||
>
|
||||
<StyledUser isExpect={isExpect} key={user.id}>
|
||||
<Avatar
|
||||
role="user"
|
||||
className="avatar"
|
||||
size="min"
|
||||
source={
|
||||
user.avatar ||
|
||||
(user.displayName ? "" : user.email && "/static/images/@.react.svg")
|
||||
}
|
||||
userName={user.displayName}
|
||||
source={isExpect ? "/static/images/@.react.svg" : user.avatar || ""}
|
||||
userName={isExpect ? "" : user.displayName}
|
||||
/>
|
||||
|
||||
<div className="name">{user.displayName || user.email}</div>
|
||||
{selfId === user.id && (
|
||||
<div className="name">
|
||||
{isExpect ? user.email : user.displayName || user.email}
|
||||
</div>
|
||||
{currentMember.id === user.id && (
|
||||
<div className="me-label"> {`(${t("Common:MeLabel")})`}</div>
|
||||
)}
|
||||
|
||||
<div className="role-wrapper">
|
||||
{userNotAuthorizedToEdit ? (
|
||||
<div className="disabled-role-combobox">{userRole.label}</div>
|
||||
) : (
|
||||
<ComboBox
|
||||
className="role-combobox"
|
||||
selectedOption={userRole}
|
||||
options={userOptions}
|
||||
onSelect={onTypeChange}
|
||||
scaled={false}
|
||||
withBackdrop={false}
|
||||
size="content"
|
||||
displaySelectedOption
|
||||
modernView
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{userRole && userRoleOptions && (
|
||||
<div className="role-wrapper">
|
||||
{currCanEditUsers && currentMember.id !== user.id ? (
|
||||
<ComboBox
|
||||
className="role-combobox"
|
||||
selectedOption={userRole}
|
||||
options={userRoleOptions}
|
||||
onSelect={onOptionClick}
|
||||
scaled={false}
|
||||
withBackdrop={false}
|
||||
size="content"
|
||||
modernView
|
||||
/>
|
||||
) : (
|
||||
<div className="disabled-role-combobox">{userRole.label}</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</StyledUser>
|
||||
);
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import toastr from "@docspace/components/toast/toastr";
|
||||
|
||||
@ -11,6 +12,7 @@ import { ShareAccessRights } from "@docspace/common/constants";
|
||||
import IconButton from "@docspace/components/icon-button";
|
||||
import Text from "@docspace/components/text";
|
||||
import User from "./User";
|
||||
import MembersHelper from "../../helpers/MembersHelper";
|
||||
|
||||
const Members = ({
|
||||
t,
|
||||
@ -24,34 +26,54 @@ const Members = ({
|
||||
setSelectionParentRoom,
|
||||
|
||||
getRoomMembers,
|
||||
changeUserType,
|
||||
updateRoomMemberRole,
|
||||
|
||||
resendEmailInvitations,
|
||||
setInvitePanelOptions,
|
||||
|
||||
changeUserType,
|
||||
canInviteUserInRoom,
|
||||
}) => {
|
||||
const membersHelper = new MembersHelper({ t });
|
||||
|
||||
const [members, setMembers] = useState(null);
|
||||
const [showLoader, setShowLoader] = useState(false);
|
||||
|
||||
const isDisabledInvite = !canInviteUserInRoom({ access: selection.access });
|
||||
const fetchMembers = async (roomId) => {
|
||||
let timerId;
|
||||
if (members) timerId = setTimeout(() => setShowLoader(true), 1500);
|
||||
let fetchedMembers = await getRoomMembers(roomId);
|
||||
fetchedMembers = fetchedMembers.filter(
|
||||
(m) => m.sharedTo.email || m.sharedTo.displayName
|
||||
);
|
||||
if (members) timerId = setTimeout(() => setShowLoader(true), 1000);
|
||||
let data = await getRoomMembers(roomId);
|
||||
data = data.filter((m) => m.sharedTo.email || m.sharedTo.displayName);
|
||||
clearTimeout(timerId);
|
||||
setMembers(fetchedMembers);
|
||||
|
||||
let inRoomMembers = [];
|
||||
let expectedMembers = [];
|
||||
data.map((fetchedMember) => {
|
||||
const member = {
|
||||
access: fetchedMember.access,
|
||||
...fetchedMember.sharedTo,
|
||||
};
|
||||
if (member.activationStatus !== 2) inRoomMembers.push(member);
|
||||
else expectedMembers.push(member);
|
||||
});
|
||||
|
||||
setShowLoader(false);
|
||||
return fetchedMembers;
|
||||
return {
|
||||
inRoom: inRoomMembers,
|
||||
expected: expectedMembers,
|
||||
};
|
||||
};
|
||||
|
||||
useEffect(async () => {
|
||||
if (!selectionParentRoom) return;
|
||||
|
||||
if (selectionParentRoom.members) {
|
||||
setMembers(selectionParentRoom.members);
|
||||
return;
|
||||
}
|
||||
const fetchedMembers = await fetchMembers(selection.id);
|
||||
|
||||
const fetchedMembers = await fetchMembers(selectionParentRoom.id);
|
||||
setSelectionParentRoom({
|
||||
...selectionParentRoom,
|
||||
members: fetchedMembers,
|
||||
@ -60,8 +82,7 @@ const Members = ({
|
||||
|
||||
useEffect(async () => {
|
||||
if (!selection.isRoom) return;
|
||||
if (selectionParentRoom && selectionParentRoom.id === selection.id) return;
|
||||
setMembers(null);
|
||||
|
||||
const fetchedMembers = await fetchMembers(selection.id);
|
||||
setSelectionParentRoom({
|
||||
...selection,
|
||||
@ -69,72 +90,140 @@ const Members = ({
|
||||
});
|
||||
}, [selection]);
|
||||
|
||||
const onAddUsers = () => {
|
||||
if (isDisabledInvite) return;
|
||||
const onClickInviteUsers = () => {
|
||||
const parentRoomId = selectionParentRoom.id;
|
||||
|
||||
setInvitePanelOptions({
|
||||
visible: true,
|
||||
roomId: selection.id,
|
||||
roomId: parentRoomId,
|
||||
hideSelector: false,
|
||||
defaultAccess: ShareAccessRights.ReadOnly,
|
||||
});
|
||||
};
|
||||
|
||||
const onRepeatInvitation = async () => {
|
||||
const userIds = members.expected.map((user) => user.id);
|
||||
resendEmailInvitations(selectionParentRoom.id, userIds)
|
||||
.then(() =>
|
||||
toastr.success(t("PeopleTranslations:SuccessSentMultipleInvitatios"))
|
||||
)
|
||||
.catch((err) => toastr.error(err));
|
||||
};
|
||||
|
||||
if (showLoader) return <Loaders.InfoPanelViewLoader view="members" />;
|
||||
if (!members) return null;
|
||||
if (!selectionParentRoom || !members) return null;
|
||||
|
||||
const [currentMember] = members.inRoom.filter(
|
||||
(member) => member.id === selfId
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<StyledUserTypeHeader>
|
||||
<Text className="title">
|
||||
{t("UsersInRoom")} : {members.length}
|
||||
{t("UsersInRoom")} : {members.inRoom.length}
|
||||
</Text>
|
||||
<IconButton
|
||||
className={"icon"}
|
||||
title={t("Common:AddUsers")}
|
||||
iconName="/static/images/person+.react.svg"
|
||||
isFill={true}
|
||||
onClick={onAddUsers}
|
||||
onClick={onClickInviteUsers}
|
||||
size={16}
|
||||
isDisabled={isDisabledInvite}
|
||||
/>
|
||||
</StyledUserTypeHeader>
|
||||
|
||||
<StyledUserList>
|
||||
{Object.values(members).map((user) => (
|
||||
{Object.values(members.inRoom).map((user) => (
|
||||
<User
|
||||
key={user.sharedTo.id}
|
||||
key={user.id}
|
||||
t={t}
|
||||
user={user.sharedTo}
|
||||
isOwner={isOwner}
|
||||
isAdmin={isAdmin}
|
||||
selfId={selfId}
|
||||
changeUserType={changeUserType}
|
||||
user={user}
|
||||
membersHelper={membersHelper}
|
||||
currentMember={currentMember}
|
||||
updateRoomMemberRole={updateRoomMemberRole}
|
||||
roomId={selectionParentRoom.id}
|
||||
roomType={selectionParentRoom.roomType}
|
||||
selectionParentRoom={selectionParentRoom}
|
||||
setSelectionParentRoom={setSelectionParentRoom}
|
||||
/>
|
||||
))}
|
||||
</StyledUserList>
|
||||
|
||||
{/* <StyledUserTypeHeader>
|
||||
<Text className="title">{`${t("Expect people")}:`}</Text>
|
||||
<IconButton
|
||||
className={"icon"}
|
||||
title={t("Repeat invitation")}
|
||||
iconName="/static/images/e-mail+.react.svg"
|
||||
isFill={true}
|
||||
onClick={() => {}}
|
||||
size={16}
|
||||
/>
|
||||
</StyledUserTypeHeader>
|
||||
{!!members.expected.length && (
|
||||
<StyledUserTypeHeader isExpect>
|
||||
<Text className="title">{t("ExpectPeople")}</Text>
|
||||
<IconButton
|
||||
className={"icon"}
|
||||
title={t("Repeat invitation")}
|
||||
iconName="/static/images/e-mail+.react.svg"
|
||||
isFill={true}
|
||||
onClick={onRepeatInvitation}
|
||||
size={16}
|
||||
/>
|
||||
</StyledUserTypeHeader>
|
||||
)}
|
||||
|
||||
<UserList t={t} users={data.members.expect} isExpect /> */}
|
||||
<StyledUserList>
|
||||
{Object.values(members.expected).map((user) => (
|
||||
<User
|
||||
isExpect
|
||||
key={user.id}
|
||||
t={t}
|
||||
user={user}
|
||||
membersHelper={membersHelper}
|
||||
currentMember={currentMember}
|
||||
updateRoomMemberRole={updateRoomMemberRole}
|
||||
roomId={selectionParentRoom.id}
|
||||
roomType={selectionParentRoom.roomType}
|
||||
selectionParentRoom={selectionParentRoom}
|
||||
setSelectionParentRoom={setSelectionParentRoom}
|
||||
/>
|
||||
))}
|
||||
</StyledUserList>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default withTranslation([
|
||||
"InfoPanel",
|
||||
"Common",
|
||||
"Translations",
|
||||
"People",
|
||||
"PeopleTranslations",
|
||||
"Settings",
|
||||
])(Members);
|
||||
export default inject(
|
||||
({ auth, filesStore, peopleStore, dialogsStore, accessRightsStore }) => {
|
||||
const { selectionParentRoom, setSelectionParentRoom } = auth.infoPanelStore;
|
||||
const {
|
||||
getRoomMembers,
|
||||
updateRoomMemberRole,
|
||||
resendEmailInvitations,
|
||||
} = filesStore;
|
||||
const { isOwner, isAdmin, id: selfId } = auth.userStore.user;
|
||||
const { setInvitePanelOptions } = dialogsStore;
|
||||
const { changeType: changeUserType } = peopleStore;
|
||||
const { canInviteUserInRoom } = accessRightsStore;
|
||||
|
||||
return {
|
||||
selectionParentRoom,
|
||||
setSelectionParentRoom,
|
||||
|
||||
getRoomMembers,
|
||||
updateRoomMemberRole,
|
||||
|
||||
isOwner,
|
||||
isAdmin,
|
||||
selfId,
|
||||
|
||||
setInvitePanelOptions,
|
||||
resendEmailInvitations,
|
||||
|
||||
changeUserType,
|
||||
canInviteUserInRoom,
|
||||
};
|
||||
}
|
||||
)(
|
||||
withTranslation([
|
||||
"InfoPanel",
|
||||
"Common",
|
||||
"Translations",
|
||||
"People",
|
||||
"PeopleTranslations",
|
||||
"Settings",
|
||||
])(observer(Members))
|
||||
);
|
||||
|
@ -11,6 +11,7 @@ import TextInput from "@docspace/components/text-input";
|
||||
import HelpButton from "@docspace/components/help-button";
|
||||
import SaveCancelButtons from "@docspace/components/save-cancel-buttons";
|
||||
import Badge from "@docspace/components/badge";
|
||||
import toastr from "@docspace/components/toast/toastr";
|
||||
|
||||
import { Base } from "@docspace/components/themes";
|
||||
import LoaderWhiteLabel from "../sub-components/loaderWhiteLabel";
|
||||
@ -67,9 +68,9 @@ const StyledComponent = styled.div`
|
||||
}
|
||||
|
||||
.logo-header {
|
||||
width: 142px;
|
||||
height: 23px;
|
||||
padding: 10px;
|
||||
width: 211px;
|
||||
height: 24px;
|
||||
padding: 12px 20px;
|
||||
background-color: ${(props) =>
|
||||
props.theme.client.settings.common.whiteLabel.backgroundColor};
|
||||
}
|
||||
@ -163,6 +164,8 @@ const WhiteLabel = (props) => {
|
||||
const [editorsHeaderLabel, setEditorsHeaderLabel] = useState();
|
||||
const [logoEditorsEmbeddedLabel, setLogoEditorsEmbeddedLabel] = useState();
|
||||
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (logoText) {
|
||||
setLogoTextWhiteLabel(logoText);
|
||||
@ -175,6 +178,10 @@ const WhiteLabel = (props) => {
|
||||
}
|
||||
}, [logoUrls]);
|
||||
|
||||
useEffect(() => {
|
||||
setLogoSizes(mapSizesToArray(logoSizes));
|
||||
}, [logoSizes]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
logoTextWhiteLabel &&
|
||||
@ -285,6 +292,26 @@ const WhiteLabel = (props) => {
|
||||
setIsUseTextAsLogo(false);
|
||||
}, [isCanvasProcessing, isUseTextAsLogo]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isCanvasProcessing) {
|
||||
let logosArr = [];
|
||||
for (let i = 0; i < 7; i++) {
|
||||
const id = String(i + 1);
|
||||
const canvas =
|
||||
id === "4"
|
||||
? document.getElementById(`canvas_logo_${id}_1`)
|
||||
: document.getElementById(`canvas_logo_${id}`);
|
||||
|
||||
const changeImg = {
|
||||
id,
|
||||
src: canvas.toDataURL(),
|
||||
};
|
||||
logosArr.push(changeImg);
|
||||
}
|
||||
setLogoUrlsChange(logosArr);
|
||||
}
|
||||
}, [isCanvasProcessing]);
|
||||
|
||||
const onUseTextAsLogo = () => {
|
||||
setIsCanvasProcessing(true);
|
||||
setIsUseTextAsLogo(true);
|
||||
@ -297,27 +324,43 @@ const WhiteLabel = (props) => {
|
||||
};
|
||||
|
||||
const onRestoreLogo = () => {
|
||||
restoreWhiteLabelSettings(true);
|
||||
setIsCanvasProcessing(false);
|
||||
try {
|
||||
restoreWhiteLabelSettings(true);
|
||||
setIsCanvasProcessing(false);
|
||||
setLogoUrlsChange([]);
|
||||
getWhiteLabelLogoUrls();
|
||||
toastr.success(t("Settings:SuccessfullySaveSettingsMessage"));
|
||||
} catch (error) {
|
||||
toastr.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const onSave = () => {
|
||||
let fd = new FormData();
|
||||
fd.append("logoText", logoTextWhiteLabel);
|
||||
const onSave = async () => {
|
||||
let logoArr = [];
|
||||
|
||||
for (let i = 0; i < 7; i++) {
|
||||
fd.append(`logo[${i}][key]`, i + 1);
|
||||
fd.append(`logo[${i}][value]`, logoUrlsWhiteLabel[i]);
|
||||
}
|
||||
logoUrlsChange.map((item) => {
|
||||
logoArr.push({ key: item.id, value: item.src });
|
||||
});
|
||||
|
||||
const data = new URLSearchParams(fd);
|
||||
console.log(data);
|
||||
const data = {
|
||||
logoText: logoTextWhiteLabel,
|
||||
logo: logoArr,
|
||||
};
|
||||
|
||||
setWhiteLabelSettings(data).finally(() => {
|
||||
setIsSaving(true);
|
||||
|
||||
try {
|
||||
await setWhiteLabelSettings(data);
|
||||
setLogoUrlsChange([]);
|
||||
getWhiteLabelLogoText();
|
||||
getWhiteLabelLogoSizes();
|
||||
getWhiteLabelLogoUrls();
|
||||
});
|
||||
toastr.success(t("Settings:SuccessfullySaveSettingsMessage"));
|
||||
} catch (error) {
|
||||
toastr.error(error);
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
};
|
||||
|
||||
const onChangeLogo = (e) => {
|
||||
@ -414,19 +457,19 @@ const WhiteLabel = (props) => {
|
||||
!logoUrlsChange.some((obj) => obj.id === "1") ? (
|
||||
<canvas
|
||||
id="canvas_logo_1"
|
||||
className="border-img logo-header"
|
||||
className="logo-header"
|
||||
width="251"
|
||||
height="48"
|
||||
data-fontsize="36"
|
||||
data-fontcolor={
|
||||
theme.client.settings.common.whiteLabel.dataFontColor
|
||||
theme.client.settings.common.whiteLabel.dataFontColorBlack
|
||||
}
|
||||
>
|
||||
{t("BrowserNoCanvasSupport")}
|
||||
</canvas>
|
||||
) : (
|
||||
<img
|
||||
className="border-img logo-header"
|
||||
className="logo-header"
|
||||
src={
|
||||
logoUrlsChange &&
|
||||
logoUrlsChange.some((obj) => obj.id === "1")
|
||||
@ -474,7 +517,7 @@ const WhiteLabel = (props) => {
|
||||
height="56"
|
||||
data-fontsize="36"
|
||||
data-fontcolor={
|
||||
theme.client.settings.common.whiteLabel.dataFontColor
|
||||
theme.client.settings.common.whiteLabel.dataFontColorBlack
|
||||
}
|
||||
>
|
||||
{t("BrowserNoCanvasSupport")}
|
||||
@ -838,34 +881,36 @@ const WhiteLabel = (props) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{isSettingPaid && (
|
||||
<SaveCancelButtons
|
||||
tabIndex={3}
|
||||
className="save-cancel-buttons"
|
||||
onSaveClick={onSave}
|
||||
onCancelClick={onRestoreLogo}
|
||||
saveButtonLabel={t("Common:SaveButton")}
|
||||
cancelButtonLabel={t("RestoreDefaultButton")}
|
||||
displaySettings={true}
|
||||
showReminder={true}
|
||||
/>
|
||||
)}
|
||||
<SaveCancelButtons
|
||||
tabIndex={3}
|
||||
className="save-cancel-buttons"
|
||||
onSaveClick={onSave}
|
||||
onCancelClick={onRestoreLogo}
|
||||
saveButtonLabel={t("Common:SaveButton")}
|
||||
cancelButtonLabel={t("RestoreDefaultButton")}
|
||||
displaySettings={true}
|
||||
showReminder={isSettingPaid}
|
||||
saveButtonDisabled={logoUrlsChange.length === 0}
|
||||
isSaving={isSaving}
|
||||
/>
|
||||
</div>
|
||||
</StyledComponent>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ setup, auth, common }) => {
|
||||
const { setWhiteLabelSettings, restoreWhiteLabelSettings } = setup;
|
||||
|
||||
const { whiteLabelLogoSizes, whiteLabelLogoText } = common;
|
||||
const { setWhiteLabelSettings } = setup;
|
||||
|
||||
const {
|
||||
whiteLabelLogoUrls,
|
||||
whiteLabelLogoSizes,
|
||||
whiteLabelLogoText,
|
||||
getWhiteLabelLogoText,
|
||||
getWhiteLabelLogoSizes,
|
||||
getWhiteLabelLogoUrls,
|
||||
} = auth.settingsStore;
|
||||
whiteLabelLogoUrls,
|
||||
restoreWhiteLabelSettings,
|
||||
} = common;
|
||||
|
||||
const { getWhiteLabelLogoUrls } = auth.settingsStore;
|
||||
|
||||
return {
|
||||
theme: auth.settingsStore.theme,
|
||||
|
@ -130,25 +130,31 @@ const PayerInformationContainer = ({
|
||||
</>
|
||||
);
|
||||
|
||||
const payerName = (
|
||||
<Text as="span" fontWeight={600} noSelect fontSize={"14px"}>
|
||||
{payerInfo ? (
|
||||
payerInfo.displayName
|
||||
) : (
|
||||
<Trans t={t} i18nKey="UserNotFound" ns="Payments">
|
||||
User
|
||||
<Text
|
||||
as="span"
|
||||
color={theme.client.settings.payment.warningColor}
|
||||
fontWeight={600}
|
||||
>
|
||||
{{ email }}
|
||||
</Text>
|
||||
is not found
|
||||
</Trans>
|
||||
)}
|
||||
</Text>
|
||||
);
|
||||
const payerName = () => {
|
||||
let emailUnfoundedUser = email;
|
||||
|
||||
if (email) emailUnfoundedUser = "«" + emailUnfoundedUser + "»";
|
||||
|
||||
return (
|
||||
<Text as="span" fontWeight={600} noSelect fontSize={"14px"}>
|
||||
{payerInfo ? (
|
||||
payerInfo.displayName
|
||||
) : (
|
||||
<Trans t={t} i18nKey="UserNotFound" ns="Payments">
|
||||
User
|
||||
<Text
|
||||
as="span"
|
||||
color={theme.client.settings.payment.warningColor}
|
||||
fontWeight={600}
|
||||
>
|
||||
{{ email: emailUnfoundedUser }}
|
||||
</Text>
|
||||
is not found
|
||||
</Trans>
|
||||
)}
|
||||
</Text>
|
||||
);
|
||||
};
|
||||
|
||||
const avatarUrl = payerInfo ? { source: payerInfo.avatar } : {};
|
||||
|
||||
@ -165,7 +171,7 @@ const PayerInformationContainer = ({
|
||||
|
||||
<div className="payer-info_wrapper">
|
||||
<div className="payer-info_description">
|
||||
{payerName}
|
||||
{payerName()}
|
||||
|
||||
<Text as="span" className="payer-info">
|
||||
{" (" + t("Payer") + ") "}
|
||||
|
@ -36,7 +36,9 @@ const StyledBody = styled.div`
|
||||
|
||||
@media (max-width: ${size.smallTablet + 40}px) {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
|
||||
grid-template-rows: ${(props) =>
|
||||
props.isHideBenefitsInfo ? "1fr" : "1fr max-content"};
|
||||
|
||||
.price-calculation-container,
|
||||
.benefits-container {
|
||||
@ -51,7 +53,8 @@ const StyledBody = styled.div`
|
||||
props.isChangeView &&
|
||||
css`
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: 1fr 1fr;
|
||||
grid-template-rows: ${(props) =>
|
||||
props.isHideBenefitsInfo ? "1fr" : "1fr max-content"};
|
||||
|
||||
.price-calculation-container,
|
||||
.benefits-container {
|
||||
@ -304,6 +307,9 @@ const PaymentsPage = ({
|
||||
|
||||
const isFreeAfterPaidPeriod = isFreeTariff && payerEmail.length !== 0;
|
||||
|
||||
const isHideBenefitsInfo =
|
||||
isGracePeriod || isNotPaidPeriod || isFreeAfterPaidPeriod;
|
||||
|
||||
return isInitialLoading || !ready ? (
|
||||
<Loaders.PaymentsLoader />
|
||||
) : (
|
||||
@ -314,6 +320,7 @@ const PaymentsPage = ({
|
||||
isChangeView={
|
||||
context.sectionWidth < size.smallTablet && expandArticle
|
||||
}
|
||||
isHideBenefitsInfo={isHideBenefitsInfo}
|
||||
>
|
||||
{isNotPaidPeriod && isValidDelayDueDate
|
||||
? expiredTitleSubscriptionWarning()
|
||||
@ -382,11 +389,7 @@ const PaymentsPage = ({
|
||||
isFreeAfterPaidPeriod={isFreeAfterPaidPeriod}
|
||||
/>
|
||||
|
||||
{isGracePeriod || isNotPaidPeriod || isFreeAfterPaidPeriod ? (
|
||||
<></>
|
||||
) : (
|
||||
<BenefitsContainer t={t} />
|
||||
)}
|
||||
{isHideBenefitsInfo ? <></> : <BenefitsContainer t={t} />}
|
||||
</div>
|
||||
<ContactContainer t={t} />
|
||||
</StyledBody>
|
||||
|
@ -3,6 +3,7 @@ import authStore from "@docspace/common/store/AuthStore";
|
||||
import api from "@docspace/common/api";
|
||||
|
||||
class CommonStore {
|
||||
whiteLabelLogoUrls = [];
|
||||
whiteLabelLogoSizes = [];
|
||||
whiteLabelLogoText = null;
|
||||
|
||||
@ -35,6 +36,7 @@ class CommonStore {
|
||||
requests.push(
|
||||
authStore.settingsStore.getPortalTimezones(),
|
||||
authStore.settingsStore.getPortalCultures(),
|
||||
this.getWhiteLabelLogoUrls(),
|
||||
this.getWhiteLabelLogoText(),
|
||||
this.getWhiteLabelLogoSizes(),
|
||||
this.getGreetingSettingsIsDefault()
|
||||
@ -43,6 +45,10 @@ class CommonStore {
|
||||
return Promise.all(requests).finally(() => this.setIsLoaded(true));
|
||||
};
|
||||
|
||||
setLogoUrls = (urls) => {
|
||||
this.whiteLabelLogoUrls = urls;
|
||||
};
|
||||
|
||||
setLogoText = (text) => {
|
||||
this.whiteLabelLogoText = text;
|
||||
};
|
||||
@ -51,10 +57,20 @@ class CommonStore {
|
||||
this.whiteLabelLogoSizes = sizes;
|
||||
};
|
||||
|
||||
restoreWhiteLabelSettings = async (isDefault) => {
|
||||
const res = await api.settings.restoreWhiteLabelSettings(isDefault);
|
||||
this.getWhiteLabelLogoUrls();
|
||||
};
|
||||
|
||||
getGreetingSettingsIsDefault = async () => {
|
||||
this.greetingSettingsIsDefault = await api.settings.getGreetingSettingsIsDefault();
|
||||
};
|
||||
|
||||
getWhiteLabelLogoUrls = async () => {
|
||||
const res = await api.settings.getLogoUrls();
|
||||
this.setLogoUrls(Object.values(res));
|
||||
};
|
||||
|
||||
getWhiteLabelLogoText = async () => {
|
||||
const res = await api.settings.getLogoText();
|
||||
this.setLogoText(res);
|
||||
|
@ -401,7 +401,7 @@ class ContextOptionsStore {
|
||||
|
||||
onShowInfoPanel = (item) => {
|
||||
const { setSelection, setIsVisible } = this.authStore.infoPanelStore;
|
||||
setSelection({ ...item, isContextMenuSelection: true });
|
||||
setSelection(item);
|
||||
setIsVisible(true);
|
||||
};
|
||||
|
||||
|
@ -1666,6 +1666,10 @@ class FilesStore {
|
||||
return api.rooms.getRoomMembers(id);
|
||||
}
|
||||
|
||||
updateRoomMemberRole(id, data) {
|
||||
return api.rooms.updateRoomMemberRole(id, data);
|
||||
}
|
||||
|
||||
getHistory(module, id) {
|
||||
return api.rooms.getHistory(module, id);
|
||||
}
|
||||
|
@ -218,10 +218,6 @@ class SettingsSetupStore {
|
||||
return Promise.resolve(response);
|
||||
};
|
||||
|
||||
restoreWhiteLabelSettings = async (isDefault) => {
|
||||
const res = await api.settings.restoreWhiteLabelSettings(isDefault);
|
||||
};
|
||||
|
||||
setLanguageAndTime = async (lng, timeZoneID) => {
|
||||
return api.settings.setLanguageAndTime(lng, timeZoneID);
|
||||
};
|
||||
|
@ -137,6 +137,7 @@ const profileActionsStore = new ProfileActionsStore(
|
||||
|
||||
authStore.infoPanelStore.authStore = authStore;
|
||||
authStore.infoPanelStore.settingsStore = settingsStore;
|
||||
authStore.infoPanelStore.filesStore = filesStore;
|
||||
authStore.infoPanelStore.peopleStore = peopleStore;
|
||||
authStore.infoPanelStore.selectedFolderStore = selectedFolderStore;
|
||||
authStore.infoPanelStore.treeFoldersStore = treeFoldersStore;
|
||||
|
@ -42,6 +42,18 @@ export function getRoomMembers(id) {
|
||||
});
|
||||
}
|
||||
|
||||
export function updateRoomMemberRole(id, data) {
|
||||
const options = {
|
||||
method: "put",
|
||||
url: `/files/rooms/${id}/share`,
|
||||
data,
|
||||
};
|
||||
|
||||
return request(options).then((res) => {
|
||||
return res;
|
||||
});
|
||||
}
|
||||
|
||||
export function getHistory(module, id) {
|
||||
const options = {
|
||||
method: "get",
|
||||
@ -263,7 +275,7 @@ export const setInvitationLinks = async (roomId, linkId, title, access) => {
|
||||
|
||||
export const resendEmailInvitations = async (id, usersIds) => {
|
||||
const options = {
|
||||
method: "put",
|
||||
method: "post",
|
||||
url: `/files/rooms/${id}/resend`,
|
||||
data: {
|
||||
usersIds,
|
||||
|
@ -164,6 +164,11 @@ const StyledHeading = styled.div`
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
|
||||
img.logo-icon_svg {
|
||||
height: 24px;
|
||||
width: 211px;
|
||||
}
|
||||
|
||||
.logo-icon_svg {
|
||||
svg {
|
||||
path:last-child {
|
||||
@ -199,6 +204,10 @@ const StyledIconBox = styled.div`
|
||||
align-items: center;
|
||||
height: 20px;
|
||||
|
||||
img {
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
@media ${tablet} {
|
||||
display: ${(props) => (props.showText ? "none" : "flex")};
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ const ArticleHeader = ({
|
||||
children,
|
||||
onClick,
|
||||
isBurgerLoading,
|
||||
whiteLabelLogoUrls,
|
||||
...rest
|
||||
}) => {
|
||||
const history = useHistory();
|
||||
@ -25,6 +26,8 @@ const ArticleHeader = ({
|
||||
const isTabletView = (isTabletUtils() || isTablet) && !isMobileOnly;
|
||||
const onLogoClick = () => history.push("/");
|
||||
|
||||
const isSvgLogo = whiteLabelLogoUrls[0].includes(".svg");
|
||||
|
||||
if (isMobileOnly) return <></>;
|
||||
return (
|
||||
<StyledArticleHeader showText={showText} {...rest}>
|
||||
@ -32,7 +35,7 @@ const ArticleHeader = ({
|
||||
<Loaders.ArticleHeader height="28px" width="28px" />
|
||||
) : (
|
||||
<StyledIconBox name="article-burger" showText={showText}>
|
||||
<img src="/static/images/logo.icon.react.svg" onClick={onLogoClick} />
|
||||
<img src={whiteLabelLogoUrls[5]} onClick={onLogoClick} />
|
||||
</StyledIconBox>
|
||||
)}
|
||||
|
||||
@ -41,17 +44,30 @@ const ArticleHeader = ({
|
||||
) : (
|
||||
<StyledHeading showText={showText} size="large">
|
||||
{isTabletView ? (
|
||||
<ReactSVG
|
||||
className="logo-icon_svg"
|
||||
src="/static/images/logo.docspace.react.svg"
|
||||
onClick={onLogoClick}
|
||||
/>
|
||||
) : (
|
||||
<Link to="/">
|
||||
isSvgLogo ? (
|
||||
<ReactSVG
|
||||
className="logo-icon_svg"
|
||||
src="/static/images/logo.docspace.react.svg"
|
||||
src={whiteLabelLogoUrls[0]}
|
||||
onClick={onLogoClick}
|
||||
/>
|
||||
) : (
|
||||
<img
|
||||
className="logo-icon_svg"
|
||||
src={whiteLabelLogoUrls[0]}
|
||||
onClick={onLogoClick}
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
<Link to="/">
|
||||
{isSvgLogo ? (
|
||||
<ReactSVG
|
||||
className="logo-icon_svg"
|
||||
src={whiteLabelLogoUrls[0]}
|
||||
onClick={onLogoClick}
|
||||
/>
|
||||
) : (
|
||||
<img className="logo-icon_svg" src={whiteLabelLogoUrls[0]} />
|
||||
)}
|
||||
</Link>
|
||||
)}
|
||||
</StyledHeading>
|
||||
@ -70,8 +86,9 @@ ArticleHeader.displayName = "Header";
|
||||
|
||||
export default inject(({ auth }) => {
|
||||
const { settingsStore } = auth;
|
||||
const { isBurgerLoading } = settingsStore;
|
||||
const { isBurgerLoading, whiteLabelLogoUrls } = settingsStore;
|
||||
return {
|
||||
isBurgerLoading,
|
||||
whiteLabelLogoUrls,
|
||||
};
|
||||
})(observer(ArticleHeader));
|
||||
|
@ -6,6 +6,16 @@ import { combineUrl } from "@docspace/common/utils";
|
||||
import { AppServerConfig } from "@docspace/common/constants";
|
||||
import config from "PACKAGE_FILE";
|
||||
import Filter from "../api/people/filter";
|
||||
import { getRoomInfo } from "../api/rooms";
|
||||
|
||||
const observedKeys = [
|
||||
"id",
|
||||
"title",
|
||||
"thumbnailStatus",
|
||||
"thumbnailUrl",
|
||||
"version",
|
||||
"comment",
|
||||
];
|
||||
|
||||
class InfoPanelStore {
|
||||
isVisible = false;
|
||||
@ -19,6 +29,7 @@ class InfoPanelStore {
|
||||
authStore = null;
|
||||
settingsStore = null;
|
||||
peopleStore = null;
|
||||
filesStore = null;
|
||||
selectedFolderStore = null;
|
||||
treeFoldersStore = null;
|
||||
|
||||
@ -26,9 +37,19 @@ class InfoPanelStore {
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
|
||||
// Setters
|
||||
|
||||
setIsVisible = (bool) => (this.isVisible = bool);
|
||||
|
||||
setSelection = (selection) => (this.selection = selection);
|
||||
setSelection = (selection) => {
|
||||
if (this.getIsAccounts() && (!selection.email || !selection.displayName)) {
|
||||
this.selection = selection.length
|
||||
? selection
|
||||
: { isSelectedFolder: true };
|
||||
return;
|
||||
}
|
||||
this.selection = selection;
|
||||
};
|
||||
setSelectionParentRoom = (obj) => (this.selectionParentRoom = obj);
|
||||
|
||||
setView = (view) => {
|
||||
@ -36,18 +57,109 @@ class InfoPanelStore {
|
||||
this.fileView = view === "members" ? "history" : view;
|
||||
};
|
||||
|
||||
// Selection helpers //
|
||||
|
||||
getSelectedItems = () => {
|
||||
const {
|
||||
selection: filesStoreSelection,
|
||||
bufferSelection: filesStoreBufferSelection,
|
||||
} = this.filesStore;
|
||||
|
||||
const {
|
||||
selection: peopleStoreSelection,
|
||||
bufferSelection: peopleStoreBufferSelection,
|
||||
} = this.peopleStore.selectionStore;
|
||||
|
||||
return this.getIsAccounts()
|
||||
? peopleStoreSelection.length
|
||||
? [...peopleStoreSelection]
|
||||
: peopleStoreBufferSelection
|
||||
? [peopleStoreBufferSelection]
|
||||
: []
|
||||
: filesStoreSelection?.length > 0
|
||||
? [...filesStoreSelection]
|
||||
: filesStoreBufferSelection
|
||||
? [filesStoreBufferSelection]
|
||||
: [];
|
||||
};
|
||||
|
||||
getSelectedFolder = () => {
|
||||
const selectedFolderStore = { ...this.selectedFolderStore };
|
||||
return {
|
||||
...selectedFolderStore,
|
||||
isFolder: true,
|
||||
isRoom: !!this.selectedFolderStore.roomType,
|
||||
};
|
||||
};
|
||||
|
||||
calculateSelection = (
|
||||
props = { selectedItems: [], selectedFolder: null }
|
||||
) => {
|
||||
const selectedItems = props.selectedItems.length
|
||||
? props.selectedItems
|
||||
: this.getSelectedItems();
|
||||
|
||||
const selectedFolder = props.selectedFolder
|
||||
? props.selectedFolder
|
||||
: this.getSelectedFolder();
|
||||
|
||||
return selectedItems.length === 0
|
||||
? this.normalizeSelection({
|
||||
...selectedFolder,
|
||||
isSelectedFolder: true,
|
||||
isSelectedItem: false,
|
||||
})
|
||||
: selectedItems.length === 1
|
||||
? this.normalizeSelection({
|
||||
...selectedItems[0],
|
||||
isSelectedFolder: false,
|
||||
isSelectedItem: true,
|
||||
})
|
||||
: [...Array(selectedItems.length).keys()];
|
||||
};
|
||||
|
||||
normalizeSelection = (selection) => {
|
||||
const isContextMenuSelection = selection.isContextMenuSelection;
|
||||
return {
|
||||
...selection,
|
||||
isRoom: selection.isRoom || !!selection.roomType,
|
||||
icon: this.getItemIcon(selection, 32),
|
||||
icon: this.getInfoPanelItemIcon(selection, 32),
|
||||
isContextMenuSelection: false,
|
||||
wasContextMenuSelection: !!isContextMenuSelection,
|
||||
};
|
||||
};
|
||||
|
||||
getItemIcon = (item, size) => {
|
||||
reloadSelection = () => {
|
||||
this.setSelection(this.calculateSelection());
|
||||
};
|
||||
|
||||
reloadSelectionParentRoom = async () => {
|
||||
if (!this.getIsRooms) return;
|
||||
|
||||
const currentFolderRoomId = this.selectedFolderStore.pathParts[1];
|
||||
const prevRoomId = selectionParentRoom?.id;
|
||||
|
||||
if (!currentFolderRoomId || currentFolderRoomId === prevRoomId) return;
|
||||
|
||||
const newSelectionParentRoom = await getRoomInfo(currentFolderRoomId);
|
||||
if (prevRoomId === newSelectionParentRoom.id) return;
|
||||
|
||||
this.setSelectionParentRoom(
|
||||
this.normalizeSelection(newSelectionParentRoom)
|
||||
);
|
||||
};
|
||||
|
||||
isItemChanged = (oldItem, newItem) => {
|
||||
for (let i = 0; i < observedKeys.length; i++) {
|
||||
const value = observedKeys[i];
|
||||
if (oldItem[value] !== newItem[value]) return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// Icon helpers //
|
||||
|
||||
getInfoPanelItemIcon = (item, size) => {
|
||||
return item.isRoom || !!item.roomType
|
||||
? item.logo && item.logo.medium
|
||||
? item.logo.medium
|
||||
@ -59,6 +171,18 @@ class InfoPanelStore {
|
||||
: this.settingsStore.getIcon(size, item.fileExst || ".file");
|
||||
};
|
||||
|
||||
// User link actions //
|
||||
|
||||
openUser = async (user, history) => {
|
||||
if (user.id === this.authStore.userStore.user.id) {
|
||||
this.openSelfProfile(history);
|
||||
return;
|
||||
}
|
||||
|
||||
const fetchedUser = await this.fetchUser(user.id);
|
||||
this.openAccountsWithSelectedUser(fetchedUser, history);
|
||||
};
|
||||
|
||||
openSelfProfile = (history) => {
|
||||
const path = [
|
||||
AppServerConfig.proxyURL,
|
||||
@ -73,21 +197,20 @@ class InfoPanelStore {
|
||||
|
||||
openAccountsWithSelectedUser = async (user, history) => {
|
||||
const { getUsersList } = this.peopleStore.usersStore;
|
||||
const { selectUser } = this.peopleStore.selectionStore;
|
||||
const { setSelection } = this.peopleStore.selectionStore;
|
||||
|
||||
const path = [AppServerConfig.proxyURL, config.homepage, "/accounts"];
|
||||
|
||||
const newFilter = Filter.getDefault();
|
||||
newFilter.page = 0;
|
||||
newFilter.search = user.email;
|
||||
await getUsersList(newFilter);
|
||||
path.push(`filter?${newFilter.toUrlParams()}`);
|
||||
const userList = await getUsersList(newFilter);
|
||||
|
||||
history.push(combineUrl(...path));
|
||||
this.selectedFolderStore.setSelectedFolder(null);
|
||||
this.treeFoldersStore.setSelectedNode(["accounts"]);
|
||||
history.push(combineUrl(...path));
|
||||
|
||||
selectUser(user);
|
||||
setSelection([user]);
|
||||
};
|
||||
|
||||
fetchUser = async (userId) => {
|
||||
@ -109,18 +232,15 @@ class InfoPanelStore {
|
||||
return fetchedUser;
|
||||
};
|
||||
|
||||
openUser = async (userId, history) => {
|
||||
if (userId === this.authStore.userStore.user.id) {
|
||||
this.openSelfProfile(history);
|
||||
return;
|
||||
}
|
||||
// Routing helpers //
|
||||
|
||||
const fetchedUser = await this.fetchUser(userId);
|
||||
this.openAccountsWithSelectedUser(fetchedUser, history);
|
||||
};
|
||||
|
||||
getItemNoThumbnail = (item) => {
|
||||
this.getItemIcon(item, 96);
|
||||
getCanDisplay = () => {
|
||||
const pathname = window.location.pathname.toLowerCase();
|
||||
const isFiles = this.getIsFiles(pathname);
|
||||
const isRooms = this.getIsRooms(pathname);
|
||||
const isAccounts = this.getIsAccounts(pathname);
|
||||
const isGallery = this.getIsGallery(pathname);
|
||||
return isRooms || isFiles || isGallery || isAccounts;
|
||||
};
|
||||
|
||||
getIsFiles = (givenPathName) => {
|
||||
@ -148,15 +268,6 @@ class InfoPanelStore {
|
||||
const pathname = givenPathName || window.location.pathname.toLowerCase();
|
||||
return pathname.indexOf("form-gallery") !== -1;
|
||||
};
|
||||
|
||||
getCanDisplay = () => {
|
||||
const pathname = window.location.pathname.toLowerCase();
|
||||
const isFiles = this.getIsFiles(pathname);
|
||||
const isRooms = this.getIsRooms(pathname);
|
||||
const isAccounts = this.getIsAccounts(pathname);
|
||||
const isGallery = this.getIsGallery(pathname);
|
||||
return isRooms || isFiles || isGallery || isAccounts;
|
||||
};
|
||||
}
|
||||
|
||||
export default InfoPanelStore;
|
||||
|
@ -70,7 +70,7 @@ class SettingsStore {
|
||||
urlSupport = "https://helpdesk.onlyoffice.com/";
|
||||
urlOforms = "https://cmsoforms.onlyoffice.com/api/oforms";
|
||||
|
||||
logoUrl = combineUrl(proxyURL, "/static/images/logo.docspace.react.svg");
|
||||
logoUrl = "";
|
||||
customNames = {
|
||||
id: "Common",
|
||||
userCaption: "User",
|
||||
@ -388,7 +388,11 @@ class SettingsStore {
|
||||
};
|
||||
|
||||
setDocSpaceLogo = (urls) => {
|
||||
this.docSpaceLogo = urls[1];
|
||||
this.docSpaceLogo = urls[6];
|
||||
};
|
||||
|
||||
setLogoUrl = (url) => {
|
||||
this.logoUrl = url[0];
|
||||
};
|
||||
|
||||
setLogoUrls = (urls) => {
|
||||
@ -407,6 +411,7 @@ class SettingsStore {
|
||||
|
||||
this.setLogoUrls(Object.values(res));
|
||||
this.setDocSpaceLogo(Object.values(res));
|
||||
this.setLogoUrl(Object.values(res));
|
||||
};
|
||||
|
||||
restoreCompanyInfoSettings = async () => {
|
||||
|
@ -16,6 +16,7 @@ const StyledLabel = styled.label`
|
||||
.checkbox {
|
||||
margin-right: 12px;
|
||||
overflow: visible;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* ${(props) =>
|
||||
|
@ -23,10 +23,10 @@ const StyledWrapper = styled.div`
|
||||
@media ${hugeMobile} {
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
box-shadow: none !important;
|
||||
max-width: 343px;
|
||||
min-width: 343px;
|
||||
background: transparent;
|
||||
background: transparent !important;
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -52,6 +52,7 @@ class SaveCancelButtons extends React.Component {
|
||||
isSaving,
|
||||
cancelEnable,
|
||||
tabIndex,
|
||||
saveButtonDisabled,
|
||||
} = this.props;
|
||||
|
||||
const cancelButtonDisabled = cancelEnable
|
||||
@ -76,7 +77,7 @@ class SaveCancelButtons extends React.Component {
|
||||
tabIndex={tabIndexSaveButton}
|
||||
className="save-button"
|
||||
size="normal"
|
||||
isDisabled={!showReminder}
|
||||
isDisabled={!showReminder || saveButtonDisabled}
|
||||
primary
|
||||
onClick={onSaveClick}
|
||||
label={saveButtonLabel}
|
||||
|
@ -2027,6 +2027,8 @@ const Base = {
|
||||
|
||||
members: {
|
||||
iconColor: "#A3A9AE",
|
||||
iconHoverColor: "#657077",
|
||||
isExpectName: "#A3A9AE",
|
||||
subtitleColor: "#a3a9ae",
|
||||
meLabelColor: "#a3a9ae",
|
||||
roleSelectorColor: "#a3a9ae",
|
||||
@ -2877,7 +2879,7 @@ const Base = {
|
||||
whiteLabel: {
|
||||
borderImg: "1px solid #d1d1d1",
|
||||
|
||||
backgroundColor: "#0f4071",
|
||||
backgroundColor: "#ECEEF1",
|
||||
greenBackgroundColor: "#7e983f",
|
||||
blueBackgroundColor: "#5170b5",
|
||||
orangeBackgroundColor: "#e86e2e",
|
||||
|
@ -2023,6 +2023,8 @@ const Dark = {
|
||||
|
||||
members: {
|
||||
iconColor: "#A3A9AE",
|
||||
iconHoverColor: "#ffffff",
|
||||
isExpectName: "#A3A9AE",
|
||||
subtitleColor: "#a3a9ae",
|
||||
meLabelColor: "#a3a9ae",
|
||||
roleSelectorColor: "#a3a9ae",
|
||||
@ -2883,13 +2885,13 @@ const Dark = {
|
||||
whiteLabel: {
|
||||
borderImg: "1px solid #d1d1d1",
|
||||
|
||||
backgroundColor: "#0f4071",
|
||||
backgroundColor: "#282828",
|
||||
greenBackgroundColor: "#7e983f",
|
||||
blueBackgroundColor: "#5170b5",
|
||||
orangeBackgroundColor: "#e86e2e",
|
||||
|
||||
dataFontColor: white,
|
||||
dataFontColorBlack: black,
|
||||
dataFontColorBlack: white,
|
||||
},
|
||||
},
|
||||
|
||||
|
1
packages/login/index.d.ts
vendored
1
packages/login/index.d.ts
vendored
@ -97,6 +97,7 @@ declare global {
|
||||
match: MatchType;
|
||||
currentColorScheme: ITheme;
|
||||
isAuth: boolean;
|
||||
logoUrls: any;
|
||||
}
|
||||
|
||||
interface DevRequest {
|
||||
|
@ -2,7 +2,6 @@ import React, { useEffect, useState, useCallback } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { ButtonsWrapper, LoginFormWrapper } from "./StyledLogin";
|
||||
import Logo from "../../../../../public/images/docspace.big.react.svg";
|
||||
import Text from "@docspace/components/text";
|
||||
import SocialButton from "@docspace/components/social-button";
|
||||
import {
|
||||
@ -24,6 +23,7 @@ import SSOIcon from "../../../../../public/images/sso.react.svg";
|
||||
import { Dark, Base } from "@docspace/components/themes";
|
||||
import { useMounted } from "../helpers/useMounted";
|
||||
import { getBgPattern } from "@docspace/common/utils";
|
||||
import { ReactSVG } from "react-svg";
|
||||
|
||||
interface ILoginProps extends IInitialState {
|
||||
isDesktopEditor?: boolean;
|
||||
@ -38,6 +38,7 @@ const Login: React.FC<ILoginProps> = ({
|
||||
currentColorScheme,
|
||||
theme,
|
||||
setTheme,
|
||||
logoUrls,
|
||||
}) => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [moreAuthVisible, setMoreAuthVisible] = useState(false);
|
||||
@ -174,6 +175,9 @@ const Login: React.FC<ILoginProps> = ({
|
||||
|
||||
const bgPattern = getBgPattern(currentColorScheme.id);
|
||||
|
||||
const loginLogo = Object.values(logoUrls)[1];
|
||||
const isSvgLogo = loginLogo.includes(".svg");
|
||||
|
||||
if (!mounted) return <></>;
|
||||
|
||||
return (
|
||||
@ -185,7 +189,11 @@ const Login: React.FC<ILoginProps> = ({
|
||||
bgPattern={bgPattern}
|
||||
>
|
||||
<ColorTheme themeId={ThemeType.LinkForgotPassword} theme={theme}>
|
||||
<Logo className="logo-wrapper" />
|
||||
{isSvgLogo ? (
|
||||
<ReactSVG src={loginLogo} className="logo-wrapper" />
|
||||
) : (
|
||||
<img src={loginLogo} className="logo-wrapper" />
|
||||
)}
|
||||
<Text
|
||||
fontSize="23px"
|
||||
fontWeight={700}
|
||||
|
@ -238,10 +238,12 @@ export const LoginContainer = styled.div`
|
||||
height: 46px;
|
||||
padding-bottom: 64px;
|
||||
|
||||
path:last-child {
|
||||
fill: ${(props) => props.theme.client.home.logoColor};
|
||||
svg {
|
||||
path:last-child {
|
||||
fill: ${(props) => props.theme.client.home.logoColor};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media ${hugeMobile} {
|
||||
display: none;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
getAuthProviders,
|
||||
getCapabilities,
|
||||
getAppearanceTheme,
|
||||
getLogoUrls
|
||||
} from "@docspace/common/api/settings";
|
||||
import { checkIsAuthenticated } from "@docspace/common/api/user";
|
||||
|
||||
@ -57,7 +58,8 @@ export const getInitialState = async (
|
||||
providers: ProvidersType,
|
||||
capabilities: ICapabilities,
|
||||
availableThemes: IThemes,
|
||||
isAuth: any;
|
||||
isAuth: any,
|
||||
logoUrls: any;
|
||||
|
||||
[
|
||||
portalSettings,
|
||||
@ -66,13 +68,15 @@ export const getInitialState = async (
|
||||
capabilities,
|
||||
availableThemes,
|
||||
isAuth,
|
||||
logoUrls
|
||||
] = await Promise.all([
|
||||
getSettings(),
|
||||
getBuildVersion(),
|
||||
getAuthProviders(),
|
||||
getCapabilities(),
|
||||
getAppearanceTheme(),
|
||||
checkIsAuthenticated()
|
||||
checkIsAuthenticated(),
|
||||
getLogoUrls()
|
||||
]);
|
||||
|
||||
const currentColorScheme = availableThemes.themes.find((theme) => {
|
||||
@ -86,7 +90,8 @@ export const getInitialState = async (
|
||||
capabilities,
|
||||
match: query,
|
||||
currentColorScheme,
|
||||
isAuth
|
||||
isAuth,
|
||||
logoUrls
|
||||
};
|
||||
|
||||
return initialState;
|
||||
|
Loading…
Reference in New Issue
Block a user